1 /* $OpenBSD: agp.c,v 1.49 2015/12/22 21:05:37 kettenis Exp $ */ 2 /*- 3 * Copyright (c) 2000 Doug Rabson 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 * 27 * $FreeBSD: src/sys/pci/agp.c,v 1.12 2001/05/19 01:28:07 alfred Exp $ 28 */ 29 30 #include <sys/param.h> 31 #include <sys/systm.h> 32 #include <sys/malloc.h> 33 34 #include <uvm/uvm_extern.h> 35 36 #include <dev/pci/pcivar.h> 37 #include <dev/pci/pcidevs.h> 38 39 #include <dev/ic/mc6845reg.h> 40 #include <dev/ic/pcdisplayvar.h> 41 #include <dev/ic/vgareg.h> 42 #include <dev/ic/vgavar.h> 43 44 #include <dev/pci/agpvar.h> 45 #include <dev/pci/agpreg.h> 46 47 void agp_attach(struct device *, struct device *, void *); 48 int agp_probe(struct device *, void *, void *); 49 50 int agpvga_match(struct pci_attach_args *); 51 52 int 53 agpdev_print(void *aux, const char *pnp) 54 { 55 if (pnp) { 56 printf("agp at %s", pnp); 57 } 58 return (UNCONF); 59 } 60 61 int 62 agpbus_probe(struct agp_attach_args *aa) 63 { 64 struct pci_attach_args *pa = aa->aa_pa; 65 66 if (strncmp(aa->aa_busname, "agp", 3) == 0 && 67 PCI_CLASS(pa->pa_class) == PCI_CLASS_BRIDGE && 68 PCI_SUBCLASS(pa->pa_class) == PCI_SUBCLASS_BRIDGE_HOST) 69 return (1); 70 return (0); 71 } 72 73 /* 74 * Find the video card hanging off the agp bus XXX assumes only one bus 75 */ 76 int 77 agpvga_match(struct pci_attach_args *pa) 78 { 79 if (PCI_CLASS(pa->pa_class) == PCI_CLASS_DISPLAY && 80 PCI_SUBCLASS(pa->pa_class) == PCI_SUBCLASS_DISPLAY_VGA) { 81 if (pci_get_capability(pa->pa_pc, pa->pa_tag, PCI_CAP_AGP, 82 NULL, NULL)) 83 return (1); 84 } 85 return (0); 86 } 87 88 struct device * 89 agp_attach_bus(struct pci_attach_args *pa, const struct agp_methods *methods, 90 bus_addr_t apaddr, bus_size_t apsize, struct device *dev) 91 { 92 struct agpbus_attach_args arg; 93 94 arg.aa_methods = methods; 95 arg.aa_pa = pa; 96 arg.aa_apaddr = apaddr; 97 arg.aa_apsize = apsize; 98 99 printf("\n"); /* newline from the driver that called us */ 100 return (config_found(dev, &arg, agpdev_print)); 101 } 102 103 int 104 agp_probe(struct device *parent, void *match, void *aux) 105 { 106 /* 107 * we don't do any checking here, driver we're attaching this 108 * interface to should have already done it. 109 */ 110 return (1); 111 } 112 113 void 114 agp_attach(struct device *parent, struct device *self, void *aux) 115 { 116 struct agpbus_attach_args *aa = aux; 117 struct pci_attach_args *pa = aa->aa_pa; 118 struct agp_softc *sc = (struct agp_softc *)self; 119 u_int memsize; 120 int i; 121 122 sc->sc_chipc = parent; 123 sc->sc_methods = aa->aa_methods; 124 sc->sc_apaddr = aa->aa_apaddr; 125 sc->sc_apsize = aa->aa_apsize; 126 127 static const int agp_max[][2] = { 128 {0, 0}, 129 {32, 4}, 130 {64, 28}, 131 {128, 96}, 132 {256, 204}, 133 {512, 440}, 134 {1024, 942}, 135 {2048, 1920}, 136 {4096, 3932} 137 }; 138 139 /* 140 * Work out an upper bound for agp memory allocation. This 141 * uses a heuristic table from the Linux driver. 142 */ 143 memsize = ptoa(physmem) >> 20; 144 145 for (i = 0; i < nitems(agp_max) && memsize > agp_max[i][0]; i++) 146 ; 147 if (i == nitems(agp_max)) 148 i = nitems(agp_max) - 1; 149 sc->sc_maxmem = agp_max[i][1] << 20; 150 151 sc->sc_pcitag = pa->pa_tag; 152 sc->sc_pc = pa->pa_pc; 153 sc->sc_id = pa->pa_id; 154 sc->sc_dmat = pa->pa_dmat; 155 sc->sc_memt = pa->pa_memt; 156 157 pci_get_capability(sc->sc_pc, sc->sc_pcitag, PCI_CAP_AGP, 158 &sc->sc_capoff, NULL); 159 160 printf(": aperture at 0x%lx, size 0x%lx\n", (u_long)sc->sc_apaddr, 161 (u_long)sc->sc_apsize); 162 } 163 164 struct cfattach agp_ca = { 165 sizeof(struct agp_softc), agp_probe, agp_attach, 166 NULL, NULL 167 }; 168 169 struct cfdriver agp_cd = { 170 NULL, "agp", DV_DULL 171 }; 172 173 struct agp_gatt * 174 agp_alloc_gatt(bus_dma_tag_t dmat, u_int32_t apsize) 175 { 176 struct agp_gatt *gatt; 177 u_int32_t entries = apsize >> AGP_PAGE_SHIFT; 178 179 gatt = malloc(sizeof(*gatt), M_AGP, M_NOWAIT | M_ZERO); 180 if (!gatt) 181 return (NULL); 182 gatt->ag_entries = entries; 183 gatt->ag_size = entries * sizeof(u_int32_t); 184 185 if (agp_alloc_dmamem(dmat, gatt->ag_size, &gatt->ag_dmamap, 186 &gatt->ag_physical, &gatt->ag_dmaseg) != 0) { 187 free(gatt, M_AGP, sizeof *gatt); 188 return (NULL); 189 } 190 191 if (bus_dmamem_map(dmat, &gatt->ag_dmaseg, 1, gatt->ag_size, 192 (caddr_t *)&gatt->ag_virtual, BUS_DMA_NOWAIT) != 0) { 193 agp_free_dmamem(dmat, gatt->ag_size, gatt->ag_dmamap, 194 &gatt->ag_dmaseg); 195 free(gatt, M_AGP, sizeof *gatt); 196 return (NULL); 197 } 198 199 agp_flush_cache(); 200 201 return (gatt); 202 } 203 204 void 205 agp_free_gatt(bus_dma_tag_t dmat, struct agp_gatt *gatt) 206 { 207 bus_dmamem_unmap(dmat, (caddr_t)gatt->ag_virtual, gatt->ag_size); 208 agp_free_dmamem(dmat, gatt->ag_size, gatt->ag_dmamap, &gatt->ag_dmaseg); 209 free(gatt, M_AGP, sizeof *gatt); 210 } 211 212 int 213 agp_generic_enable(struct agp_softc *sc, u_int32_t mode) 214 { 215 struct pci_attach_args pa; 216 pcireg_t tstatus, mstatus, command; 217 int rq, sba, fw, rate, capoff; 218 219 if (pci_find_device(&pa, agpvga_match) == 0 || 220 pci_get_capability(pa.pa_pc, pa.pa_tag, PCI_CAP_AGP, 221 &capoff, NULL) == 0) { 222 printf("agp_generic_enable: not an AGP capable device\n"); 223 return (-1); 224 } 225 226 tstatus = pci_conf_read(sc->sc_pc, sc->sc_pcitag, 227 sc->sc_capoff + AGP_STATUS); 228 /* display agp mode */ 229 mstatus = pci_conf_read(pa.pa_pc, pa.pa_tag, 230 capoff + AGP_STATUS); 231 232 /* Set RQ to the min of mode, tstatus and mstatus */ 233 rq = AGP_MODE_GET_RQ(mode); 234 if (AGP_MODE_GET_RQ(tstatus) < rq) 235 rq = AGP_MODE_GET_RQ(tstatus); 236 if (AGP_MODE_GET_RQ(mstatus) < rq) 237 rq = AGP_MODE_GET_RQ(mstatus); 238 239 /* Set SBA if all three can deal with SBA */ 240 sba = (AGP_MODE_GET_SBA(tstatus) 241 & AGP_MODE_GET_SBA(mstatus) 242 & AGP_MODE_GET_SBA(mode)); 243 244 /* Similar for FW */ 245 fw = (AGP_MODE_GET_FW(tstatus) 246 & AGP_MODE_GET_FW(mstatus) 247 & AGP_MODE_GET_FW(mode)); 248 249 /* Figure out the max rate */ 250 rate = (AGP_MODE_GET_RATE(tstatus) 251 & AGP_MODE_GET_RATE(mstatus) 252 & AGP_MODE_GET_RATE(mode)); 253 if (rate & AGP_MODE_RATE_4x) 254 rate = AGP_MODE_RATE_4x; 255 else if (rate & AGP_MODE_RATE_2x) 256 rate = AGP_MODE_RATE_2x; 257 else 258 rate = AGP_MODE_RATE_1x; 259 260 /* Construct the new mode word and tell the hardware */ 261 command = AGP_MODE_SET_RQ(0, rq); 262 command = AGP_MODE_SET_SBA(command, sba); 263 command = AGP_MODE_SET_FW(command, fw); 264 command = AGP_MODE_SET_RATE(command, rate); 265 command = AGP_MODE_SET_AGP(command, 1); 266 267 pci_conf_write(sc->sc_pc, sc->sc_pcitag, 268 sc->sc_capoff + AGP_COMMAND, command); 269 pci_conf_write(pa.pa_pc, pa.pa_tag, capoff + AGP_COMMAND, command); 270 return (0); 271 } 272 273 /* 274 * Allocates a single-segment block of zeroed, wired dma memory. 275 */ 276 int 277 agp_alloc_dmamem(bus_dma_tag_t tag, size_t size, bus_dmamap_t *mapp, 278 bus_addr_t *baddr, bus_dma_segment_t *seg) 279 { 280 int error, level = 0, nseg; 281 282 if ((error = bus_dmamem_alloc(tag, size, PAGE_SIZE, 0, 283 seg, 1, &nseg, BUS_DMA_NOWAIT | BUS_DMA_ZERO)) != 0) 284 goto out; 285 level++; 286 287 if ((error = bus_dmamap_create(tag, size, nseg, size, 0, 288 BUS_DMA_NOWAIT, mapp)) != 0) 289 goto out; 290 level++; 291 292 if ((error = bus_dmamap_load_raw(tag, *mapp, seg, nseg, size, 293 BUS_DMA_NOWAIT)) != 0) 294 goto out; 295 296 *baddr = (*mapp)->dm_segs[0].ds_addr; 297 298 return (0); 299 out: 300 switch (level) { 301 case 2: 302 bus_dmamap_destroy(tag, *mapp); 303 /* FALLTHROUGH */ 304 case 1: 305 bus_dmamem_free(tag, seg, nseg); 306 break; 307 default: 308 break; 309 } 310 311 return (error); 312 } 313 314 void 315 agp_free_dmamem(bus_dma_tag_t tag, size_t size, bus_dmamap_t map, 316 bus_dma_segment_t *seg) 317 { 318 bus_dmamap_unload(tag, map); 319 bus_dmamap_destroy(tag, map); 320 bus_dmamem_free(tag, seg, 1); 321 } 322 323 /* Implementation of the kernel api */ 324 325 void * 326 agp_find_device(int unit) 327 { 328 if (unit >= agp_cd.cd_ndevs || unit < 0) 329 return (NULL); 330 return (agp_cd.cd_devs[unit]); 331 } 332 333 enum agp_acquire_state 334 agp_state(void *dev) 335 { 336 struct agp_softc *sc = (struct agp_softc *) dev; 337 return (sc->sc_state); 338 } 339 340 void 341 agp_get_info(void *dev, struct agp_info *info) 342 { 343 struct agp_softc *sc = (struct agp_softc *)dev; 344 345 if (sc->sc_capoff != 0) 346 info->ai_mode = pci_conf_read(sc->sc_pc, sc->sc_pcitag, 347 AGP_STATUS + sc->sc_capoff); 348 else 349 info->ai_mode = 0; /* i810 doesn't have real AGP */ 350 info->ai_aperture_base = sc->sc_apaddr; 351 info->ai_aperture_size = sc->sc_apsize; 352 info->ai_memory_allowed = sc->sc_maxmem; 353 info->ai_memory_used = sc->sc_allocated; 354 info->ai_devid = sc->sc_id; 355 } 356 357 int 358 agp_acquire(void *dev) 359 { 360 struct agp_softc *sc = (struct agp_softc *)dev; 361 362 if (sc->sc_chipc == NULL) 363 return (EINVAL); 364 365 if (sc->sc_state != AGP_ACQUIRE_FREE) 366 return (EBUSY); 367 sc->sc_state = AGP_ACQUIRE_KERNEL; 368 369 return (0); 370 } 371 372 int 373 agp_release(void *dev) 374 { 375 struct agp_softc *sc = (struct agp_softc *)dev; 376 377 if (sc->sc_state == AGP_ACQUIRE_FREE) 378 return (0); 379 380 if (sc->sc_state != AGP_ACQUIRE_KERNEL) 381 return (EBUSY); 382 383 sc->sc_state = AGP_ACQUIRE_FREE; 384 return (0); 385 } 386 387 int 388 agp_enable(void *dev, u_int32_t mode) 389 { 390 struct agp_softc *sc = dev; 391 int ret; 392 393 if (sc->sc_methods->enable != NULL) { 394 ret = sc->sc_methods->enable(sc->sc_chipc, mode); 395 } else { 396 ret = agp_generic_enable(sc, mode); 397 } 398 return (ret); 399 } 400 401 paddr_t 402 agp_mmap(struct agp_softc *sc, off_t off, int prot) 403 { 404 if (sc->sc_chipc == NULL) 405 return (-1); 406 407 if (off >= sc->sc_apsize) 408 return (-1); 409 410 if (sc->sc_apaddr == 0) 411 return (-1); 412 413 return bus_space_mmap(sc->sc_memt, sc->sc_apaddr, off, prot, 0); 414 } 415