1 /* $OpenBSD: vga_pci.c,v 1.14 2002/07/15 13:23:48 mickey 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 if (!vga_common_probe(pa->pa_iot, pa->pa_memt)) 180 return (0); 181 182 return (1); 183 } 184 185 void 186 vga_pci_attach(parent, self, aux) 187 struct device *parent, *self; 188 void *aux; 189 { 190 struct pci_attach_args *pa = aux; 191 #ifdef PCIAGP 192 struct vga_pci_softc *sc = (struct vga_pci_softc *)self; 193 const struct agp_product *ap; 194 u_int memsize; 195 int i, ret; 196 #endif 197 198 #ifdef PCIAGP 199 ap = agp_lookup(pa); 200 if (ap) { 201 static const int agp_max[][2] = { 202 {0, 0}, 203 {32, 4}, 204 {64, 28}, 205 {128, 96}, 206 {256, 204}, 207 {512, 440}, 208 {1024, 942}, 209 {2048, 1920}, 210 {4096, 3932} 211 }; 212 #define agp_max_size (sizeof(agp_max)/sizeof(agp_max[0])) 213 214 /* 215 * Work out an upper bound for agp memory allocation. This 216 * uses a heurisitc table from the Linux driver. 217 */ 218 memsize = ptoa(physmem) >> 20; 219 220 for (i = 0; i < agp_max_size && memsize > agp_max[i][0]; i++) 221 ; 222 if (i == agp_max_size) 223 i = agp_max_size - 1; 224 sc->sc_maxmem = agp_max[i][1] << 20; 225 226 /* 227 * The lock is used to prevent re-entry to 228 * agp_generic_bind_memory() since that function can sleep. 229 */ 230 231 lockinit(&sc->sc_lock, PZERO|PCATCH, "agplk", 0, 0); 232 233 TAILQ_INIT(&sc->sc_memory); 234 235 sc->sc_pcitag = pa->pa_tag; 236 sc->sc_pc = pa->pa_pc; 237 sc->sc_id = pa->pa_id; 238 sc->sc_dmat = pa->pa_dmat; 239 240 pci_get_capability(sc->sc_pc, sc->sc_pcitag, PCI_CAP_AGP, 241 &sc->sc_capoff, NULL); 242 243 ret = (*ap->ap_attach)(sc, pa, &agp_pchb_pa); 244 if (ret == 0) 245 printf(": aperture at 0x%lx, size 0x%lx", 246 (u_long)sc->sc_apaddr, 247 (u_long)AGP_GET_APERTURE(sc)); 248 else { 249 sc->sc_chipc = NULL; 250 printf(": AGP GART"); 251 } 252 } 253 #endif 254 printf("\n"); 255 vga_common_attach(self, pa->pa_iot, pa->pa_memt, 256 WSDISPLAY_TYPE_PCIVGA); 257 } 258 259 paddr_t 260 vga_pci_mmap(void *v, off_t off, int prot) 261 { 262 #ifdef PCIAGP 263 struct vga_config* vs = (struct vga_config*) v; 264 struct vga_pci_softc* sc = (struct vga_pci_softc *)vs->vc_softc; 265 266 if (sc->sc_apaddr) { 267 268 if (off > AGP_GET_APERTURE(sc)) 269 return (-1); 270 271 #ifdef __i386__ 272 return i386_btop(sc->sc_apaddr + off); 273 #endif 274 } 275 #endif 276 return -1; 277 } 278 279 int 280 vga_pci_cnattach(iot, memt, pc, bus, device, function) 281 bus_space_tag_t iot, memt; 282 pci_chipset_tag_t pc; 283 int bus, device, function; 284 { 285 return (vga_cnattach(iot, memt, WSDISPLAY_TYPE_PCIVGA, 0)); 286 } 287 288 int 289 vga_pci_ioctl(v, cmd, addr, flag, p) 290 void *v; 291 u_long cmd; 292 caddr_t addr; 293 int flag; 294 struct proc *p; 295 { 296 int error = 0; 297 #ifdef PCIAGP 298 struct vga_config *vc = v; 299 struct vga_pci_softc *sc = (struct vga_pci_softc *)vc->vc_softc; 300 struct agp_memory *mem; 301 agp_info *info; 302 agp_setup *setup; 303 agp_allocate *alloc; 304 agp_bind *bind; 305 agp_unbind *unbind; 306 vsize_t size; 307 308 switch (cmd) { 309 case AGPIOC_INFO: 310 if (!sc->sc_chipc) 311 return (ENXIO); 312 case AGPIOC_ACQUIRE: 313 case AGPIOC_RELEASE: 314 case AGPIOC_SETUP: 315 case AGPIOC_ALLOCATE: 316 case AGPIOC_DEALLOCATE: 317 case AGPIOC_BIND: 318 case AGPIOC_UNBIND: 319 if (cmd != AGPIOC_INFO && !(flag & FWRITE)) 320 return (EPERM); 321 break; 322 } 323 #endif 324 325 switch (cmd) { 326 #ifdef PCIAGP 327 case AGPIOC_INFO: 328 info = (agp_info *)addr; 329 bzero(info, sizeof *info); 330 info->bridge_id = sc->sc_id; 331 if (sc->sc_capoff != 0) 332 info->agp_mode = pci_conf_read(sc->sc_pc, sc->sc_pcitag, 333 AGP_STATUS + sc->sc_capoff); 334 else 335 info->agp_mode = 0; /* i810 doesn't have real AGP */ 336 info->aper_base = sc->sc_apaddr; 337 info->aper_size = AGP_GET_APERTURE(sc) >> 20; 338 info->pg_total = 339 info->pg_system = sc->sc_maxmem >> AGP_PAGE_SHIFT; 340 info->pg_used = sc->sc_allocated >> AGP_PAGE_SHIFT; 341 break; 342 343 case AGPIOC_ACQUIRE: 344 if (sc->sc_state != AGP_ACQUIRE_FREE) 345 error = EBUSY; 346 else 347 sc->sc_state = AGP_ACQUIRE_USER; 348 break; 349 350 case AGPIOC_RELEASE: 351 if (sc->sc_state == AGP_ACQUIRE_FREE) 352 break; 353 354 if (sc->sc_state != AGP_ACQUIRE_USER) { 355 error = EBUSY; 356 break; 357 } 358 359 /* 360 * Clear out the aperture and free any 361 * outstanding memory blocks. 362 */ 363 TAILQ_FOREACH(mem, &sc->sc_memory, am_link) { 364 if (mem->am_is_bound) { 365 printf("agp_release_helper: mem %d is bound\n", 366 mem->am_id); 367 AGP_UNBIND_MEMORY(sc, mem); 368 } 369 } 370 sc->sc_state = AGP_ACQUIRE_FREE; 371 break; 372 373 case AGPIOC_SETUP: 374 setup = (agp_setup *)addr; 375 error = AGP_ENABLE(sc, setup->agp_mode); 376 break; 377 378 case AGPIOC_ALLOCATE: 379 alloc = (agp_allocate *)addr; 380 size = alloc->pg_count << AGP_PAGE_SHIFT; 381 if (sc->sc_allocated + size > sc->sc_maxmem) 382 error = EINVAL; 383 else { 384 mem = AGP_ALLOC_MEMORY(sc, alloc->type, size); 385 if (mem) { 386 alloc->key = mem->am_id; 387 alloc->physical = mem->am_physical; 388 } else 389 error = ENOMEM; 390 } 391 break; 392 393 case AGPIOC_DEALLOCATE: 394 mem = agp_find_memory(sc, *(int *)addr); 395 if (mem) 396 AGP_FREE_MEMORY(sc, mem); 397 else 398 error = ENOENT; 399 break; 400 401 case AGPIOC_BIND: 402 bind = (agp_bind *)addr; 403 mem = agp_find_memory(sc, bind->key); 404 if (!mem) 405 error = ENOENT; 406 else 407 error = AGP_BIND_MEMORY(sc, mem, 408 bind->pg_start << AGP_PAGE_SHIFT); 409 break; 410 411 case AGPIOC_UNBIND: 412 unbind = (agp_unbind *)addr; 413 mem = agp_find_memory(sc, unbind->key); 414 if (!mem) 415 error = ENOENT; 416 else 417 error = AGP_UNBIND_MEMORY(sc, mem); 418 break; 419 #endif /* PCIAGP */ 420 421 default: 422 error = ENOTTY; 423 } 424 425 return (error); 426 } 427 428 #ifdef PCIAGP 429 struct agp_memory * 430 agp_find_memory(struct vga_pci_softc *sc, int id) 431 { 432 struct agp_memory *mem; 433 434 AGP_DPF("searching for memory block %d\n", id); 435 TAILQ_FOREACH(mem, &sc->sc_memory, am_link) { 436 AGP_DPF("considering memory block %d\n", mem->am_id); 437 if (mem->am_id == id) 438 return (mem); 439 } 440 return 0; 441 } 442 443 const struct agp_product * 444 agp_lookup(struct pci_attach_args *pa) 445 { 446 const struct agp_product *ap; 447 448 if (!agp_pchb_pa_set) 449 return (NULL); 450 agp_pchb_pa_set = 0; 451 452 /* First find the vendor. */ 453 for (ap = agp_products; ap->ap_attach != NULL; ap++) 454 if (ap->ap_vendor == PCI_VENDOR(pa->pa_id)) 455 break; 456 457 if (ap->ap_attach == NULL) 458 return (NULL); 459 460 /* Now find the product within the vendor's domain. */ 461 for (; ap->ap_attach != NULL; ap++) { 462 /* Ran out of this vendor's section of the table. */ 463 if (ap->ap_vendor != PCI_VENDOR(pa->pa_id)) 464 return (NULL); 465 466 if (ap->ap_product == PCI_PRODUCT(pa->pa_id)) 467 break; /* Exact match. */ 468 if (ap->ap_product == (u_int32_t) -1) 469 break; /* Wildcard match. */ 470 } 471 472 if (ap->ap_attach == NULL) 473 ap = NULL; 474 475 return (ap); 476 } 477 478 void 479 pciagp_set_pchb(struct pci_attach_args *pa) 480 { 481 if (!agp_pchb_pa_set) { 482 memcpy(&agp_pchb_pa, pa, sizeof *pa); 483 agp_pchb_pa_set++; 484 } 485 } 486 487 int 488 agp_map_aperture(struct vga_pci_softc *sc) 489 { 490 /* 491 * Find and the aperture. Don't map it (yet), this would 492 * eat KVA. 493 */ 494 if (pci_mapreg_info(sc->sc_pc, sc->sc_pcitag, AGP_APBASE, 495 PCI_MAPREG_TYPE_MEM, &sc->sc_apaddr, &sc->sc_apsize, 496 &sc->sc_apflags) != 0) 497 return ENXIO; 498 499 return 0; 500 } 501 502 struct agp_gatt * 503 agp_alloc_gatt(struct vga_pci_softc *sc) 504 { 505 u_int32_t apsize = AGP_GET_APERTURE(sc); 506 u_int32_t entries = apsize >> AGP_PAGE_SHIFT; 507 struct agp_gatt *gatt; 508 int nseg; 509 510 gatt = malloc(sizeof(*gatt), M_DEVBUF, M_NOWAIT); 511 if (!gatt) 512 return (NULL); 513 bzero(gatt, sizeof(*gatt)); 514 gatt->ag_entries = entries; 515 516 if (agp_alloc_dmamem(sc->sc_dmat, entries * sizeof(u_int32_t), 517 0, &gatt->ag_dmamap, (caddr_t *)&gatt->ag_virtual, 518 &gatt->ag_physical, &gatt->ag_dmaseg, 1, &nseg) != 0) 519 return NULL; 520 521 gatt->ag_size = entries * sizeof(u_int32_t); 522 memset(gatt->ag_virtual, 0, gatt->ag_size); 523 agp_flush_cache(); 524 525 return gatt; 526 } 527 528 void 529 agp_free_gatt(struct vga_pci_softc *sc, struct agp_gatt *gatt) 530 { 531 agp_free_dmamem(sc->sc_dmat, gatt->ag_size, gatt->ag_dmamap, 532 (caddr_t)gatt->ag_virtual, &gatt->ag_dmaseg, 1); 533 free(gatt, M_DEVBUF); 534 } 535 536 int 537 agp_generic_detach(struct vga_pci_softc *sc) 538 { 539 lockmgr(&sc->sc_lock, LK_DRAIN, NULL, curproc); 540 agp_flush_cache(); 541 return 0; 542 } 543 544 int 545 agp_generic_enable(struct vga_pci_softc *sc, u_int32_t mode) 546 { 547 pcireg_t tstatus, mstatus; 548 pcireg_t command; 549 int rq, sba, fw, rate, capoff; 550 551 if (pci_get_capability(sc->sc_pc, sc->sc_pcitag, PCI_CAP_AGP, 552 &capoff, NULL) == 0) { 553 printf("agp_generic_enable: not an AGP capable device\n"); 554 return -1; 555 } 556 557 tstatus = pci_conf_read(sc->sc_pc, sc->sc_pcitag, 558 sc->sc_capoff + AGP_STATUS); 559 mstatus = pci_conf_read(sc->sc_pc, sc->sc_pcitag, 560 capoff + AGP_STATUS); 561 562 /* Set RQ to the min of mode, tstatus and mstatus */ 563 rq = AGP_MODE_GET_RQ(mode); 564 if (AGP_MODE_GET_RQ(tstatus) < rq) 565 rq = AGP_MODE_GET_RQ(tstatus); 566 if (AGP_MODE_GET_RQ(mstatus) < rq) 567 rq = AGP_MODE_GET_RQ(mstatus); 568 569 /* Set SBA if all three can deal with SBA */ 570 sba = (AGP_MODE_GET_SBA(tstatus) 571 & AGP_MODE_GET_SBA(mstatus) 572 & AGP_MODE_GET_SBA(mode)); 573 574 /* Similar for FW */ 575 fw = (AGP_MODE_GET_FW(tstatus) 576 & AGP_MODE_GET_FW(mstatus) 577 & AGP_MODE_GET_FW(mode)); 578 579 /* Figure out the max rate */ 580 rate = (AGP_MODE_GET_RATE(tstatus) 581 & AGP_MODE_GET_RATE(mstatus) 582 & AGP_MODE_GET_RATE(mode)); 583 if (rate & AGP_MODE_RATE_4x) 584 rate = AGP_MODE_RATE_4x; 585 else if (rate & AGP_MODE_RATE_2x) 586 rate = AGP_MODE_RATE_2x; 587 else 588 rate = AGP_MODE_RATE_1x; 589 590 /* Construct the new mode word and tell the hardware */ 591 command = AGP_MODE_SET_RQ(0, rq); 592 command = AGP_MODE_SET_SBA(command, sba); 593 command = AGP_MODE_SET_FW(command, fw); 594 command = AGP_MODE_SET_RATE(command, rate); 595 command = AGP_MODE_SET_AGP(command, 1); 596 pci_conf_write(sc->sc_pc, sc->sc_pcitag, 597 sc->sc_capoff + AGP_COMMAND, command); 598 pci_conf_write(sc->sc_pc, sc->sc_pcitag, capoff + AGP_COMMAND, command); 599 return 0; 600 } 601 602 struct agp_memory * 603 agp_generic_alloc_memory(struct vga_pci_softc *sc, int type, vsize_t size) 604 { 605 struct agp_memory *mem; 606 607 if (type != 0) { 608 printf("agp_generic_alloc_memory: unsupported type %d\n", type); 609 return 0; 610 } 611 612 mem = malloc(sizeof *mem, M_DEVBUF, M_WAITOK); 613 if (mem == NULL) 614 return NULL; 615 616 if (bus_dmamap_create(sc->sc_dmat, size, size / PAGE_SIZE + 1, 617 size, 0, BUS_DMA_NOWAIT, &mem->am_dmamap) != 0) { 618 free(mem, M_DEVBUF); 619 return NULL; 620 } 621 622 mem->am_id = sc->sc_nextid++; 623 mem->am_size = size; 624 mem->am_type = 0; 625 mem->am_physical = 0; 626 mem->am_offset = 0; 627 mem->am_is_bound = 0; 628 TAILQ_INSERT_TAIL(&sc->sc_memory, mem, am_link); 629 sc->sc_allocated += size; 630 631 return mem; 632 } 633 634 int 635 agp_generic_free_memory(struct vga_pci_softc *sc, struct agp_memory *mem) 636 { 637 if (mem->am_is_bound) 638 return EBUSY; 639 640 sc->sc_allocated -= mem->am_size; 641 TAILQ_REMOVE(&sc->sc_memory, mem, am_link); 642 bus_dmamap_destroy(sc->sc_dmat, mem->am_dmamap); 643 free(mem, M_DEVBUF); 644 return 0; 645 } 646 647 int 648 agp_generic_bind_memory(struct vga_pci_softc *sc, struct agp_memory *mem, 649 off_t offset) 650 { 651 bus_dma_segment_t *segs, *seg; 652 bus_size_t done, j; 653 bus_addr_t pa; 654 off_t i, k; 655 int contigpages, nseg, error; 656 657 lockmgr(&sc->sc_lock, LK_EXCLUSIVE, NULL, curproc); 658 659 if (mem->am_is_bound) { 660 printf("AGP: memory already bound\n"); 661 lockmgr(&sc->sc_lock, LK_RELEASE, NULL, curproc); 662 return EINVAL; 663 } 664 665 if (offset < 0 666 || (offset & (AGP_PAGE_SIZE - 1)) != 0 667 || offset + mem->am_size > AGP_GET_APERTURE(sc)) { 668 printf("AGP: binding memory at bad offset %#lx\n", 669 (unsigned long) offset); 670 lockmgr(&sc->sc_lock, LK_RELEASE, NULL, curproc); 671 return EINVAL; 672 } 673 674 /* 675 * XXXfvdl 676 * The memory here needs to be directly accessable from the 677 * AGP video card, so it should be allocated using bus_dma. 678 * However, it need not be contiguous, since individual pages 679 * are translated using the GATT. 680 * 681 * Using a large chunk of contiguous memory may get in the way 682 * of other subsystems that may need one, so we try to be friendly 683 * and ask for allocation in chunks of a minimum of 8 pages 684 * of contiguous memory on average, falling back to 4, 2 and 1 685 * if really needed. Larger chunks are preferred, since allocating 686 * a bus_dma_segment per page would be overkill. 687 */ 688 689 for (contigpages = 32; contigpages > 0; contigpages >>= 1) { 690 nseg = (mem->am_size / (contigpages * PAGE_SIZE)) + 1; 691 segs = malloc(nseg * sizeof *segs, M_DEVBUF, M_WAITOK); 692 if (segs == NULL) 693 return ENOMEM; 694 if ((error = bus_dmamem_alloc(sc->sc_dmat, mem->am_size, PAGE_SIZE, 0, 695 segs, nseg, &mem->am_nseg, BUS_DMA_WAITOK)) != 0) { 696 free(segs, M_DEVBUF); 697 AGP_DPF("bus_dmamem_alloc failed %d\n", error); 698 continue; 699 } 700 if ((error = bus_dmamem_map(sc->sc_dmat, segs, mem->am_nseg, 701 mem->am_size, &mem->am_virtual, BUS_DMA_WAITOK)) != 0) { 702 bus_dmamem_free(sc->sc_dmat, segs, mem->am_nseg); 703 free(segs, M_DEVBUF); 704 AGP_DPF("bus_dmamem_map failed %d\n", error); 705 continue; 706 } 707 if ((error = bus_dmamap_load(sc->sc_dmat, mem->am_dmamap, 708 mem->am_virtual, mem->am_size, NULL, 709 BUS_DMA_WAITOK)) != 0) { 710 bus_dmamem_unmap(sc->sc_dmat, mem->am_virtual, 711 mem->am_size); 712 bus_dmamem_free(sc->sc_dmat, segs, mem->am_nseg); 713 free(segs, M_DEVBUF); 714 AGP_DPF("bus_dmamap_load failed %d\n", error); 715 continue; 716 } 717 mem->am_dmaseg = segs; 718 break; 719 } 720 721 if (contigpages == 0) { 722 lockmgr(&sc->sc_lock, LK_RELEASE, NULL, curproc); 723 return ENOMEM; 724 } 725 726 /* 727 * Bind the individual pages and flush the chipset's 728 * TLB. 729 */ 730 done = 0; 731 for (i = 0; i < mem->am_dmamap->dm_nsegs; i++) { 732 seg = &mem->am_dmamap->dm_segs[i]; 733 /* 734 * Install entries in the GATT, making sure that if 735 * AGP_PAGE_SIZE < PAGE_SIZE and mem->am_size is not 736 * aligned to PAGE_SIZE, we don't modify too many GATT 737 * entries. 738 */ 739 for (j = 0; j < seg->ds_len && (done + j) < mem->am_size; 740 j += AGP_PAGE_SIZE) { 741 pa = seg->ds_addr + j; 742 AGP_DPF("binding offset %#lx to pa %#lx\n", 743 (unsigned long)(offset + done + j), 744 (unsigned long)pa); 745 error = AGP_BIND_PAGE(sc, offset + done + j, pa); 746 if (error) { 747 /* 748 * Bail out. Reverse all the mappings 749 * and unwire the pages. 750 */ 751 for (k = 0; k < done + j; k += AGP_PAGE_SIZE) 752 AGP_UNBIND_PAGE(sc, offset + k); 753 754 bus_dmamap_unload(sc->sc_dmat, mem->am_dmamap); 755 bus_dmamem_unmap(sc->sc_dmat, mem->am_virtual, 756 mem->am_size); 757 bus_dmamem_free(sc->sc_dmat, mem->am_dmaseg, 758 mem->am_nseg); 759 free(mem->am_dmaseg, M_DEVBUF); 760 lockmgr(&sc->sc_lock, LK_RELEASE, NULL, curproc); 761 return error; 762 } 763 } 764 done += seg->ds_len; 765 } 766 767 /* 768 * Flush the cpu cache since we are providing a new mapping 769 * for these pages. 770 */ 771 agp_flush_cache(); 772 773 /* 774 * Make sure the chipset gets the new mappings. 775 */ 776 AGP_FLUSH_TLB(sc); 777 778 mem->am_offset = offset; 779 mem->am_is_bound = 1; 780 781 lockmgr(&sc->sc_lock, LK_RELEASE, NULL, curproc); 782 783 return 0; 784 } 785 786 int 787 agp_generic_unbind_memory(struct vga_pci_softc *sc, struct agp_memory *mem) 788 { 789 int i; 790 791 lockmgr(&sc->sc_lock, LK_EXCLUSIVE, NULL, curproc); 792 793 if (!mem->am_is_bound) { 794 printf("AGP: memory is not bound\n"); 795 lockmgr(&sc->sc_lock, LK_RELEASE, NULL, curproc); 796 return EINVAL; 797 } 798 799 800 /* 801 * Unbind the individual pages and flush the chipset's 802 * TLB. Unwire the pages so they can be swapped. 803 */ 804 for (i = 0; i < mem->am_size; i += AGP_PAGE_SIZE) 805 AGP_UNBIND_PAGE(sc, mem->am_offset + i); 806 807 agp_flush_cache(); 808 AGP_FLUSH_TLB(sc); 809 810 bus_dmamap_unload(sc->sc_dmat, mem->am_dmamap); 811 bus_dmamem_unmap(sc->sc_dmat, mem->am_virtual, mem->am_size); 812 bus_dmamem_free(sc->sc_dmat, mem->am_dmaseg, mem->am_nseg); 813 814 free(mem->am_dmaseg, M_DEVBUF); 815 816 mem->am_offset = 0; 817 mem->am_is_bound = 0; 818 819 lockmgr(&sc->sc_lock, LK_RELEASE, NULL, curproc); 820 821 return 0; 822 } 823 824 int 825 agp_alloc_dmamem(bus_dma_tag_t tag, size_t size, int flags, 826 bus_dmamap_t *mapp, caddr_t *vaddr, bus_addr_t *baddr, 827 bus_dma_segment_t *seg, int nseg, int *rseg) 828 829 { 830 int error, level = 0; 831 832 if ((error = bus_dmamem_alloc(tag, size, PAGE_SIZE, 0, 833 seg, nseg, rseg, BUS_DMA_NOWAIT)) != 0) 834 goto out; 835 level++; 836 837 if ((error = bus_dmamem_map(tag, seg, *rseg, size, vaddr, 838 BUS_DMA_NOWAIT | flags)) != 0) 839 goto out; 840 level++; 841 842 if ((error = bus_dmamap_create(tag, size, *rseg, size, 0, 843 BUS_DMA_NOWAIT, mapp)) != 0) 844 goto out; 845 level++; 846 847 if ((error = bus_dmamap_load(tag, *mapp, *vaddr, size, NULL, 848 BUS_DMA_NOWAIT)) != 0) 849 goto out; 850 851 *baddr = (*mapp)->dm_segs[0].ds_addr; 852 853 return 0; 854 out: 855 switch (level) { 856 case 3: 857 bus_dmamap_destroy(tag, *mapp); 858 /* FALLTHROUGH */ 859 case 2: 860 bus_dmamem_unmap(tag, *vaddr, size); 861 /* FALLTHROUGH */ 862 case 1: 863 bus_dmamem_free(tag, seg, *rseg); 864 break; 865 default: 866 break; 867 } 868 869 return error; 870 } 871 872 void 873 agp_free_dmamem(bus_dma_tag_t tag, size_t size, bus_dmamap_t map, 874 caddr_t vaddr, bus_dma_segment_t *seg, int nseg) 875 { 876 877 bus_dmamap_unload(tag, map); 878 bus_dmamap_destroy(tag, map); 879 bus_dmamem_unmap(tag, vaddr, size); 880 bus_dmamem_free(tag, seg, nseg); 881 } 882 #endif 883