root/dev/pci/agp.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. agp_attach
  2. agp_mmap
  3. agp_ioctl
  4. agp_close
  5. agp_find_memory
  6. agp_lookup
  7. pciagp_set_pchb
  8. agp_map_aperture
  9. agp_alloc_gatt
  10. agp_free_gatt
  11. agp_generic_detach
  12. agp_generic_enable
  13. agp_generic_alloc_memory
  14. agp_generic_free_memory
  15. agp_generic_bind_memory
  16. agp_generic_unbind_memory
  17. agp_alloc_dmamem
  18. agp_free_dmamem

    1 /* $OpenBSD: agp.c,v 1.6 2007/08/04 19:40:25 reyk 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/malloc.h>
   32 #include <sys/agpio.h>
   33 #include <sys/fcntl.h>
   34 #include <sys/ioctl.h>
   35 
   36 #include <uvm/uvm.h>
   37 
   38 #include <dev/pci/pcivar.h>
   39 
   40 #include <dev/ic/mc6845reg.h>
   41 #include <dev/ic/pcdisplayvar.h>
   42 #include <dev/ic/vgareg.h>
   43 #include <dev/ic/vgavar.h>
   44 
   45 #include <dev/pci/agpvar.h>
   46 #include <dev/pci/agpreg.h>
   47 
   48 struct agp_memory *agp_find_memory(struct vga_pci_softc *sc, int id);
   49 const struct agp_product *agp_lookup(struct pci_attach_args *pa);
   50 
   51 struct pci_attach_args agp_pchb_pa;
   52 int agp_pchb_pa_set = 0;
   53 
   54 void
   55 agp_attach(struct device *parent, struct device *self, void *aux)
   56 {
   57         struct pci_attach_args *pa = aux;
   58         struct vga_pci_softc *sc = (struct vga_pci_softc *)self;
   59         const struct agp_product *ap;
   60         u_int memsize;
   61         int i, ret;
   62 
   63         ap = agp_lookup(pa);
   64         if (ap) {
   65                 static const int agp_max[][2] = {
   66                         {0,             0},
   67                         {32,            4},
   68                         {64,            28},
   69                         {128,           96},
   70                         {256,           204},
   71                         {512,           440},
   72                         {1024,          942},
   73                         {2048,          1920},
   74                         {4096,          3932}
   75                 };
   76 #define agp_max_size     (sizeof(agp_max)/sizeof(agp_max[0]))
   77 
   78                 /*
   79                  * Work out an upper bound for agp memory allocation. This
   80                  * uses a heuristic table from the Linux driver.
   81                  */
   82                 memsize = ptoa(physmem) >> 20;
   83 
   84                 for (i = 0; i < agp_max_size && memsize > agp_max[i][0]; i++)
   85                         ;
   86                 if (i == agp_max_size)
   87                         i = agp_max_size - 1;
   88                 sc->sc_maxmem = agp_max[i][1] << 20;
   89 
   90                 /*
   91                  * The lock is used to prevent re-entry to
   92                  * agp_generic_bind_memory() since that function can sleep.
   93                  */
   94 
   95                 lockinit(&sc->sc_lock, PZERO|PCATCH, "agplk", 0, 0);
   96 
   97                 TAILQ_INIT(&sc->sc_memory);
   98 
   99                 sc->sc_pcitag = pa->pa_tag;
  100                 sc->sc_pc = pa->pa_pc;
  101                 sc->sc_id = pa->pa_id;
  102                 sc->sc_dmat = pa->pa_dmat;
  103 
  104                 pci_get_capability(sc->sc_pc, sc->sc_pcitag, PCI_CAP_AGP,
  105                     &sc->sc_capoff, NULL);
  106 
  107                 ret = (*ap->ap_attach)(sc, pa, &agp_pchb_pa);
  108                 if (ret == 0)
  109                         printf(": aperture at 0x%lx, size 0x%lx",
  110                             (u_long)sc->sc_apaddr,
  111                             (u_long)AGP_GET_APERTURE(sc));
  112                 else {
  113                         sc->sc_chipc = NULL;
  114                         printf(": AGP GART");
  115                 }
  116         }
  117 }
  118 
  119 paddr_t
  120 agp_mmap(void *v, off_t off, int prot)
  121 {
  122         struct vga_config* vs = (struct vga_config*) v;
  123         struct vga_pci_softc* sc = (struct vga_pci_softc *)vs->vc_softc;
  124 
  125         if (sc->sc_apaddr) {
  126 
  127                 if (off > AGP_GET_APERTURE(sc))
  128                         return (-1);
  129 
  130                 return atop(sc->sc_apaddr + off);
  131         }
  132         return -1;
  133 }
  134 
  135 int
  136 agp_ioctl(void *v, u_long cmd, caddr_t addr, int flag, struct proc *pb)
  137 {
  138         struct vga_config *vc = v;
  139         struct vga_pci_softc *sc = (struct vga_pci_softc *)vc->vc_softc;
  140         struct agp_memory *mem;
  141         agp_info *info;
  142         agp_setup *setup;
  143         agp_allocate *alloc;
  144         agp_bind *bind;
  145         agp_unbind *unbind;
  146         vsize_t size;
  147         int error = 0;
  148 
  149         if (sc->sc_methods == NULL || sc->sc_chipc == NULL)
  150                 return (ENXIO);
  151 
  152         switch (cmd) {
  153         case AGPIOC_INFO:
  154                 if (!sc->sc_chipc)
  155                         return (ENXIO);
  156         case AGPIOC_ACQUIRE:
  157         case AGPIOC_RELEASE:
  158         case AGPIOC_SETUP:
  159         case AGPIOC_ALLOCATE:
  160         case AGPIOC_DEALLOCATE:
  161         case AGPIOC_BIND:
  162         case AGPIOC_UNBIND:
  163                 if (cmd != AGPIOC_INFO && !(flag & FWRITE))
  164                         return (EPERM);
  165                 break;
  166         }
  167         switch(cmd) {
  168         case AGPIOC_INFO:
  169                 info = (agp_info *)addr;
  170                 bzero(info, sizeof *info);
  171                 info->bridge_id = sc->sc_id;
  172                 if (sc->sc_capoff != 0)
  173                         info->agp_mode = pci_conf_read(sc->sc_pc, sc->sc_pcitag,
  174                             AGP_STATUS + sc->sc_capoff);
  175                 else
  176                         info->agp_mode = 0; /* i810 doesn't have real AGP */
  177                 info->aper_base = sc->sc_apaddr;
  178                 info->aper_size = AGP_GET_APERTURE(sc) >> 20;
  179                 info->pg_total =
  180                 info->pg_system = sc->sc_maxmem >> AGP_PAGE_SHIFT;
  181                 info->pg_used = sc->sc_allocated >> AGP_PAGE_SHIFT;
  182                 break;
  183 
  184         case AGPIOC_ACQUIRE:
  185                 if (sc->sc_state != AGP_ACQUIRE_FREE)
  186                         error = EBUSY;
  187                 else
  188                         sc->sc_state = AGP_ACQUIRE_USER;
  189                 break;
  190 
  191         case AGPIOC_RELEASE:
  192                 if (sc->sc_state == AGP_ACQUIRE_FREE)
  193                         break;
  194 
  195                 if (sc->sc_state != AGP_ACQUIRE_USER) {
  196                         error = EBUSY;
  197                         break;
  198                 }
  199 
  200                 /*
  201                  * Clear out the aperture and free any
  202                  * outstanding memory blocks.
  203                  */
  204                 TAILQ_FOREACH(mem, &sc->sc_memory, am_link) {
  205                         if (mem->am_is_bound) {
  206                                 printf("agp_release_helper: mem %d is bound\n",
  207                                     mem->am_id);
  208                                 AGP_UNBIND_MEMORY(sc, mem);
  209                         }
  210                 }
  211                 sc->sc_state = AGP_ACQUIRE_FREE;
  212                 break;
  213 
  214         case AGPIOC_SETUP:
  215                 setup = (agp_setup *)addr;
  216                 error = AGP_ENABLE(sc, setup->agp_mode);
  217                 break;
  218 
  219         case AGPIOC_ALLOCATE:
  220                 alloc = (agp_allocate *)addr;
  221                 size = alloc->pg_count << AGP_PAGE_SHIFT;
  222                 if (sc->sc_allocated + size > sc->sc_maxmem)
  223                         error = EINVAL;
  224                 else {
  225                         mem = AGP_ALLOC_MEMORY(sc, alloc->type, size);
  226                         if (mem) {
  227                                 alloc->key = mem->am_id;
  228                                 alloc->physical = mem->am_physical;
  229                         } else
  230                                 error = ENOMEM;
  231                 }
  232                 break;
  233 
  234         case AGPIOC_DEALLOCATE:
  235                 mem = agp_find_memory(sc, *(int *)addr);
  236                 if (mem)
  237                         AGP_FREE_MEMORY(sc, mem);
  238                 else
  239                         error = ENOENT;
  240                 break;
  241 
  242         case AGPIOC_BIND:
  243                 bind = (agp_bind *)addr;
  244                 mem = agp_find_memory(sc, bind->key);
  245                 if (!mem)
  246                         error = ENOENT;
  247                 else
  248                         error = AGP_BIND_MEMORY(sc, mem,
  249                             bind->pg_start << AGP_PAGE_SHIFT);
  250                 break;
  251 
  252         case AGPIOC_UNBIND:
  253                 unbind = (agp_unbind *)addr;
  254                 mem = agp_find_memory(sc, unbind->key);
  255                 if (!mem)
  256                         error = ENOENT;
  257                 else
  258                         error = AGP_UNBIND_MEMORY(sc, mem);
  259                 break;
  260         default:
  261                 error = ENOTTY;
  262         }
  263 
  264         return (error);
  265 }
  266 
  267 #ifdef notyet
  268 void
  269 agp_close(void *v)
  270 {
  271         struct vga_config *vc = v;
  272         struct vga_pci_softc *sc = (struct vga_pci_softc *)vc->vc_softc;
  273         struct agp_memory *mem;
  274 
  275         /*
  276          * Clear out the aperture and free any
  277          * outstanding memory blocks.
  278          */
  279         TAILQ_FOREACH(mem, &sc->sc_memory, am_link) {
  280                 if (mem->am_is_bound) {
  281                         AGP_UNBIND_MEMORY(sc, mem);
  282                 }
  283         }
  284 
  285         while (!TAILQ_EMPTY(&sc->sc_memory)) {
  286                 mem = TAILQ_FIRST(&sc->sc_memory);
  287                 AGP_FREE_MEMORY(sc, mem);
  288         }
  289 
  290         sc->sc_state = AGP_ACQUIRE_FREE;
  291 }
  292 #endif
  293 
  294 struct agp_memory *
  295 agp_find_memory(struct vga_pci_softc *sc, int id)
  296 {
  297         struct agp_memory *mem;
  298 
  299         AGP_DPF("searching for memory block %d\n", id);
  300         TAILQ_FOREACH(mem, &sc->sc_memory, am_link) {
  301                 AGP_DPF("considering memory block %d\n", mem->am_id);
  302                 if (mem->am_id == id)
  303                         return (mem);
  304         }
  305         return 0;
  306 }
  307 
  308 const struct agp_product *
  309 agp_lookup(struct pci_attach_args *pa)
  310 {
  311         const struct agp_product *ap;
  312 
  313         if (!agp_pchb_pa_set)
  314                 return (NULL);
  315         agp_pchb_pa_set = 0;
  316 
  317         /* First find the vendor. */
  318         for (ap = agp_products; ap->ap_attach != NULL; ap++)
  319                 if (ap->ap_vendor == PCI_VENDOR(pa->pa_id))
  320                         break;
  321 
  322         if (ap->ap_attach == NULL)
  323                 return (NULL);
  324 
  325         /* Now find the product within the vendor's domain. */
  326         for (; ap->ap_attach != NULL; ap++) {
  327                 /* Ran out of this vendor's section of the table. */
  328                 if (ap->ap_vendor != PCI_VENDOR(pa->pa_id))
  329                         return (NULL);
  330 
  331                 if (ap->ap_product == PCI_PRODUCT(pa->pa_id))
  332                         break;          /* Exact match. */
  333                 if (ap->ap_product == (u_int32_t) -1)
  334                         break;          /* Wildcard match. */
  335         }
  336 
  337         if (ap->ap_attach == NULL)
  338                 ap = NULL;
  339 
  340         return (ap);
  341 }
  342 
  343 void
  344 pciagp_set_pchb(struct pci_attach_args *pa)
  345 {
  346         if (!agp_pchb_pa_set) {
  347                 memcpy(&agp_pchb_pa, pa, sizeof *pa);
  348                 agp_pchb_pa_set++;
  349         }
  350 }
  351 
  352 int
  353 agp_map_aperture(struct vga_pci_softc *sc, u_int32_t bar, u_int32_t memtype)
  354 {
  355         /*
  356          * Find and the aperture. Don't map it (yet), this would
  357          * eat KVA.
  358          */
  359         if (pci_mapreg_info(sc->sc_pc, sc->sc_pcitag, bar,
  360             memtype, &sc->sc_apaddr, &sc->sc_apsize,
  361             &sc->sc_apflags) != 0)
  362                 return ENXIO;
  363 
  364         return 0;
  365 }
  366 
  367 struct agp_gatt *
  368 agp_alloc_gatt(struct vga_pci_softc *sc)
  369 {
  370         u_int32_t apsize = AGP_GET_APERTURE(sc);
  371         u_int32_t entries = apsize >> AGP_PAGE_SHIFT;
  372         struct agp_gatt *gatt;
  373         int nseg;
  374 
  375         gatt = malloc(sizeof(*gatt), M_DEVBUF, M_NOWAIT);
  376         if (!gatt)
  377                 return (NULL);
  378         bzero(gatt, sizeof(*gatt));
  379         gatt->ag_entries = entries;
  380 
  381         if (agp_alloc_dmamem(sc->sc_dmat, entries * sizeof(u_int32_t),
  382             0, &gatt->ag_dmamap, (caddr_t *)&gatt->ag_virtual,
  383             &gatt->ag_physical, &gatt->ag_dmaseg, 1, &nseg) != 0)
  384                 return NULL;
  385 
  386         gatt->ag_size = entries * sizeof(u_int32_t);
  387         memset(gatt->ag_virtual, 0, gatt->ag_size);
  388         agp_flush_cache();
  389 
  390         return gatt;
  391 }
  392 
  393 void
  394 agp_free_gatt(struct vga_pci_softc *sc, struct agp_gatt *gatt)
  395 {
  396         agp_free_dmamem(sc->sc_dmat, gatt->ag_size, gatt->ag_dmamap,
  397             (caddr_t)gatt->ag_virtual, &gatt->ag_dmaseg, 1);
  398         free(gatt, M_DEVBUF);
  399 }
  400 
  401 int
  402 agp_generic_detach(struct vga_pci_softc *sc)
  403 {
  404         lockmgr(&sc->sc_lock, LK_DRAIN, NULL);
  405         agp_flush_cache();
  406         return 0;
  407 }
  408 
  409 int
  410 agp_generic_enable(struct vga_pci_softc *sc, u_int32_t mode)
  411 {
  412         pcireg_t tstatus, mstatus;
  413         pcireg_t command;
  414         int rq, sba, fw, rate, capoff;
  415         
  416         if (pci_get_capability(sc->sc_pc, sc->sc_pcitag, PCI_CAP_AGP,
  417              &capoff, NULL) == 0) {
  418                 printf("agp_generic_enable: not an AGP capable device\n");
  419                 return -1;
  420         }
  421 
  422         tstatus = pci_conf_read(sc->sc_pc, sc->sc_pcitag,
  423             sc->sc_capoff + AGP_STATUS);
  424         mstatus = pci_conf_read(sc->sc_pc, sc->sc_pcitag,
  425             capoff + AGP_STATUS);
  426 
  427         /* Set RQ to the min of mode, tstatus and mstatus */
  428         rq = AGP_MODE_GET_RQ(mode);
  429         if (AGP_MODE_GET_RQ(tstatus) < rq)
  430                 rq = AGP_MODE_GET_RQ(tstatus);
  431         if (AGP_MODE_GET_RQ(mstatus) < rq)
  432                 rq = AGP_MODE_GET_RQ(mstatus);
  433 
  434         /* Set SBA if all three can deal with SBA */
  435         sba = (AGP_MODE_GET_SBA(tstatus)
  436                & AGP_MODE_GET_SBA(mstatus)
  437                & AGP_MODE_GET_SBA(mode));
  438 
  439         /* Similar for FW */
  440         fw = (AGP_MODE_GET_FW(tstatus)
  441                & AGP_MODE_GET_FW(mstatus)
  442                & AGP_MODE_GET_FW(mode));
  443 
  444         /* Figure out the max rate */
  445         rate = (AGP_MODE_GET_RATE(tstatus)
  446                 & AGP_MODE_GET_RATE(mstatus)
  447                 & AGP_MODE_GET_RATE(mode));
  448         if (rate & AGP_MODE_RATE_4x)
  449                 rate = AGP_MODE_RATE_4x;
  450         else if (rate & AGP_MODE_RATE_2x)
  451                 rate = AGP_MODE_RATE_2x;
  452         else
  453                 rate = AGP_MODE_RATE_1x;
  454 
  455         /* Construct the new mode word and tell the hardware  */
  456         command = AGP_MODE_SET_RQ(0, rq);
  457         command = AGP_MODE_SET_SBA(command, sba);
  458         command = AGP_MODE_SET_FW(command, fw);
  459         command = AGP_MODE_SET_RATE(command, rate);
  460         command = AGP_MODE_SET_AGP(command, 1);
  461         pci_conf_write(sc->sc_pc, sc->sc_pcitag,
  462             sc->sc_capoff + AGP_COMMAND, command);
  463         pci_conf_write(sc->sc_pc, sc->sc_pcitag, capoff + AGP_COMMAND, command);
  464         return 0;
  465 }
  466 
  467 struct agp_memory *
  468 agp_generic_alloc_memory(struct vga_pci_softc *sc, int type, vsize_t size)
  469 {
  470         struct agp_memory *mem;
  471 
  472         if (type != 0) {
  473                 printf("agp_generic_alloc_memory: unsupported type %d\n", type);
  474                 return 0;
  475         }
  476 
  477         mem = malloc(sizeof *mem, M_DEVBUF, M_WAITOK);
  478         if (mem == NULL)
  479                 return NULL;
  480         bzero(mem, sizeof *mem);
  481 
  482         if (bus_dmamap_create(sc->sc_dmat, size, size / PAGE_SIZE + 1,
  483             size, 0, BUS_DMA_NOWAIT, &mem->am_dmamap) != 0) {
  484                 free(mem, M_DEVBUF);
  485                 return NULL;
  486         }
  487 
  488         mem->am_id = sc->sc_nextid++;
  489         mem->am_size = size;
  490         TAILQ_INSERT_TAIL(&sc->sc_memory, mem, am_link);
  491         sc->sc_allocated += size;
  492 
  493         return mem;
  494 }
  495 
  496 int
  497 agp_generic_free_memory(struct vga_pci_softc *sc, struct agp_memory *mem)
  498 {
  499         if (mem->am_is_bound)
  500                 return EBUSY;
  501 
  502         sc->sc_allocated -= mem->am_size;
  503         TAILQ_REMOVE(&sc->sc_memory, mem, am_link);
  504         bus_dmamap_destroy(sc->sc_dmat, mem->am_dmamap);
  505         free(mem, M_DEVBUF);
  506         return 0;
  507 }
  508 
  509 int
  510 agp_generic_bind_memory(struct vga_pci_softc *sc, struct agp_memory *mem,
  511                         off_t offset)
  512 {
  513         bus_dma_segment_t *segs, *seg;
  514         bus_size_t done, j;
  515         bus_addr_t pa;
  516         off_t i, k;
  517         int nseg, error;
  518 
  519         lockmgr(&sc->sc_lock, LK_EXCLUSIVE, NULL);
  520 
  521         if (mem->am_is_bound) {
  522                 printf("AGP: memory already bound\n");
  523                 lockmgr(&sc->sc_lock, LK_RELEASE, NULL);
  524                 return EINVAL;
  525         }
  526 
  527         if (offset < 0
  528             || (offset & (AGP_PAGE_SIZE - 1)) != 0
  529             || offset + mem->am_size > AGP_GET_APERTURE(sc)) {
  530                 printf("AGP: binding memory at bad offset %#lx\n",
  531                               (unsigned long) offset);
  532                 lockmgr(&sc->sc_lock, LK_RELEASE, NULL);
  533                 return EINVAL;
  534         }
  535 
  536         /*
  537          * The memory here needs to be directly accessable from the
  538          * AGP video card, so it should be allocated using bus_dma.
  539          * However, it need not be contiguous, since individual pages
  540          * are translated using the GATT.
  541          */
  542 
  543         nseg = (mem->am_size + PAGE_SIZE - 1) / PAGE_SIZE;
  544         segs = malloc(nseg * sizeof *segs, M_DEVBUF, M_WAITOK);
  545         if (segs == NULL) {
  546                 lockmgr(&sc->sc_lock, LK_RELEASE, NULL);
  547                 AGP_DPF("malloc segs (%u) failed\n",
  548                     nseg * sizeof *segs);
  549                 return ENOMEM;
  550         }
  551         if ((error = bus_dmamem_alloc(sc->sc_dmat, mem->am_size, PAGE_SIZE, 0,
  552             segs, nseg, &mem->am_nseg, BUS_DMA_WAITOK)) != 0) {
  553                 free(segs, M_DEVBUF);
  554                 lockmgr(&sc->sc_lock, LK_RELEASE, NULL);
  555                 AGP_DPF("bus_dmamem_alloc failed %d\n", error);
  556                 return error;
  557         }
  558         if ((error = bus_dmamem_map(sc->sc_dmat, segs, mem->am_nseg,
  559             mem->am_size, &mem->am_virtual, BUS_DMA_WAITOK)) != 0) {
  560                 bus_dmamem_free(sc->sc_dmat, segs, mem->am_nseg);
  561                 free(segs, M_DEVBUF);
  562                 lockmgr(&sc->sc_lock, LK_RELEASE, NULL);
  563                 AGP_DPF("bus_dmamem_map failed %d\n", error);
  564                 return error;
  565         }
  566         if ((error = bus_dmamap_load(sc->sc_dmat, mem->am_dmamap,
  567             mem->am_virtual, mem->am_size, NULL,
  568             BUS_DMA_WAITOK)) != 0) {
  569                 bus_dmamem_unmap(sc->sc_dmat, mem->am_virtual,
  570                     mem->am_size);
  571                 bus_dmamem_free(sc->sc_dmat, segs, mem->am_nseg);
  572                 free(segs, M_DEVBUF);
  573                 lockmgr(&sc->sc_lock, LK_RELEASE, NULL);
  574                 AGP_DPF("bus_dmamap_load failed %d\n", error);
  575                 return error;
  576         }
  577         mem->am_dmaseg = segs;
  578 
  579         /*
  580          * Bind the individual pages and flush the chipset's
  581          * TLB.
  582          */
  583         done = 0;
  584         for (i = 0; i < mem->am_dmamap->dm_nsegs; i++) {
  585                 seg = &mem->am_dmamap->dm_segs[i];
  586                 /*
  587                  * Install entries in the GATT, making sure that if
  588                  * AGP_PAGE_SIZE < PAGE_SIZE and mem->am_size is not
  589                  * aligned to PAGE_SIZE, we don't modify too many GATT
  590                  * entries.
  591                  */
  592                 for (j = 0; j < seg->ds_len && (done + j) < mem->am_size;
  593                      j += AGP_PAGE_SIZE) {
  594                         pa = seg->ds_addr + j;
  595                         AGP_DPF("binding offset %#lx to pa %#lx\n",
  596                                 (unsigned long)(offset + done + j),
  597                                 (unsigned long)pa);
  598                         error = AGP_BIND_PAGE(sc, offset + done + j, pa);
  599                         if (error) {
  600                                 /*
  601                                  * Bail out. Reverse all the mappings
  602                                  * and unwire the pages.
  603                                  */
  604                                 for (k = 0; k < done + j; k += AGP_PAGE_SIZE)
  605                                         AGP_UNBIND_PAGE(sc, offset + k);
  606 
  607                                 bus_dmamap_unload(sc->sc_dmat, mem->am_dmamap);
  608                                 bus_dmamem_unmap(sc->sc_dmat, mem->am_virtual,
  609                                                  mem->am_size);
  610                                 bus_dmamem_free(sc->sc_dmat, mem->am_dmaseg,
  611                                                 mem->am_nseg);
  612                                 free(mem->am_dmaseg, M_DEVBUF);
  613                                 lockmgr(&sc->sc_lock, LK_RELEASE, NULL);
  614                                 AGP_DPF("AGP_BIND_PAGE failed %d\n", error);
  615                                 return error;
  616                         }
  617                 }
  618                 done += seg->ds_len;
  619         }
  620 
  621         /*
  622          * Flush the cpu cache since we are providing a new mapping
  623          * for these pages.
  624          */
  625         agp_flush_cache();
  626 
  627         /*
  628          * Make sure the chipset gets the new mappings.
  629          */
  630         AGP_FLUSH_TLB(sc);
  631 
  632         mem->am_offset = offset;
  633         mem->am_is_bound = 1;
  634 
  635         lockmgr(&sc->sc_lock, LK_RELEASE, NULL);
  636 
  637         return 0;
  638 }
  639 
  640 int
  641 agp_generic_unbind_memory(struct vga_pci_softc *sc, struct agp_memory *mem)
  642 {
  643         int i;
  644 
  645         lockmgr(&sc->sc_lock, LK_EXCLUSIVE, NULL);
  646 
  647         if (!mem->am_is_bound) {
  648                 printf("AGP: memory is not bound\n");
  649                 lockmgr(&sc->sc_lock, LK_RELEASE, NULL);
  650                 return EINVAL;
  651         }
  652 
  653 
  654         /*
  655          * Unbind the individual pages and flush the chipset's
  656          * TLB. Unwire the pages so they can be swapped.
  657          */
  658         for (i = 0; i < mem->am_size; i += AGP_PAGE_SIZE)
  659                 AGP_UNBIND_PAGE(sc, mem->am_offset + i);
  660 
  661         agp_flush_cache();
  662         AGP_FLUSH_TLB(sc);
  663 
  664         bus_dmamap_unload(sc->sc_dmat, mem->am_dmamap);
  665         bus_dmamem_unmap(sc->sc_dmat, mem->am_virtual, mem->am_size);
  666         bus_dmamem_free(sc->sc_dmat, mem->am_dmaseg, mem->am_nseg);
  667 
  668         free(mem->am_dmaseg, M_DEVBUF);
  669 
  670         mem->am_offset = 0;
  671         mem->am_is_bound = 0;
  672 
  673         lockmgr(&sc->sc_lock, LK_RELEASE, NULL);
  674 
  675         return 0;
  676 }
  677 
  678 int
  679 agp_alloc_dmamem(bus_dma_tag_t tag, size_t size, int flags,
  680                  bus_dmamap_t *mapp, caddr_t *vaddr, bus_addr_t *baddr,
  681                  bus_dma_segment_t *seg, int nseg, int *rseg)
  682 
  683 {
  684         int error, level = 0;
  685 
  686         if ((error = bus_dmamem_alloc(tag, size, PAGE_SIZE, 0,
  687                         seg, nseg, rseg, BUS_DMA_NOWAIT)) != 0)
  688                 goto out;
  689         level++;
  690 
  691         if ((error = bus_dmamem_map(tag, seg, *rseg, size, vaddr,
  692                         BUS_DMA_NOWAIT | flags)) != 0)
  693                 goto out;
  694         level++;
  695 
  696         if ((error = bus_dmamap_create(tag, size, *rseg, size, 0,
  697                         BUS_DMA_NOWAIT, mapp)) != 0)
  698                 goto out;
  699         level++;
  700 
  701         if ((error = bus_dmamap_load(tag, *mapp, *vaddr, size, NULL,
  702                         BUS_DMA_NOWAIT)) != 0)
  703                 goto out;
  704 
  705         *baddr = (*mapp)->dm_segs[0].ds_addr;
  706 
  707         return 0;
  708 out:
  709         switch (level) {
  710         case 3:
  711                 bus_dmamap_destroy(tag, *mapp);
  712                 /* FALLTHROUGH */
  713         case 2:
  714                 bus_dmamem_unmap(tag, *vaddr, size);
  715                 /* FALLTHROUGH */
  716         case 1:
  717                 bus_dmamem_free(tag, seg, *rseg);
  718                 break;
  719         default:
  720                 break;
  721         }
  722 
  723         return error;
  724 }
  725 
  726 void
  727 agp_free_dmamem(bus_dma_tag_t tag, size_t size, bus_dmamap_t map,
  728                 caddr_t vaddr, bus_dma_segment_t *seg, int nseg)
  729 {
  730 
  731         bus_dmamap_unload(tag, map);
  732         bus_dmamap_destroy(tag, map);
  733         bus_dmamem_unmap(tag, vaddr, size);
  734         bus_dmamem_free(tag, seg, nseg);
  735 }

/* [<][>][^][v][top][bottom][index][help] */