1 /* $OpenBSD: vga_pci.c,v 1.15 2003/10/31 04:10:05 drahn Exp $ */ 2 /* $NetBSD: vga_pci.c,v 1.3 1998/06/08 06:55:58 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.c,v 1.12 2001/05/19 01:28:07 alfred Exp $ 30 */ 31 /* 32 * Copyright (c) 2001 Wasabi Systems, Inc. 33 * All rights reserved. 34 * 35 * Written by Frank van der Linden for Wasabi Systems, Inc. 36 * 37 * Redistribution and use in source and binary forms, with or without 38 * modification, are permitted provided that the following conditions 39 * are met: 40 * 1. Redistributions of source code must retain the above copyright 41 * notice, this list of conditions and the following disclaimer. 42 * 2. Redistributions in binary form must reproduce the above copyright 43 * notice, this list of conditions and the following disclaimer in the 44 * documentation and/or other materials provided with the distribution. 45 * 3. All advertising materials mentioning features or use of this software 46 * must display the following acknowledgement: 47 * This product includes software developed for the NetBSD Project by 48 * Wasabi Systems, Inc. 49 * 4. The name of Wasabi Systems, Inc. may not be used to endorse 50 * or promote products derived from this software without specific prior 51 * written permission. 52 * 53 * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND 54 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 55 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 56 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC 57 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 58 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 59 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 60 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 61 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 62 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 63 * POSSIBILITY OF SUCH DAMAGE. 64 */ 65 /* 66 * Copyright (c) 1995, 1996 Carnegie-Mellon University. 67 * All rights reserved. 68 * 69 * Author: Chris G. Demetriou 70 * 71 * Permission to use, copy, modify and distribute this software and 72 * its documentation is hereby granted, provided that both the copyright 73 * notice and this permission notice appear in all copies of the 74 * software, derivative works or modified versions, and any portions 75 * thereof, and that both notices appear in supporting documentation. 76 * 77 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" 78 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND 79 * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 80 * 81 * Carnegie Mellon requests users of this software to return to 82 * 83 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU 84 * School of Computer Science 85 * Carnegie Mellon University 86 * Pittsburgh PA 15213-3890 87 * 88 * any improvements or extensions that they make and grant Carnegie the 89 * rights to redistribute these changes. 90 */ 91 92 #include "vga.h" 93 94 #include <sys/param.h> 95 #include <sys/systm.h> 96 #include <sys/kernel.h> 97 #include <sys/device.h> 98 #include <sys/malloc.h> 99 #include <sys/agpio.h> 100 101 #include <uvm/uvm.h> 102 103 #include <machine/bus.h> 104 105 #include <dev/pci/pcireg.h> 106 #include <dev/pci/pcivar.h> 107 #include <dev/pci/pcidevs.h> 108 109 #include <dev/ic/mc6845reg.h> 110 #include <dev/ic/pcdisplayvar.h> 111 #include <dev/ic/vgareg.h> 112 #include <dev/ic/vgavar.h> 113 #include <dev/pci/vga_pcivar.h> 114 115 #ifdef PCIAGP 116 #include <sys/fcntl.h> 117 118 #include <dev/pci/agpvar.h> 119 #include <dev/pci/agpreg.h> 120 #endif 121 122 #include <dev/wscons/wsconsio.h> 123 #include <dev/wscons/wsdisplayvar.h> 124 125 int vga_pci_match(struct device *, void *, void *); 126 void vga_pci_attach(struct device *, struct device *, void *); 127 paddr_t vga_pci_mmap(void* v, off_t off, int prot); 128 129 struct cfattach vga_pci_ca = { 130 sizeof(struct vga_pci_softc), vga_pci_match, vga_pci_attach, 131 }; 132 133 #ifdef PCIAGP 134 struct agp_memory *agp_find_memory(struct vga_pci_softc *sc, int id); 135 const struct agp_product *agp_lookup(struct pci_attach_args *pa); 136 137 struct pci_attach_args agp_pchb_pa; 138 int agp_pchb_pa_set = 0; 139 #endif 140 141 int 142 vga_pci_match(parent, match, aux) 143 struct device *parent; 144 void *match; 145 void *aux; 146 { 147 struct pci_attach_args *pa = aux; 148 int potential; 149 150 potential = 0; 151 152 /* 153 * If it's prehistoric/vga or display/vga, we might match. 154 * For the console device, this is jut a sanity check. 155 */ 156 if (PCI_CLASS(pa->pa_class) == PCI_CLASS_PREHISTORIC && 157 PCI_SUBCLASS(pa->pa_class) == PCI_SUBCLASS_PREHISTORIC_VGA) 158 potential = 1; 159 if (PCI_CLASS(pa->pa_class) == PCI_CLASS_DISPLAY && 160 PCI_SUBCLASS(pa->pa_class) == PCI_SUBCLASS_DISPLAY_VGA) 161 potential = 1; 162 163 if (!potential) 164 return (0); 165 166 /* check whether it is disabled by firmware */ 167 if ((pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG) 168 & (PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MEM_ENABLE)) 169 != (PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MEM_ENABLE)) 170 return (0); 171 172 /* If it's the console, we have a winner! */ 173 if (vga_is_console(pa->pa_iot, WSDISPLAY_TYPE_PCIVGA)) 174 return (1); 175 176 /* 177 * If we might match, make sure that the card actually looks OK. 178 */ 179 #ifdef ISA_SPACE_NOT_ACCESSABLE_WITH_PCI_IOT 180 if (!vga_common_probe(MD_ISA_IOT, MD_ISA_MEMT)) 181 return (0); 182 #else 183 if (!vga_common_probe(pa->pa_iot, pa->pa_memt)) 184 return (0); 185 #endif 186 187 return (1); 188 } 189 190 void 191 vga_pci_attach(parent, self, aux) 192 struct device *parent, *self; 193 void *aux; 194 { 195 #ifndef ISA_SPACE_NOT_ACCESSABLE_WITH_PCI_IOT 196 struct pci_attach_args *pa = aux; 197 #endif 198 #ifdef PCIAGP 199 struct vga_pci_softc *sc = (struct vga_pci_softc *)self; 200 const struct agp_product *ap; 201 u_int memsize; 202 int i, ret; 203 #endif 204 205 #ifdef PCIAGP 206 ap = agp_lookup(pa); 207 if (ap) { 208 static const int agp_max[][2] = { 209 {0, 0}, 210 {32, 4}, 211 {64, 28}, 212 {128, 96}, 213 {256, 204}, 214 {512, 440}, 215 {1024, 942}, 216 {2048, 1920}, 217 {4096, 3932} 218 }; 219 #define agp_max_size (sizeof(agp_max)/sizeof(agp_max[0])) 220 221 /* 222 * Work out an upper bound for agp memory allocation. This 223 * uses a heurisitc table from the Linux driver. 224 */ 225 memsize = ptoa(physmem) >> 20; 226 227 for (i = 0; i < agp_max_size && memsize > agp_max[i][0]; i++) 228 ; 229 if (i == agp_max_size) 230 i = agp_max_size - 1; 231 sc->sc_maxmem = agp_max[i][1] << 20; 232 233 /* 234 * The lock is used to prevent re-entry to 235 * agp_generic_bind_memory() since that function can sleep. 236 */ 237 238 lockinit(&sc->sc_lock, PZERO|PCATCH, "agplk", 0, 0); 239 240 TAILQ_INIT(&sc->sc_memory); 241 242 sc->sc_pcitag = pa->pa_tag; 243 sc->sc_pc = pa->pa_pc; 244 sc->sc_id = pa->pa_id; 245 sc->sc_dmat = pa->pa_dmat; 246 247 pci_get_capability(sc->sc_pc, sc->sc_pcitag, PCI_CAP_AGP, 248 &sc->sc_capoff, NULL); 249 250 ret = (*ap->ap_attach)(sc, pa, &agp_pchb_pa); 251 if (ret == 0) 252 printf(": aperture at 0x%lx, size 0x%lx", 253 (u_long)sc->sc_apaddr, 254 (u_long)AGP_GET_APERTURE(sc)); 255 else { 256 sc->sc_chipc = NULL; 257 printf(": AGP GART"); 258 } 259 } 260 #endif 261 printf("\n"); 262 #ifdef ISA_SPACE_NOT_ACCESSABLE_WITH_PCI_IOT 263 vga_extended_attach(self, MD_ISA_IOT, ppc_isa_membus_space, 264 WSDISPLAY_TYPE_PCIVGA, vga_pci_mmap); 265 #else 266 vga_common_attach(self, pa->pa_iot, pa->pa_memt, 267 WSDISPLAY_TYPE_PCIVGA); 268 #endif 269 } 270 271 paddr_t 272 vga_pci_mmap(void *v, off_t off, int prot) 273 { 274 #ifdef PCIAGP 275 struct vga_config* vs = (struct vga_config*) v; 276 struct vga_pci_softc* sc = (struct vga_pci_softc *)vs->vc_softc; 277 278 if (sc->sc_apaddr) { 279 280 if (off > AGP_GET_APERTURE(sc)) 281 return (-1); 282 283 #ifdef __i386__ 284 return i386_btop(sc->sc_apaddr + off); 285 #endif 286 } 287 #endif 288 #ifdef __pegasos__ 289 /* XXX */ 290 return off; 291 #endif 292 return -1; 293 } 294 295 int 296 vga_pci_cnattach(iot, memt, pc, bus, device, function) 297 bus_space_tag_t iot, memt; 298 pci_chipset_tag_t pc; 299 int bus, device, function; 300 { 301 return (vga_cnattach(iot, memt, WSDISPLAY_TYPE_PCIVGA, 0)); 302 } 303 304 int 305 vga_pci_ioctl(v, cmd, addr, flag, p) 306 void *v; 307 u_long cmd; 308 caddr_t addr; 309 int flag; 310 struct proc *p; 311 { 312 int error = 0; 313 #ifdef PCIAGP 314 struct vga_config *vc = v; 315 struct vga_pci_softc *sc = (struct vga_pci_softc *)vc->vc_softc; 316 struct agp_memory *mem; 317 agp_info *info; 318 agp_setup *setup; 319 agp_allocate *alloc; 320 agp_bind *bind; 321 agp_unbind *unbind; 322 vsize_t size; 323 324 switch (cmd) { 325 case AGPIOC_INFO: 326 if (!sc->sc_chipc) 327 return (ENXIO); 328 case AGPIOC_ACQUIRE: 329 case AGPIOC_RELEASE: 330 case AGPIOC_SETUP: 331 case AGPIOC_ALLOCATE: 332 case AGPIOC_DEALLOCATE: 333 case AGPIOC_BIND: 334 case AGPIOC_UNBIND: 335 if (cmd != AGPIOC_INFO && !(flag & FWRITE)) 336 return (EPERM); 337 break; 338 } 339 #endif 340 341 switch (cmd) { 342 #ifdef PCIAGP 343 case AGPIOC_INFO: 344 info = (agp_info *)addr; 345 bzero(info, sizeof *info); 346 info->bridge_id = sc->sc_id; 347 if (sc->sc_capoff != 0) 348 info->agp_mode = pci_conf_read(sc->sc_pc, sc->sc_pcitag, 349 AGP_STATUS + sc->sc_capoff); 350 else 351 info->agp_mode = 0; /* i810 doesn't have real AGP */ 352 info->aper_base = sc->sc_apaddr; 353 info->aper_size = AGP_GET_APERTURE(sc) >> 20; 354 info->pg_total = 355 info->pg_system = sc->sc_maxmem >> AGP_PAGE_SHIFT; 356 info->pg_used = sc->sc_allocated >> AGP_PAGE_SHIFT; 357 break; 358 359 case AGPIOC_ACQUIRE: 360 if (sc->sc_state != AGP_ACQUIRE_FREE) 361 error = EBUSY; 362 else 363 sc->sc_state = AGP_ACQUIRE_USER; 364 break; 365 366 case AGPIOC_RELEASE: 367 if (sc->sc_state == AGP_ACQUIRE_FREE) 368 break; 369 370 if (sc->sc_state != AGP_ACQUIRE_USER) { 371 error = EBUSY; 372 break; 373 } 374 375 /* 376 * Clear out the aperture and free any 377 * outstanding memory blocks. 378 */ 379 TAILQ_FOREACH(mem, &sc->sc_memory, am_link) { 380 if (mem->am_is_bound) { 381 printf("agp_release_helper: mem %d is bound\n", 382 mem->am_id); 383 AGP_UNBIND_MEMORY(sc, mem); 384 } 385 } 386 sc->sc_state = AGP_ACQUIRE_FREE; 387 break; 388 389 case AGPIOC_SETUP: 390 setup = (agp_setup *)addr; 391 error = AGP_ENABLE(sc, setup->agp_mode); 392 break; 393 394 case AGPIOC_ALLOCATE: 395 alloc = (agp_allocate *)addr; 396 size = alloc->pg_count << AGP_PAGE_SHIFT; 397 if (sc->sc_allocated + size > sc->sc_maxmem) 398 error = EINVAL; 399 else { 400 mem = AGP_ALLOC_MEMORY(sc, alloc->type, size); 401 if (mem) { 402 alloc->key = mem->am_id; 403 alloc->physical = mem->am_physical; 404 } else 405 error = ENOMEM; 406 } 407 break; 408 409 case AGPIOC_DEALLOCATE: 410 mem = agp_find_memory(sc, *(int *)addr); 411 if (mem) 412 AGP_FREE_MEMORY(sc, mem); 413 else 414 error = ENOENT; 415 break; 416 417 case AGPIOC_BIND: 418 bind = (agp_bind *)addr; 419 mem = agp_find_memory(sc, bind->key); 420 if (!mem) 421 error = ENOENT; 422 else 423 error = AGP_BIND_MEMORY(sc, mem, 424 bind->pg_start << AGP_PAGE_SHIFT); 425 break; 426 427 case AGPIOC_UNBIND: 428 unbind = (agp_unbind *)addr; 429 mem = agp_find_memory(sc, unbind->key); 430 if (!mem) 431 error = ENOENT; 432 else 433 error = AGP_UNBIND_MEMORY(sc, mem); 434 break; 435 #endif /* PCIAGP */ 436 437 default: 438 error = ENOTTY; 439 } 440 441 return (error); 442 } 443 444 #ifdef PCIAGP 445 struct agp_memory * 446 agp_find_memory(struct vga_pci_softc *sc, int id) 447 { 448 struct agp_memory *mem; 449 450 AGP_DPF("searching for memory block %d\n", id); 451 TAILQ_FOREACH(mem, &sc->sc_memory, am_link) { 452 AGP_DPF("considering memory block %d\n", mem->am_id); 453 if (mem->am_id == id) 454 return (mem); 455 } 456 return 0; 457 } 458 459 const struct agp_product * 460 agp_lookup(struct pci_attach_args *pa) 461 { 462 const struct agp_product *ap; 463 464 if (!agp_pchb_pa_set) 465 return (NULL); 466 agp_pchb_pa_set = 0; 467 468 /* First find the vendor. */ 469 for (ap = agp_products; ap->ap_attach != NULL; ap++) 470 if (ap->ap_vendor == PCI_VENDOR(pa->pa_id)) 471 break; 472 473 if (ap->ap_attach == NULL) 474 return (NULL); 475 476 /* Now find the product within the vendor's domain. */ 477 for (; ap->ap_attach != NULL; ap++) { 478 /* Ran out of this vendor's section of the table. */ 479 if (ap->ap_vendor != PCI_VENDOR(pa->pa_id)) 480 return (NULL); 481 482 if (ap->ap_product == PCI_PRODUCT(pa->pa_id)) 483 break; /* Exact match. */ 484 if (ap->ap_product == (u_int32_t) -1) 485 break; /* Wildcard match. */ 486 } 487 488 if (ap->ap_attach == NULL) 489 ap = NULL; 490 491 return (ap); 492 } 493 494 void 495 pciagp_set_pchb(struct pci_attach_args *pa) 496 { 497 if (!agp_pchb_pa_set) { 498 memcpy(&agp_pchb_pa, pa, sizeof *pa); 499 agp_pchb_pa_set++; 500 } 501 } 502 503 int 504 agp_map_aperture(struct vga_pci_softc *sc) 505 { 506 /* 507 * Find and the aperture. Don't map it (yet), this would 508 * eat KVA. 509 */ 510 if (pci_mapreg_info(sc->sc_pc, sc->sc_pcitag, AGP_APBASE, 511 PCI_MAPREG_TYPE_MEM, &sc->sc_apaddr, &sc->sc_apsize, 512 &sc->sc_apflags) != 0) 513 return ENXIO; 514 515 return 0; 516 } 517 518 struct agp_gatt * 519 agp_alloc_gatt(struct vga_pci_softc *sc) 520 { 521 u_int32_t apsize = AGP_GET_APERTURE(sc); 522 u_int32_t entries = apsize >> AGP_PAGE_SHIFT; 523 struct agp_gatt *gatt; 524 int nseg; 525 526 gatt = malloc(sizeof(*gatt), M_DEVBUF, M_NOWAIT); 527 if (!gatt) 528 return (NULL); 529 bzero(gatt, sizeof(*gatt)); 530 gatt->ag_entries = entries; 531 532 if (agp_alloc_dmamem(sc->sc_dmat, entries * sizeof(u_int32_t), 533 0, &gatt->ag_dmamap, (caddr_t *)&gatt->ag_virtual, 534 &gatt->ag_physical, &gatt->ag_dmaseg, 1, &nseg) != 0) 535 return NULL; 536 537 gatt->ag_size = entries * sizeof(u_int32_t); 538 memset(gatt->ag_virtual, 0, gatt->ag_size); 539 agp_flush_cache(); 540 541 return gatt; 542 } 543 544 void 545 agp_free_gatt(struct vga_pci_softc *sc, struct agp_gatt *gatt) 546 { 547 agp_free_dmamem(sc->sc_dmat, gatt->ag_size, gatt->ag_dmamap, 548 (caddr_t)gatt->ag_virtual, &gatt->ag_dmaseg, 1); 549 free(gatt, M_DEVBUF); 550 } 551 552 int 553 agp_generic_detach(struct vga_pci_softc *sc) 554 { 555 lockmgr(&sc->sc_lock, LK_DRAIN, NULL, curproc); 556 agp_flush_cache(); 557 return 0; 558 } 559 560 int 561 agp_generic_enable(struct vga_pci_softc *sc, u_int32_t mode) 562 { 563 pcireg_t tstatus, mstatus; 564 pcireg_t command; 565 int rq, sba, fw, rate, capoff; 566 567 if (pci_get_capability(sc->sc_pc, sc->sc_pcitag, PCI_CAP_AGP, 568 &capoff, NULL) == 0) { 569 printf("agp_generic_enable: not an AGP capable device\n"); 570 return -1; 571 } 572 573 tstatus = pci_conf_read(sc->sc_pc, sc->sc_pcitag, 574 sc->sc_capoff + AGP_STATUS); 575 mstatus = pci_conf_read(sc->sc_pc, sc->sc_pcitag, 576 capoff + AGP_STATUS); 577 578 /* Set RQ to the min of mode, tstatus and mstatus */ 579 rq = AGP_MODE_GET_RQ(mode); 580 if (AGP_MODE_GET_RQ(tstatus) < rq) 581 rq = AGP_MODE_GET_RQ(tstatus); 582 if (AGP_MODE_GET_RQ(mstatus) < rq) 583 rq = AGP_MODE_GET_RQ(mstatus); 584 585 /* Set SBA if all three can deal with SBA */ 586 sba = (AGP_MODE_GET_SBA(tstatus) 587 & AGP_MODE_GET_SBA(mstatus) 588 & AGP_MODE_GET_SBA(mode)); 589 590 /* Similar for FW */ 591 fw = (AGP_MODE_GET_FW(tstatus) 592 & AGP_MODE_GET_FW(mstatus) 593 & AGP_MODE_GET_FW(mode)); 594 595 /* Figure out the max rate */ 596 rate = (AGP_MODE_GET_RATE(tstatus) 597 & AGP_MODE_GET_RATE(mstatus) 598 & AGP_MODE_GET_RATE(mode)); 599 if (rate & AGP_MODE_RATE_4x) 600 rate = AGP_MODE_RATE_4x; 601 else if (rate & AGP_MODE_RATE_2x) 602 rate = AGP_MODE_RATE_2x; 603 else 604 rate = AGP_MODE_RATE_1x; 605 606 /* Construct the new mode word and tell the hardware */ 607 command = AGP_MODE_SET_RQ(0, rq); 608 command = AGP_MODE_SET_SBA(command, sba); 609 command = AGP_MODE_SET_FW(command, fw); 610 command = AGP_MODE_SET_RATE(command, rate); 611 command = AGP_MODE_SET_AGP(command, 1); 612 pci_conf_write(sc->sc_pc, sc->sc_pcitag, 613 sc->sc_capoff + AGP_COMMAND, command); 614 pci_conf_write(sc->sc_pc, sc->sc_pcitag, capoff + AGP_COMMAND, command); 615 return 0; 616 } 617 618 struct agp_memory * 619 agp_generic_alloc_memory(struct vga_pci_softc *sc, int type, vsize_t size) 620 { 621 struct agp_memory *mem; 622 623 if (type != 0) { 624 printf("agp_generic_alloc_memory: unsupported type %d\n", type); 625 return 0; 626 } 627 628 mem = malloc(sizeof *mem, M_DEVBUF, M_WAITOK); 629 if (mem == NULL) 630 return NULL; 631 632 if (bus_dmamap_create(sc->sc_dmat, size, size / PAGE_SIZE + 1, 633 size, 0, BUS_DMA_NOWAIT, &mem->am_dmamap) != 0) { 634 free(mem, M_DEVBUF); 635 return NULL; 636 } 637 638 mem->am_id = sc->sc_nextid++; 639 mem->am_size = size; 640 mem->am_type = 0; 641 mem->am_physical = 0; 642 mem->am_offset = 0; 643 mem->am_is_bound = 0; 644 TAILQ_INSERT_TAIL(&sc->sc_memory, mem, am_link); 645 sc->sc_allocated += size; 646 647 return mem; 648 } 649 650 int 651 agp_generic_free_memory(struct vga_pci_softc *sc, struct agp_memory *mem) 652 { 653 if (mem->am_is_bound) 654 return EBUSY; 655 656 sc->sc_allocated -= mem->am_size; 657 TAILQ_REMOVE(&sc->sc_memory, mem, am_link); 658 bus_dmamap_destroy(sc->sc_dmat, mem->am_dmamap); 659 free(mem, M_DEVBUF); 660 return 0; 661 } 662 663 int 664 agp_generic_bind_memory(struct vga_pci_softc *sc, struct agp_memory *mem, 665 off_t offset) 666 { 667 bus_dma_segment_t *segs, *seg; 668 bus_size_t done, j; 669 bus_addr_t pa; 670 off_t i, k; 671 int contigpages, nseg, error; 672 673 lockmgr(&sc->sc_lock, LK_EXCLUSIVE, NULL, curproc); 674 675 if (mem->am_is_bound) { 676 printf("AGP: memory already bound\n"); 677 lockmgr(&sc->sc_lock, LK_RELEASE, NULL, curproc); 678 return EINVAL; 679 } 680 681 if (offset < 0 682 || (offset & (AGP_PAGE_SIZE - 1)) != 0 683 || offset + mem->am_size > AGP_GET_APERTURE(sc)) { 684 printf("AGP: binding memory at bad offset %#lx\n", 685 (unsigned long) offset); 686 lockmgr(&sc->sc_lock, LK_RELEASE, NULL, curproc); 687 return EINVAL; 688 } 689 690 /* 691 * XXXfvdl 692 * The memory here needs to be directly accessable from the 693 * AGP video card, so it should be allocated using bus_dma. 694 * However, it need not be contiguous, since individual pages 695 * are translated using the GATT. 696 * 697 * Using a large chunk of contiguous memory may get in the way 698 * of other subsystems that may need one, so we try to be friendly 699 * and ask for allocation in chunks of a minimum of 8 pages 700 * of contiguous memory on average, falling back to 4, 2 and 1 701 * if really needed. Larger chunks are preferred, since allocating 702 * a bus_dma_segment per page would be overkill. 703 */ 704 705 for (contigpages = 32; contigpages > 0; contigpages >>= 1) { 706 nseg = (mem->am_size / (contigpages * PAGE_SIZE)) + 1; 707 segs = malloc(nseg * sizeof *segs, M_DEVBUF, M_WAITOK); 708 if (segs == NULL) 709 return ENOMEM; 710 if ((error = bus_dmamem_alloc(sc->sc_dmat, mem->am_size, PAGE_SIZE, 0, 711 segs, nseg, &mem->am_nseg, BUS_DMA_WAITOK)) != 0) { 712 free(segs, M_DEVBUF); 713 AGP_DPF("bus_dmamem_alloc failed %d\n", error); 714 continue; 715 } 716 if ((error = bus_dmamem_map(sc->sc_dmat, segs, mem->am_nseg, 717 mem->am_size, &mem->am_virtual, BUS_DMA_WAITOK)) != 0) { 718 bus_dmamem_free(sc->sc_dmat, segs, mem->am_nseg); 719 free(segs, M_DEVBUF); 720 AGP_DPF("bus_dmamem_map failed %d\n", error); 721 continue; 722 } 723 if ((error = bus_dmamap_load(sc->sc_dmat, mem->am_dmamap, 724 mem->am_virtual, mem->am_size, NULL, 725 BUS_DMA_WAITOK)) != 0) { 726 bus_dmamem_unmap(sc->sc_dmat, mem->am_virtual, 727 mem->am_size); 728 bus_dmamem_free(sc->sc_dmat, segs, mem->am_nseg); 729 free(segs, M_DEVBUF); 730 AGP_DPF("bus_dmamap_load failed %d\n", error); 731 continue; 732 } 733 mem->am_dmaseg = segs; 734 break; 735 } 736 737 if (contigpages == 0) { 738 lockmgr(&sc->sc_lock, LK_RELEASE, NULL, curproc); 739 return ENOMEM; 740 } 741 742 /* 743 * Bind the individual pages and flush the chipset's 744 * TLB. 745 */ 746 done = 0; 747 for (i = 0; i < mem->am_dmamap->dm_nsegs; i++) { 748 seg = &mem->am_dmamap->dm_segs[i]; 749 /* 750 * Install entries in the GATT, making sure that if 751 * AGP_PAGE_SIZE < PAGE_SIZE and mem->am_size is not 752 * aligned to PAGE_SIZE, we don't modify too many GATT 753 * entries. 754 */ 755 for (j = 0; j < seg->ds_len && (done + j) < mem->am_size; 756 j += AGP_PAGE_SIZE) { 757 pa = seg->ds_addr + j; 758 AGP_DPF("binding offset %#lx to pa %#lx\n", 759 (unsigned long)(offset + done + j), 760 (unsigned long)pa); 761 error = AGP_BIND_PAGE(sc, offset + done + j, pa); 762 if (error) { 763 /* 764 * Bail out. Reverse all the mappings 765 * and unwire the pages. 766 */ 767 for (k = 0; k < done + j; k += AGP_PAGE_SIZE) 768 AGP_UNBIND_PAGE(sc, offset + k); 769 770 bus_dmamap_unload(sc->sc_dmat, mem->am_dmamap); 771 bus_dmamem_unmap(sc->sc_dmat, mem->am_virtual, 772 mem->am_size); 773 bus_dmamem_free(sc->sc_dmat, mem->am_dmaseg, 774 mem->am_nseg); 775 free(mem->am_dmaseg, M_DEVBUF); 776 lockmgr(&sc->sc_lock, LK_RELEASE, NULL, curproc); 777 return error; 778 } 779 } 780 done += seg->ds_len; 781 } 782 783 /* 784 * Flush the cpu cache since we are providing a new mapping 785 * for these pages. 786 */ 787 agp_flush_cache(); 788 789 /* 790 * Make sure the chipset gets the new mappings. 791 */ 792 AGP_FLUSH_TLB(sc); 793 794 mem->am_offset = offset; 795 mem->am_is_bound = 1; 796 797 lockmgr(&sc->sc_lock, LK_RELEASE, NULL, curproc); 798 799 return 0; 800 } 801 802 int 803 agp_generic_unbind_memory(struct vga_pci_softc *sc, struct agp_memory *mem) 804 { 805 int i; 806 807 lockmgr(&sc->sc_lock, LK_EXCLUSIVE, NULL, curproc); 808 809 if (!mem->am_is_bound) { 810 printf("AGP: memory is not bound\n"); 811 lockmgr(&sc->sc_lock, LK_RELEASE, NULL, curproc); 812 return EINVAL; 813 } 814 815 816 /* 817 * Unbind the individual pages and flush the chipset's 818 * TLB. Unwire the pages so they can be swapped. 819 */ 820 for (i = 0; i < mem->am_size; i += AGP_PAGE_SIZE) 821 AGP_UNBIND_PAGE(sc, mem->am_offset + i); 822 823 agp_flush_cache(); 824 AGP_FLUSH_TLB(sc); 825 826 bus_dmamap_unload(sc->sc_dmat, mem->am_dmamap); 827 bus_dmamem_unmap(sc->sc_dmat, mem->am_virtual, mem->am_size); 828 bus_dmamem_free(sc->sc_dmat, mem->am_dmaseg, mem->am_nseg); 829 830 free(mem->am_dmaseg, M_DEVBUF); 831 832 mem->am_offset = 0; 833 mem->am_is_bound = 0; 834 835 lockmgr(&sc->sc_lock, LK_RELEASE, NULL, curproc); 836 837 return 0; 838 } 839 840 int 841 agp_alloc_dmamem(bus_dma_tag_t tag, size_t size, int flags, 842 bus_dmamap_t *mapp, caddr_t *vaddr, bus_addr_t *baddr, 843 bus_dma_segment_t *seg, int nseg, int *rseg) 844 845 { 846 int error, level = 0; 847 848 if ((error = bus_dmamem_alloc(tag, size, PAGE_SIZE, 0, 849 seg, nseg, rseg, BUS_DMA_NOWAIT)) != 0) 850 goto out; 851 level++; 852 853 if ((error = bus_dmamem_map(tag, seg, *rseg, size, vaddr, 854 BUS_DMA_NOWAIT | flags)) != 0) 855 goto out; 856 level++; 857 858 if ((error = bus_dmamap_create(tag, size, *rseg, size, 0, 859 BUS_DMA_NOWAIT, mapp)) != 0) 860 goto out; 861 level++; 862 863 if ((error = bus_dmamap_load(tag, *mapp, *vaddr, size, NULL, 864 BUS_DMA_NOWAIT)) != 0) 865 goto out; 866 867 *baddr = (*mapp)->dm_segs[0].ds_addr; 868 869 return 0; 870 out: 871 switch (level) { 872 case 3: 873 bus_dmamap_destroy(tag, *mapp); 874 /* FALLTHROUGH */ 875 case 2: 876 bus_dmamem_unmap(tag, *vaddr, size); 877 /* FALLTHROUGH */ 878 case 1: 879 bus_dmamem_free(tag, seg, *rseg); 880 break; 881 default: 882 break; 883 } 884 885 return error; 886 } 887 888 void 889 agp_free_dmamem(bus_dma_tag_t tag, size_t size, bus_dmamap_t map, 890 caddr_t vaddr, bus_dma_segment_t *seg, int nseg) 891 { 892 893 bus_dmamap_unload(tag, map); 894 bus_dmamap_destroy(tag, map); 895 bus_dmamem_unmap(tag, vaddr, size); 896 bus_dmamem_free(tag, seg, nseg); 897 } 898 #endif 899