LCOV - code coverage report
Current view: top level - dev/pci - agp.c (source / functions) Hit Total Coverage
Test: 6.4 Lines: 0 193 0.0 %
Date: 2018-10-19 03:25:38 Functions: 0 18 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       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           0 : agpdev_print(void *aux, const char *pnp)
      54             : {
      55           0 :         if (pnp) {
      56           0 :                 printf("agp at %s", pnp);
      57           0 :         }
      58           0 :         return (UNCONF);
      59             : }
      60             : 
      61             : int
      62           0 : agpbus_probe(struct agp_attach_args *aa)
      63             : {
      64           0 :         struct pci_attach_args  *pa = aa->aa_pa;
      65             : 
      66           0 :         if (strncmp(aa->aa_busname, "agp", 3) == 0 &&
      67           0 :             PCI_CLASS(pa->pa_class) == PCI_CLASS_BRIDGE && 
      68           0 :             PCI_SUBCLASS(pa->pa_class) == PCI_SUBCLASS_BRIDGE_HOST)
      69           0 :                 return (1);
      70           0 :         return (0);
      71           0 : }
      72             : 
      73             : /*
      74             :  * Find the video card hanging off the agp bus XXX assumes only one bus
      75             :  */
      76             : int
      77           0 : agpvga_match(struct pci_attach_args *pa)
      78             : {
      79           0 :         if (PCI_CLASS(pa->pa_class) == PCI_CLASS_DISPLAY &&
      80           0 :             PCI_SUBCLASS(pa->pa_class) == PCI_SUBCLASS_DISPLAY_VGA) {
      81           0 :                 if (pci_get_capability(pa->pa_pc, pa->pa_tag, PCI_CAP_AGP,
      82             :                     NULL, NULL))
      83           0 :                         return (1);
      84             :         }
      85           0 :         return (0);
      86           0 : }
      87             : 
      88             : struct device *
      89           0 : 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           0 :         struct agpbus_attach_args arg;
      93             : 
      94           0 :         arg.aa_methods = methods;
      95           0 :         arg.aa_pa = pa;
      96           0 :         arg.aa_apaddr = apaddr;
      97           0 :         arg.aa_apsize = apsize;
      98             : 
      99           0 :         printf("\n"); /* newline from the driver that called us */
     100           0 :         return (config_found(dev, &arg, agpdev_print));
     101           0 : }
     102             : 
     103             : int
     104           0 : 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           0 :         return (1);
     111             : }
     112             : 
     113             : void
     114           0 : agp_attach(struct device *parent, struct device *self, void *aux)
     115             : {
     116           0 :         struct agpbus_attach_args *aa = aux;
     117           0 :         struct pci_attach_args *pa = aa->aa_pa;
     118           0 :         struct agp_softc *sc = (struct agp_softc *)self;
     119             :         u_int memsize;
     120             :         int i;
     121             : 
     122           0 :         sc->sc_chipc = parent;
     123           0 :         sc->sc_methods = aa->aa_methods;
     124           0 :         sc->sc_apaddr = aa->aa_apaddr;
     125           0 :         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           0 :         memsize = ptoa(physmem) >> 20;
     144             : 
     145           0 :         for (i = 0; i < nitems(agp_max) && memsize > agp_max[i][0]; i++)
     146             :                 ;
     147           0 :         if (i == nitems(agp_max))
     148           0 :                 i = nitems(agp_max) - 1;
     149           0 :         sc->sc_maxmem = agp_max[i][1] << 20;
     150             : 
     151           0 :         sc->sc_pcitag = pa->pa_tag;
     152           0 :         sc->sc_pc = pa->pa_pc;
     153           0 :         sc->sc_id = pa->pa_id;
     154           0 :         sc->sc_dmat = pa->pa_dmat;
     155           0 :         sc->sc_memt = pa->pa_memt;
     156             : 
     157           0 :         pci_get_capability(sc->sc_pc, sc->sc_pcitag, PCI_CAP_AGP,
     158           0 :             &sc->sc_capoff, NULL);
     159             : 
     160           0 :         printf(": aperture at 0x%lx, size 0x%lx\n", (u_long)sc->sc_apaddr,
     161           0 :             (u_long)sc->sc_apsize);
     162           0 : }
     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           0 : agp_alloc_gatt(bus_dma_tag_t dmat, u_int32_t apsize)
     175             : {
     176             :         struct agp_gatt         *gatt;
     177           0 :         u_int32_t                entries = apsize >> AGP_PAGE_SHIFT;
     178             : 
     179           0 :         gatt = malloc(sizeof(*gatt), M_AGP, M_NOWAIT | M_ZERO);
     180           0 :         if (!gatt)
     181           0 :                 return (NULL);
     182           0 :         gatt->ag_entries = entries;
     183           0 :         gatt->ag_size = entries * sizeof(u_int32_t);
     184             : 
     185           0 :         if (agp_alloc_dmamem(dmat, gatt->ag_size, &gatt->ag_dmamap,
     186           0 :             &gatt->ag_physical, &gatt->ag_dmaseg) != 0) {
     187           0 :                 free(gatt, M_AGP, sizeof *gatt);
     188           0 :                 return (NULL);
     189             :         }
     190             : 
     191           0 :         if (bus_dmamem_map(dmat, &gatt->ag_dmaseg, 1, gatt->ag_size,
     192           0 :             (caddr_t *)&gatt->ag_virtual, BUS_DMA_NOWAIT) != 0) {
     193           0 :                 agp_free_dmamem(dmat, gatt->ag_size, gatt->ag_dmamap,
     194             :                     &gatt->ag_dmaseg);
     195           0 :                 free(gatt, M_AGP, sizeof *gatt);
     196           0 :                 return (NULL);
     197             :         }
     198             : 
     199           0 :         agp_flush_cache();
     200             : 
     201           0 :         return (gatt);
     202           0 : }
     203             : 
     204             : void
     205           0 : agp_free_gatt(bus_dma_tag_t dmat, struct agp_gatt *gatt)
     206             : {
     207           0 :         bus_dmamem_unmap(dmat, (caddr_t)gatt->ag_virtual, gatt->ag_size);
     208           0 :         agp_free_dmamem(dmat, gatt->ag_size, gatt->ag_dmamap, &gatt->ag_dmaseg);
     209           0 :         free(gatt, M_AGP, sizeof *gatt);
     210           0 : }
     211             : 
     212             : int
     213           0 : agp_generic_enable(struct agp_softc *sc, u_int32_t mode)
     214             : {
     215           0 :         struct pci_attach_args  pa;
     216             :         pcireg_t                tstatus, mstatus, command;
     217           0 :         int                     rq, sba, fw, rate, capoff;
     218             :         
     219           0 :         if (pci_find_device(&pa, agpvga_match) == 0 ||
     220           0 :             pci_get_capability(pa.pa_pc, pa.pa_tag, PCI_CAP_AGP,
     221           0 :             &capoff, NULL) == 0) {
     222           0 :                 printf("agp_generic_enable: not an AGP capable device\n");
     223           0 :                 return (-1);
     224             :         }
     225             : 
     226           0 :         tstatus = pci_conf_read(sc->sc_pc, sc->sc_pcitag,
     227           0 :             sc->sc_capoff + AGP_STATUS);
     228             :         /* display agp mode */
     229           0 :         mstatus = pci_conf_read(pa.pa_pc, pa.pa_tag,
     230           0 :             capoff + AGP_STATUS);
     231             : 
     232             :         /* Set RQ to the min of mode, tstatus and mstatus */
     233           0 :         rq = AGP_MODE_GET_RQ(mode);
     234           0 :         if (AGP_MODE_GET_RQ(tstatus) < rq)
     235           0 :                 rq = AGP_MODE_GET_RQ(tstatus);
     236           0 :         if (AGP_MODE_GET_RQ(mstatus) < rq)
     237           0 :                 rq = AGP_MODE_GET_RQ(mstatus);
     238             : 
     239             :         /* Set SBA if all three can deal with SBA */
     240           0 :         sba = (AGP_MODE_GET_SBA(tstatus)
     241           0 :             & AGP_MODE_GET_SBA(mstatus)
     242           0 :             & AGP_MODE_GET_SBA(mode));
     243             : 
     244             :         /* Similar for FW */
     245           0 :         fw = (AGP_MODE_GET_FW(tstatus)
     246           0 :             & AGP_MODE_GET_FW(mstatus)
     247           0 :             & AGP_MODE_GET_FW(mode));
     248             : 
     249             :         /* Figure out the max rate */
     250           0 :         rate = (AGP_MODE_GET_RATE(tstatus)
     251           0 :             & AGP_MODE_GET_RATE(mstatus)
     252           0 :             & AGP_MODE_GET_RATE(mode));
     253           0 :         if (rate & AGP_MODE_RATE_4x)
     254           0 :                 rate = AGP_MODE_RATE_4x;
     255           0 :         else if (rate & AGP_MODE_RATE_2x)
     256           0 :                 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           0 :         command = AGP_MODE_SET_RQ(0, rq);
     262           0 :         command = AGP_MODE_SET_SBA(command, sba);
     263           0 :         command = AGP_MODE_SET_FW(command, fw);
     264           0 :         command = AGP_MODE_SET_RATE(command, rate);
     265           0 :         command = AGP_MODE_SET_AGP(command, 1);
     266             : 
     267           0 :         pci_conf_write(sc->sc_pc, sc->sc_pcitag,
     268           0 :             sc->sc_capoff + AGP_COMMAND, command);
     269           0 :         pci_conf_write(pa.pa_pc, pa.pa_tag, capoff + AGP_COMMAND, command);
     270           0 :         return (0);
     271           0 : }
     272             : 
     273             : /*
     274             :  * Allocates a single-segment block of zeroed, wired dma memory.
     275             :  */
     276             : int
     277           0 : 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           0 :         int error, level = 0, nseg;
     281             : 
     282           0 :         if ((error = bus_dmamem_alloc(tag, size, PAGE_SIZE, 0,
     283           0 :             seg, 1, &nseg, BUS_DMA_NOWAIT | BUS_DMA_ZERO)) != 0)
     284             :                 goto out;
     285             :         level++;
     286             : 
     287           0 :         if ((error = bus_dmamap_create(tag, size, nseg, size, 0,
     288           0 :             BUS_DMA_NOWAIT, mapp)) != 0)
     289             :                 goto out;
     290             :         level++;
     291             : 
     292           0 :         if ((error = bus_dmamap_load_raw(tag, *mapp, seg, nseg, size,
     293           0 :             BUS_DMA_NOWAIT)) != 0)
     294             :                 goto out;
     295             : 
     296           0 :         *baddr = (*mapp)->dm_segs[0].ds_addr;
     297             : 
     298           0 :         return (0);
     299             : out:
     300           0 :         switch (level) {
     301             :         case 2:
     302           0 :                 bus_dmamap_destroy(tag, *mapp);
     303             :                 /* FALLTHROUGH */
     304             :         case 1:
     305           0 :                 bus_dmamem_free(tag, seg, nseg);
     306           0 :                 break;
     307             :         default:
     308             :                 break;
     309             :         }
     310             : 
     311           0 :         return (error);
     312           0 : }
     313             : 
     314             : void
     315           0 : agp_free_dmamem(bus_dma_tag_t tag, size_t size, bus_dmamap_t map,
     316             :     bus_dma_segment_t *seg)
     317             : {
     318           0 :         bus_dmamap_unload(tag, map);
     319           0 :         bus_dmamap_destroy(tag, map);
     320           0 :         bus_dmamem_free(tag, seg, 1);
     321           0 : }
     322             : 
     323             : /* Implementation of the kernel api */
     324             : 
     325             : void *
     326           0 : agp_find_device(int unit)
     327             : {
     328           0 :         if (unit >= agp_cd.cd_ndevs || unit < 0)
     329           0 :                 return (NULL);
     330           0 :         return (agp_cd.cd_devs[unit]);
     331           0 : }
     332             : 
     333             : enum agp_acquire_state
     334           0 : agp_state(void *dev)
     335             : {
     336           0 :         struct agp_softc *sc = (struct agp_softc *) dev;
     337           0 :         return (sc->sc_state);
     338             : }
     339             : 
     340             : void
     341           0 : agp_get_info(void *dev, struct agp_info *info)
     342             : {
     343           0 :         struct agp_softc *sc = (struct agp_softc *)dev;
     344             : 
     345           0 :         if (sc->sc_capoff != 0)
     346           0 :                 info->ai_mode = pci_conf_read(sc->sc_pc, sc->sc_pcitag,
     347           0 :                     AGP_STATUS + sc->sc_capoff);
     348             :         else
     349           0 :                 info->ai_mode = 0; /* i810 doesn't have real AGP */
     350           0 :         info->ai_aperture_base = sc->sc_apaddr;
     351           0 :         info->ai_aperture_size = sc->sc_apsize;
     352           0 :         info->ai_memory_allowed = sc->sc_maxmem;
     353           0 :         info->ai_memory_used = sc->sc_allocated;
     354           0 :         info->ai_devid = sc->sc_id;
     355           0 : }
     356             : 
     357             : int
     358           0 : agp_acquire(void *dev)
     359             : {
     360           0 :         struct agp_softc *sc = (struct agp_softc *)dev;
     361             : 
     362           0 :         if (sc->sc_chipc == NULL) 
     363           0 :                 return (EINVAL);
     364             : 
     365           0 :         if (sc->sc_state != AGP_ACQUIRE_FREE)
     366           0 :                 return (EBUSY);
     367           0 :         sc->sc_state = AGP_ACQUIRE_KERNEL;
     368             : 
     369           0 :         return (0);
     370           0 : }
     371             : 
     372             : int
     373           0 : agp_release(void *dev)
     374             : {
     375           0 :         struct agp_softc *sc = (struct agp_softc *)dev;
     376             : 
     377           0 :         if (sc->sc_state == AGP_ACQUIRE_FREE)
     378           0 :                 return (0);
     379             : 
     380           0 :         if (sc->sc_state != AGP_ACQUIRE_KERNEL) 
     381           0 :                 return (EBUSY);
     382             : 
     383           0 :         sc->sc_state = AGP_ACQUIRE_FREE;
     384           0 :         return (0);
     385           0 : }
     386             : 
     387             : int
     388           0 : agp_enable(void *dev, u_int32_t mode)
     389             : {
     390           0 :         struct agp_softc        *sc = dev;
     391             :         int                      ret;
     392             : 
     393           0 :         if (sc->sc_methods->enable != NULL) {
     394           0 :                 ret = sc->sc_methods->enable(sc->sc_chipc, mode);
     395           0 :         } else {
     396           0 :                 ret = agp_generic_enable(sc, mode);
     397             :         }
     398           0 :         return (ret);
     399             : }
     400             : 
     401             : paddr_t
     402           0 : agp_mmap(struct agp_softc *sc, off_t off, int prot)
     403             : {
     404           0 :         if (sc->sc_chipc == NULL)
     405           0 :                 return (-1);
     406             : 
     407           0 :         if (off >= sc->sc_apsize)
     408           0 :                 return (-1);
     409             : 
     410           0 :         if (sc->sc_apaddr == 0)
     411           0 :                 return (-1);
     412             : 
     413           0 :         return bus_space_mmap(sc->sc_memt, sc->sc_apaddr, off, prot, 0);
     414           0 : }

Generated by: LCOV version 1.13