The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/drm/mga_dma.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /* mga_dma.c -- DMA support for mga g200/g400 -*- linux-c -*-
    2  * Created: Mon Dec 13 01:50:01 1999 by jhartmann@precisioninsight.com
    3  */
    4 /* Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
    5  * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
    6  * All Rights Reserved.
    7  *
    8  * Permission is hereby granted, free of charge, to any person obtaining a
    9  * copy of this software and associated documentation files (the "Software"),
   10  * to deal in the Software without restriction, including without limitation
   11  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
   12  * and/or sell copies of the Software, and to permit persons to whom the
   13  * Software is furnished to do so, subject to the following conditions:
   14  *
   15  * The above copyright notice and this permission notice (including the next
   16  * paragraph) shall be included in all copies or substantial portions of the
   17  * Software.
   18  *
   19  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   20  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   21  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
   22  * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
   23  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
   24  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
   25  * DEALINGS IN THE SOFTWARE.
   26  */
   27 
   28 #include <sys/cdefs.h>
   29 __FBSDID("$FreeBSD: releng/6.4/sys/dev/drm/mga_dma.c 153401 2005-12-14 00:52:59Z anholt $");
   30 
   31 /**
   32  * \file mga_dma.c
   33  * DMA support for MGA G200 / G400.
   34  * 
   35  * \author Rickard E. (Rik) Faith <faith@valinux.com>
   36  * \author Jeff Hartmann <jhartmann@valinux.com>
   37  * \author Keith Whitwell <keith@tungstengraphics.com>
   38  * \author Gareth Hughes <gareth@valinux.com>
   39  */
   40 
   41 #include "dev/drm/drmP.h"
   42 #include "dev/drm/drm.h"
   43 #include "dev/drm/drm_sarea.h"
   44 #include "dev/drm/mga_drm.h"
   45 #include "dev/drm/mga_drv.h"
   46 
   47 #define MGA_DEFAULT_USEC_TIMEOUT        10000
   48 #define MGA_FREELIST_DEBUG              0
   49 
   50 #define MINIMAL_CLEANUP    0
   51 #define FULL_CLEANUP       1
   52 static int mga_do_cleanup_dma(drm_device_t * dev, int full_cleanup);
   53 
   54 /* ================================================================
   55  * Engine control
   56  */
   57 
   58 int mga_do_wait_for_idle(drm_mga_private_t * dev_priv)
   59 {
   60         u32 status = 0;
   61         int i;
   62         DRM_DEBUG("\n");
   63 
   64         for (i = 0; i < dev_priv->usec_timeout; i++) {
   65                 status = MGA_READ(MGA_STATUS) & MGA_ENGINE_IDLE_MASK;
   66                 if (status == MGA_ENDPRDMASTS) {
   67                         MGA_WRITE8(MGA_CRTC_INDEX, 0);
   68                         return 0;
   69                 }
   70                 DRM_UDELAY(1);
   71         }
   72 
   73 #if MGA_DMA_DEBUG
   74         DRM_ERROR("failed!\n");
   75         DRM_INFO("   status=0x%08x\n", status);
   76 #endif
   77         return DRM_ERR(EBUSY);
   78 }
   79 
   80 static int mga_do_dma_reset(drm_mga_private_t * dev_priv)
   81 {
   82         drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
   83         drm_mga_primary_buffer_t *primary = &dev_priv->prim;
   84 
   85         DRM_DEBUG("\n");
   86 
   87         /* The primary DMA stream should look like new right about now.
   88          */
   89         primary->tail = 0;
   90         primary->space = primary->size;
   91         primary->last_flush = 0;
   92 
   93         sarea_priv->last_wrap = 0;
   94 
   95         /* FIXME: Reset counters, buffer ages etc...
   96          */
   97 
   98         /* FIXME: What else do we need to reinitialize?  WARP stuff?
   99          */
  100 
  101         return 0;
  102 }
  103 
  104 /* ================================================================
  105  * Primary DMA stream
  106  */
  107 
  108 void mga_do_dma_flush(drm_mga_private_t * dev_priv)
  109 {
  110         drm_mga_primary_buffer_t *primary = &dev_priv->prim;
  111         u32 head, tail;
  112         u32 status = 0;
  113         int i;
  114         DMA_LOCALS;
  115         DRM_DEBUG("\n");
  116 
  117         /* We need to wait so that we can do an safe flush */
  118         for (i = 0; i < dev_priv->usec_timeout; i++) {
  119                 status = MGA_READ(MGA_STATUS) & MGA_ENGINE_IDLE_MASK;
  120                 if (status == MGA_ENDPRDMASTS)
  121                         break;
  122                 DRM_UDELAY(1);
  123         }
  124 
  125         if (primary->tail == primary->last_flush) {
  126                 DRM_DEBUG("   bailing out...\n");
  127                 return;
  128         }
  129 
  130         tail = primary->tail + dev_priv->primary->offset;
  131 
  132         /* We need to pad the stream between flushes, as the card
  133          * actually (partially?) reads the first of these commands.
  134          * See page 4-16 in the G400 manual, middle of the page or so.
  135          */
  136         BEGIN_DMA(1);
  137 
  138         DMA_BLOCK(MGA_DMAPAD, 0x00000000,
  139                   MGA_DMAPAD, 0x00000000,
  140                   MGA_DMAPAD, 0x00000000, MGA_DMAPAD, 0x00000000);
  141 
  142         ADVANCE_DMA();
  143 
  144         primary->last_flush = primary->tail;
  145 
  146         head = MGA_READ(MGA_PRIMADDRESS);
  147 
  148         if (head <= tail) {
  149                 primary->space = primary->size - primary->tail;
  150         } else {
  151                 primary->space = head - tail;
  152         }
  153 
  154         DRM_DEBUG("   head = 0x%06lx\n", head - dev_priv->primary->offset);
  155         DRM_DEBUG("   tail = 0x%06lx\n", tail - dev_priv->primary->offset);
  156         DRM_DEBUG("  space = 0x%06x\n", primary->space);
  157 
  158         mga_flush_write_combine();
  159         MGA_WRITE(MGA_PRIMEND, tail | dev_priv->dma_access);
  160 
  161         DRM_DEBUG("done.\n");
  162 }
  163 
  164 void mga_do_dma_wrap_start(drm_mga_private_t * dev_priv)
  165 {
  166         drm_mga_primary_buffer_t *primary = &dev_priv->prim;
  167         u32 head, tail;
  168         DMA_LOCALS;
  169         DRM_DEBUG("\n");
  170 
  171         BEGIN_DMA_WRAP();
  172 
  173         DMA_BLOCK(MGA_DMAPAD, 0x00000000,
  174                   MGA_DMAPAD, 0x00000000,
  175                   MGA_DMAPAD, 0x00000000, MGA_DMAPAD, 0x00000000);
  176 
  177         ADVANCE_DMA();
  178 
  179         tail = primary->tail + dev_priv->primary->offset;
  180 
  181         primary->tail = 0;
  182         primary->last_flush = 0;
  183         primary->last_wrap++;
  184 
  185         head = MGA_READ(MGA_PRIMADDRESS);
  186 
  187         if (head == dev_priv->primary->offset) {
  188                 primary->space = primary->size;
  189         } else {
  190                 primary->space = head - dev_priv->primary->offset;
  191         }
  192 
  193         DRM_DEBUG("   head = 0x%06lx\n", head - dev_priv->primary->offset);
  194         DRM_DEBUG("   tail = 0x%06x\n", primary->tail);
  195         DRM_DEBUG("   wrap = %d\n", primary->last_wrap);
  196         DRM_DEBUG("  space = 0x%06x\n", primary->space);
  197 
  198         mga_flush_write_combine();
  199         MGA_WRITE(MGA_PRIMEND, tail | dev_priv->dma_access);
  200 
  201         set_bit(0, &primary->wrapped);
  202         DRM_DEBUG("done.\n");
  203 }
  204 
  205 void mga_do_dma_wrap_end(drm_mga_private_t * dev_priv)
  206 {
  207         drm_mga_primary_buffer_t *primary = &dev_priv->prim;
  208         drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
  209         u32 head = dev_priv->primary->offset;
  210         DRM_DEBUG("\n");
  211 
  212         sarea_priv->last_wrap++;
  213         DRM_DEBUG("   wrap = %d\n", sarea_priv->last_wrap);
  214 
  215         mga_flush_write_combine();
  216         MGA_WRITE(MGA_PRIMADDRESS, head | MGA_DMA_GENERAL);
  217 
  218         clear_bit(0, &primary->wrapped);
  219         DRM_DEBUG("done.\n");
  220 }
  221 
  222 /* ================================================================
  223  * Freelist management
  224  */
  225 
  226 #define MGA_BUFFER_USED         ~0
  227 #define MGA_BUFFER_FREE         0
  228 
  229 #if MGA_FREELIST_DEBUG
  230 static void mga_freelist_print(drm_device_t * dev)
  231 {
  232         drm_mga_private_t *dev_priv = dev->dev_private;
  233         drm_mga_freelist_t *entry;
  234 
  235         DRM_INFO("\n");
  236         DRM_INFO("current dispatch: last=0x%x done=0x%x\n",
  237                  dev_priv->sarea_priv->last_dispatch,
  238                  (unsigned int)(MGA_READ(MGA_PRIMADDRESS) -
  239                                 dev_priv->primary->offset));
  240         DRM_INFO("current freelist:\n");
  241 
  242         for (entry = dev_priv->head->next; entry; entry = entry->next) {
  243                 DRM_INFO("   %p   idx=%2d  age=0x%x 0x%06lx\n",
  244                          entry, entry->buf->idx, entry->age.head,
  245                          entry->age.head - dev_priv->primary->offset);
  246         }
  247         DRM_INFO("\n");
  248 }
  249 #endif
  250 
  251 static int mga_freelist_init(drm_device_t * dev, drm_mga_private_t * dev_priv)
  252 {
  253         drm_device_dma_t *dma = dev->dma;
  254         drm_buf_t *buf;
  255         drm_mga_buf_priv_t *buf_priv;
  256         drm_mga_freelist_t *entry;
  257         int i;
  258         DRM_DEBUG("count=%d\n", dma->buf_count);
  259 
  260         dev_priv->head = drm_alloc(sizeof(drm_mga_freelist_t), DRM_MEM_DRIVER);
  261         if (dev_priv->head == NULL)
  262                 return DRM_ERR(ENOMEM);
  263 
  264         memset(dev_priv->head, 0, sizeof(drm_mga_freelist_t));
  265         SET_AGE(&dev_priv->head->age, MGA_BUFFER_USED, 0);
  266 
  267         for (i = 0; i < dma->buf_count; i++) {
  268                 buf = dma->buflist[i];
  269                 buf_priv = buf->dev_private;
  270 
  271                 entry = drm_alloc(sizeof(drm_mga_freelist_t), DRM_MEM_DRIVER);
  272                 if (entry == NULL)
  273                         return DRM_ERR(ENOMEM);
  274 
  275                 memset(entry, 0, sizeof(drm_mga_freelist_t));
  276 
  277                 entry->next = dev_priv->head->next;
  278                 entry->prev = dev_priv->head;
  279                 SET_AGE(&entry->age, MGA_BUFFER_FREE, 0);
  280                 entry->buf = buf;
  281 
  282                 if (dev_priv->head->next != NULL)
  283                         dev_priv->head->next->prev = entry;
  284                 if (entry->next == NULL)
  285                         dev_priv->tail = entry;
  286 
  287                 buf_priv->list_entry = entry;
  288                 buf_priv->discard = 0;
  289                 buf_priv->dispatched = 0;
  290 
  291                 dev_priv->head->next = entry;
  292         }
  293 
  294         return 0;
  295 }
  296 
  297 static void mga_freelist_cleanup(drm_device_t * dev)
  298 {
  299         drm_mga_private_t *dev_priv = dev->dev_private;
  300         drm_mga_freelist_t *entry;
  301         drm_mga_freelist_t *next;
  302         DRM_DEBUG("\n");
  303 
  304         entry = dev_priv->head;
  305         while (entry) {
  306                 next = entry->next;
  307                 drm_free(entry, sizeof(drm_mga_freelist_t), DRM_MEM_DRIVER);
  308                 entry = next;
  309         }
  310 
  311         dev_priv->head = dev_priv->tail = NULL;
  312 }
  313 
  314 #if 0
  315 /* FIXME: Still needed?
  316  */
  317 static void mga_freelist_reset(drm_device_t * dev)
  318 {
  319         drm_device_dma_t *dma = dev->dma;
  320         drm_buf_t *buf;
  321         drm_mga_buf_priv_t *buf_priv;
  322         int i;
  323 
  324         for (i = 0; i < dma->buf_count; i++) {
  325                 buf = dma->buflist[i];
  326                 buf_priv = buf->dev_private;
  327                 SET_AGE(&buf_priv->list_entry->age, MGA_BUFFER_FREE, 0);
  328         }
  329 }
  330 #endif
  331 
  332 static drm_buf_t *mga_freelist_get(drm_device_t * dev)
  333 {
  334         drm_mga_private_t *dev_priv = dev->dev_private;
  335         drm_mga_freelist_t *next;
  336         drm_mga_freelist_t *prev;
  337         drm_mga_freelist_t *tail = dev_priv->tail;
  338         u32 head, wrap;
  339         DRM_DEBUG("\n");
  340 
  341         head = MGA_READ(MGA_PRIMADDRESS);
  342         wrap = dev_priv->sarea_priv->last_wrap;
  343 
  344         DRM_DEBUG("   tail=0x%06lx %d\n",
  345                   tail->age.head ?
  346                   tail->age.head - dev_priv->primary->offset : 0,
  347                   tail->age.wrap);
  348         DRM_DEBUG("   head=0x%06lx %d\n",
  349                   head - dev_priv->primary->offset, wrap);
  350 
  351         if (TEST_AGE(&tail->age, head, wrap)) {
  352                 prev = dev_priv->tail->prev;
  353                 next = dev_priv->tail;
  354                 prev->next = NULL;
  355                 next->prev = next->next = NULL;
  356                 dev_priv->tail = prev;
  357                 SET_AGE(&next->age, MGA_BUFFER_USED, 0);
  358                 return next->buf;
  359         }
  360 
  361         DRM_DEBUG("returning NULL!\n");
  362         return NULL;
  363 }
  364 
  365 int mga_freelist_put(drm_device_t * dev, drm_buf_t * buf)
  366 {
  367         drm_mga_private_t *dev_priv = dev->dev_private;
  368         drm_mga_buf_priv_t *buf_priv = buf->dev_private;
  369         drm_mga_freelist_t *head, *entry, *prev;
  370 
  371         DRM_DEBUG("age=0x%06lx wrap=%d\n",
  372                   buf_priv->list_entry->age.head -
  373                   dev_priv->primary->offset, buf_priv->list_entry->age.wrap);
  374 
  375         entry = buf_priv->list_entry;
  376         head = dev_priv->head;
  377 
  378         if (buf_priv->list_entry->age.head == MGA_BUFFER_USED) {
  379                 SET_AGE(&entry->age, MGA_BUFFER_FREE, 0);
  380                 prev = dev_priv->tail;
  381                 prev->next = entry;
  382                 entry->prev = prev;
  383                 entry->next = NULL;
  384         } else {
  385                 prev = head->next;
  386                 head->next = entry;
  387                 prev->prev = entry;
  388                 entry->prev = head;
  389                 entry->next = prev;
  390         }
  391 
  392         return 0;
  393 }
  394 
  395 /* ================================================================
  396  * DMA initialization, cleanup
  397  */
  398 
  399 int mga_driver_load(drm_device_t *dev, unsigned long flags)
  400 {
  401         drm_mga_private_t * dev_priv;
  402 
  403         dev_priv = drm_alloc(sizeof(drm_mga_private_t), DRM_MEM_DRIVER);
  404         if (!dev_priv)
  405                 return DRM_ERR(ENOMEM);
  406 
  407         dev->dev_private = (void *)dev_priv;
  408         memset(dev_priv, 0, sizeof(drm_mga_private_t));
  409 
  410         dev_priv->usec_timeout = MGA_DEFAULT_USEC_TIMEOUT;
  411         dev_priv->chipset = flags;
  412 
  413         dev_priv->mmio_base = drm_get_resource_start(dev, 1);
  414         dev_priv->mmio_size = drm_get_resource_len(dev, 1);
  415 
  416         dev->counters += 3;
  417         dev->types[6] = _DRM_STAT_IRQ;
  418         dev->types[7] = _DRM_STAT_PRIMARY;
  419         dev->types[8] = _DRM_STAT_SECONDARY;
  420 
  421         return 0;
  422 }
  423 
  424 /**
  425  * Bootstrap the driver for AGP DMA.
  426  * 
  427  * \todo
  428  * Investigate whether there is any benifit to storing the WARP microcode in
  429  * AGP memory.  If not, the microcode may as well always be put in PCI
  430  * memory.
  431  *
  432  * \todo
  433  * This routine needs to set dma_bs->agp_mode to the mode actually configured
  434  * in the hardware.  Looking just at the Linux AGP driver code, I don't see
  435  * an easy way to determine this.
  436  *
  437  * \sa mga_do_dma_bootstrap, mga_do_pci_dma_bootstrap
  438  */
  439 static int mga_do_agp_dma_bootstrap(drm_device_t * dev,
  440                                     drm_mga_dma_bootstrap_t * dma_bs)
  441 {
  442         drm_mga_private_t * const dev_priv = (drm_mga_private_t *) dev->dev_private;
  443         unsigned int warp_size = mga_warp_microcode_size(dev_priv);
  444         int err;
  445         unsigned  offset;
  446         const unsigned secondary_size = dma_bs->secondary_bin_count
  447                 * dma_bs->secondary_bin_size;
  448         const unsigned agp_size = (dma_bs->agp_size << 20);
  449         drm_buf_desc_t req;
  450         drm_agp_mode_t mode;
  451         drm_agp_info_t info;
  452         drm_agp_buffer_t agp_req;
  453         drm_agp_binding_t bind_req;
  454 
  455         /* Acquire AGP. */
  456         err = drm_agp_acquire(dev);
  457         if (err) {
  458                 DRM_ERROR("Unable to acquire AGP: %d\n", err);
  459                 return err;
  460         }
  461 
  462         err = drm_agp_info(dev, &info);
  463         if (err) {
  464                 DRM_ERROR("Unable to get AGP info: %d\n", err);
  465                 return err;
  466         }
  467 
  468         mode.mode = (info.mode & ~0x07) | dma_bs->agp_mode;
  469         err = drm_agp_enable(dev, mode);
  470         if (err) {
  471                 DRM_ERROR("Unable to enable AGP (mode = 0x%lx)\n", mode.mode);
  472                 return err;
  473         }
  474 
  475         /* In addition to the usual AGP mode configuration, the G200 AGP cards
  476          * need to have the AGP mode "manually" set.
  477          */
  478 
  479         if (dev_priv->chipset == MGA_CARD_TYPE_G200) {
  480                 if (mode.mode & 0x02) {
  481                         MGA_WRITE(MGA_AGP_PLL, MGA_AGP2XPLL_ENABLE);
  482                 } else {
  483                         MGA_WRITE(MGA_AGP_PLL, MGA_AGP2XPLL_DISABLE);
  484                 }
  485         }
  486 
  487 
  488         /* Allocate and bind AGP memory. */
  489         agp_req.size = agp_size;
  490         agp_req.type = 0;
  491         err = drm_agp_alloc( dev, & agp_req );
  492         if (err) {
  493                 dev_priv->agp_size = 0;
  494                 DRM_ERROR("Unable to allocate %uMB AGP memory\n",
  495                           dma_bs->agp_size);
  496                 return err;
  497         }
  498 
  499         dev_priv->agp_size = agp_size;
  500         dev_priv->agp_handle = agp_req.handle;
  501 
  502         bind_req.handle = agp_req.handle;
  503         bind_req.offset = 0;
  504         err = drm_agp_bind( dev, &bind_req );
  505         if (err) {
  506                 DRM_ERROR("Unable to bind AGP memory: %d\n", err);
  507                 return err;
  508         }
  509 
  510         /* Make drm_addbufs happy by not trying to create a mapping for less
  511          * than a page.
  512          */
  513         if (warp_size < PAGE_SIZE)
  514                 warp_size = PAGE_SIZE;
  515 
  516         offset = 0;
  517         err = drm_addmap( dev, offset, warp_size,
  518                           _DRM_AGP, _DRM_READ_ONLY, & dev_priv->warp );
  519         if (err) {
  520                 DRM_ERROR("Unable to map WARP microcode: %d\n", err);
  521                 return err;
  522         }
  523 
  524         offset += warp_size;
  525         err = drm_addmap( dev, offset, dma_bs->primary_size,
  526                           _DRM_AGP, _DRM_READ_ONLY, & dev_priv->primary );
  527         if (err) {
  528                 DRM_ERROR("Unable to map primary DMA region: %d\n", err);
  529                 return err;
  530         }
  531 
  532         offset += dma_bs->primary_size;
  533         err = drm_addmap( dev, offset, secondary_size,
  534                           _DRM_AGP, 0, & dev->agp_buffer_map );
  535         if (err) {
  536                 DRM_ERROR("Unable to map secondary DMA region: %d\n", err);
  537                 return err;
  538         }
  539 
  540         (void) memset( &req, 0, sizeof(req) );
  541         req.count = dma_bs->secondary_bin_count;
  542         req.size = dma_bs->secondary_bin_size;
  543         req.flags = _DRM_AGP_BUFFER;
  544         req.agp_start = offset;
  545 
  546         err = drm_addbufs_agp( dev, & req );
  547         if (err) {
  548                 DRM_ERROR("Unable to add secondary DMA buffers: %d\n", err);
  549                 return err;
  550         }
  551 
  552 #ifdef __linux__
  553         {
  554                 drm_map_list_t *_entry;
  555                 unsigned long agp_token = 0;
  556 
  557                 list_for_each_entry(_entry, &dev->maplist->head, head) {
  558                         if (_entry->map == dev->agp_buffer_map)
  559                                 agp_token = _entry->user_token;
  560                 }
  561                 if (!agp_token)
  562                         return -EFAULT;
  563 
  564                 dev->agp_buffer_token = agp_token;
  565         }
  566 #endif
  567 
  568         offset += secondary_size;
  569         err = drm_addmap( dev, offset, agp_size - offset,
  570                           _DRM_AGP, 0, & dev_priv->agp_textures );
  571         if (err) {
  572                 DRM_ERROR("Unable to map AGP texture region: %d\n", err);
  573                 return err;
  574         }
  575 
  576         drm_core_ioremap(dev_priv->warp, dev);
  577         drm_core_ioremap(dev_priv->primary, dev);
  578         drm_core_ioremap(dev->agp_buffer_map, dev);
  579 
  580         if (!dev_priv->warp->handle ||
  581             !dev_priv->primary->handle || !dev->agp_buffer_map->handle) {
  582                 DRM_ERROR("failed to ioremap agp regions! (%p, %p, %p)\n",
  583                           dev_priv->warp->handle, dev_priv->primary->handle,
  584                           dev->agp_buffer_map->handle);
  585                 return DRM_ERR(ENOMEM);
  586         }
  587 
  588         dev_priv->dma_access = MGA_PAGPXFER;
  589         dev_priv->wagp_enable = MGA_WAGP_ENABLE;
  590 
  591         DRM_INFO("Initialized card for AGP DMA.\n");
  592         return 0;
  593 }
  594 
  595 /**
  596  * Bootstrap the driver for PCI DMA.
  597  * 
  598  * \todo
  599  * The algorithm for decreasing the size of the primary DMA buffer could be
  600  * better.  The size should be rounded up to the nearest page size, then
  601  * decrease the request size by a single page each pass through the loop.
  602  *
  603  * \todo
  604  * Determine whether the maximum address passed to drm_pci_alloc is correct.
  605  * The same goes for drm_addbufs_pci.
  606  * 
  607  * \sa mga_do_dma_bootstrap, mga_do_agp_dma_bootstrap
  608  */
  609 static int mga_do_pci_dma_bootstrap(drm_device_t * dev,
  610                                     drm_mga_dma_bootstrap_t * dma_bs)
  611 {
  612         drm_mga_private_t * const dev_priv = (drm_mga_private_t *) dev->dev_private;
  613         unsigned int warp_size = mga_warp_microcode_size(dev_priv);
  614         unsigned int primary_size;
  615         unsigned int bin_count;
  616         int err;
  617         drm_buf_desc_t req;
  618 
  619         
  620         if (dev->dma == NULL) {
  621                 DRM_ERROR("dev->dma is NULL\n");
  622                 return DRM_ERR(EFAULT);
  623         }
  624 
  625         /* Make drm_addbufs happy by not trying to create a mapping for less
  626          * than a page.
  627          */
  628         if (warp_size < PAGE_SIZE)
  629                 warp_size = PAGE_SIZE;
  630 
  631         /* The proper alignment is 0x100 for this mapping */
  632         err = drm_addmap(dev, 0, warp_size, _DRM_CONSISTENT,
  633                          _DRM_READ_ONLY, &dev_priv->warp);
  634         if (err != 0) {
  635                 DRM_ERROR("Unable to create mapping for WARP microcode: %d\n",
  636                           err);
  637                 return err;
  638         }
  639 
  640         /* Other than the bottom two bits being used to encode other
  641          * information, there don't appear to be any restrictions on the
  642          * alignment of the primary or secondary DMA buffers.
  643          */
  644 
  645         for ( primary_size = dma_bs->primary_size
  646               ; primary_size != 0
  647               ; primary_size >>= 1 ) {
  648                 /* The proper alignment for this mapping is 0x04 */
  649                 err = drm_addmap(dev, 0, primary_size, _DRM_CONSISTENT,
  650                                  _DRM_READ_ONLY, &dev_priv->primary);
  651                 if (!err)
  652                         break;
  653         }
  654 
  655         if (err != 0) {
  656                 DRM_ERROR("Unable to allocate primary DMA region: %d\n", err);
  657                 return DRM_ERR(ENOMEM);
  658         }
  659 
  660         if (dev_priv->primary->size != dma_bs->primary_size) {
  661                 DRM_INFO("Primary DMA buffer size reduced from %u to %u.\n",
  662                          dma_bs->primary_size, 
  663                          (unsigned) dev_priv->primary->size);
  664                 dma_bs->primary_size = dev_priv->primary->size;
  665         }
  666 
  667         for ( bin_count = dma_bs->secondary_bin_count
  668               ; bin_count > 0 
  669               ; bin_count-- ) {
  670                 (void) memset( &req, 0, sizeof(req) );
  671                 req.count = bin_count;
  672                 req.size = dma_bs->secondary_bin_size;
  673 
  674                 err = drm_addbufs_pci( dev, & req );
  675                 if (!err) {
  676                         break;
  677                 }
  678         }
  679         
  680         if (bin_count == 0) {
  681                 DRM_ERROR("Unable to add secondary DMA buffers: %d\n", err);
  682                 return err;
  683         }
  684 
  685         if (bin_count != dma_bs->secondary_bin_count) {
  686                 DRM_INFO("Secondary PCI DMA buffer bin count reduced from %u "
  687                          "to %u.\n", dma_bs->secondary_bin_count, bin_count);
  688 
  689                 dma_bs->secondary_bin_count = bin_count;
  690         }
  691 
  692         dev_priv->dma_access = 0;
  693         dev_priv->wagp_enable = 0;
  694 
  695         dma_bs->agp_mode = 0;
  696 
  697         DRM_INFO("Initialized card for PCI DMA.\n");
  698         return 0;
  699 }
  700 
  701 
  702 static int mga_do_dma_bootstrap(drm_device_t * dev,
  703                                 drm_mga_dma_bootstrap_t * dma_bs)
  704 {
  705         const int is_agp = (dma_bs->agp_mode != 0) && drm_device_is_agp(dev);
  706         int err;
  707         drm_mga_private_t * const dev_priv =
  708                 (drm_mga_private_t *) dev->dev_private;
  709 
  710 
  711         dev_priv->used_new_dma_init = 1;
  712 
  713         /* The first steps are the same for both PCI and AGP based DMA.  Map
  714          * the cards MMIO registers and map a status page.
  715          */
  716         err = drm_addmap( dev, dev_priv->mmio_base, dev_priv->mmio_size,
  717                           _DRM_REGISTERS, _DRM_READ_ONLY, & dev_priv->mmio );
  718         if (err) {
  719                 DRM_ERROR("Unable to map MMIO region: %d\n", err);
  720                 return err;
  721         }
  722 
  723 
  724         err = drm_addmap( dev, 0, SAREA_MAX, _DRM_SHM,
  725                           _DRM_READ_ONLY | _DRM_LOCKED | _DRM_KERNEL,
  726                           & dev_priv->status );
  727         if (err) {
  728                 DRM_ERROR("Unable to map status region: %d\n", err);
  729                 return err;
  730         }
  731 
  732 
  733         /* The DMA initialization procedure is slightly different for PCI and
  734          * AGP cards.  AGP cards just allocate a large block of AGP memory and
  735          * carve off portions of it for internal uses.  The remaining memory
  736          * is returned to user-mode to be used for AGP textures.
  737          */
  738 
  739         if (is_agp) {
  740                 err = mga_do_agp_dma_bootstrap(dev, dma_bs);
  741         }
  742         
  743         /* If we attempted to initialize the card for AGP DMA but failed,
  744          * clean-up any mess that may have been created.
  745          */
  746 
  747         if (err) {
  748                 mga_do_cleanup_dma(dev, MINIMAL_CLEANUP);
  749         }
  750 
  751 
  752         /* Not only do we want to try and initialized PCI cards for PCI DMA,
  753          * but we also try to initialized AGP cards that could not be
  754          * initialized for AGP DMA.  This covers the case where we have an AGP
  755          * card in a system with an unsupported AGP chipset.  In that case the
  756          * card will be detected as AGP, but we won't be able to allocate any
  757          * AGP memory, etc.
  758          */
  759 
  760         if (!is_agp || err) {
  761                 err = mga_do_pci_dma_bootstrap(dev, dma_bs);
  762         }
  763 
  764 
  765         return err;
  766 }
  767 
  768 int mga_dma_bootstrap(DRM_IOCTL_ARGS)
  769 {
  770         DRM_DEVICE;
  771         drm_mga_dma_bootstrap_t bootstrap;
  772         int err;
  773         static const int modes[] = { 0, 1, 2, 2, 4, 4, 4, 4 };
  774         const drm_mga_private_t * const dev_priv = 
  775                 (drm_mga_private_t *) dev->dev_private;
  776 
  777 
  778         DRM_COPY_FROM_USER_IOCTL(bootstrap,
  779                                  (drm_mga_dma_bootstrap_t __user *) data,
  780                                  sizeof(bootstrap));
  781 
  782         err = mga_do_dma_bootstrap(dev, & bootstrap);
  783         if (err) {
  784                 mga_do_cleanup_dma(dev, FULL_CLEANUP);
  785                 return err;
  786         }
  787 
  788         if (dev_priv->agp_textures != NULL) {
  789                 bootstrap.texture_handle = dev_priv->agp_textures->offset;
  790                 bootstrap.texture_size = dev_priv->agp_textures->size;
  791         } else {
  792                 bootstrap.texture_handle = 0;
  793                 bootstrap.texture_size = 0;
  794         }
  795 
  796         bootstrap.agp_mode = modes[bootstrap.agp_mode & 0x07];
  797 
  798         DRM_COPY_TO_USER_IOCTL((drm_mga_dma_bootstrap_t __user *)data,
  799                                bootstrap, sizeof(bootstrap));
  800 
  801         return 0;
  802 }
  803 
  804 
  805 static int mga_do_init_dma(drm_device_t * dev, drm_mga_init_t * init)
  806 {
  807         drm_mga_private_t *dev_priv;
  808         int ret;
  809         DRM_DEBUG("\n");
  810 
  811 
  812         dev_priv = dev->dev_private;
  813 
  814         if (init->sgram) {
  815                 dev_priv->clear_cmd = MGA_DWGCTL_CLEAR | MGA_ATYPE_BLK;
  816         } else {
  817                 dev_priv->clear_cmd = MGA_DWGCTL_CLEAR | MGA_ATYPE_RSTR;
  818         }
  819         dev_priv->maccess = init->maccess;
  820 
  821         dev_priv->fb_cpp = init->fb_cpp;
  822         dev_priv->front_offset = init->front_offset;
  823         dev_priv->front_pitch = init->front_pitch;
  824         dev_priv->back_offset = init->back_offset;
  825         dev_priv->back_pitch = init->back_pitch;
  826 
  827         dev_priv->depth_cpp = init->depth_cpp;
  828         dev_priv->depth_offset = init->depth_offset;
  829         dev_priv->depth_pitch = init->depth_pitch;
  830 
  831         /* FIXME: Need to support AGP textures...
  832          */
  833         dev_priv->texture_offset = init->texture_offset[0];
  834         dev_priv->texture_size = init->texture_size[0];
  835 
  836         DRM_GETSAREA();
  837 
  838         if (!dev_priv->sarea) {
  839                 DRM_ERROR("failed to find sarea!\n");
  840                 return DRM_ERR(EINVAL);
  841         }
  842 
  843         if (! dev_priv->used_new_dma_init) {
  844 
  845                 dev_priv->dma_access = MGA_PAGPXFER;
  846                 dev_priv->wagp_enable = MGA_WAGP_ENABLE;
  847 
  848                 dev_priv->status = drm_core_findmap(dev, init->status_offset);
  849                 if (!dev_priv->status) {
  850                         DRM_ERROR("failed to find status page!\n");
  851                         return DRM_ERR(EINVAL);
  852                 }
  853                 dev_priv->mmio = drm_core_findmap(dev, init->mmio_offset);
  854                 if (!dev_priv->mmio) {
  855                         DRM_ERROR("failed to find mmio region!\n");
  856                         return DRM_ERR(EINVAL);
  857                 }
  858                 dev_priv->warp = drm_core_findmap(dev, init->warp_offset);
  859                 if (!dev_priv->warp) {
  860                         DRM_ERROR("failed to find warp microcode region!\n");
  861                         return DRM_ERR(EINVAL);
  862                 }
  863                 dev_priv->primary = drm_core_findmap(dev, init->primary_offset);
  864                 if (!dev_priv->primary) {
  865                         DRM_ERROR("failed to find primary dma region!\n");
  866                         return DRM_ERR(EINVAL);
  867                 }
  868                 dev->agp_buffer_token = init->buffers_offset;
  869                 dev->agp_buffer_map = drm_core_findmap(dev, init->buffers_offset);
  870                 if (!dev->agp_buffer_map) {
  871                         DRM_ERROR("failed to find dma buffer region!\n");
  872                         return DRM_ERR(EINVAL);
  873                 }
  874 
  875                 drm_core_ioremap(dev_priv->warp, dev);
  876                 drm_core_ioremap(dev_priv->primary, dev);
  877                 drm_core_ioremap(dev->agp_buffer_map, dev);
  878         }
  879 
  880         dev_priv->sarea_priv =
  881             (drm_mga_sarea_t *) ((u8 *) dev_priv->sarea->handle +
  882                                  init->sarea_priv_offset);
  883 
  884         if (!dev_priv->warp->handle ||
  885             !dev_priv->primary->handle ||
  886             ((dev_priv->dma_access != 0) &&
  887              ((dev->agp_buffer_map == NULL) ||
  888               (dev->agp_buffer_map->handle == NULL)))) {
  889                 DRM_ERROR("failed to ioremap agp regions!\n");
  890                 return DRM_ERR(ENOMEM);
  891         }
  892 
  893         ret = mga_warp_install_microcode(dev_priv);
  894         if (ret != 0) {
  895                 DRM_ERROR("failed to install WARP ucode: %d!\n", ret);
  896                 return ret;
  897         }
  898 
  899         ret = mga_warp_init(dev_priv);
  900         if (ret != 0) {
  901                 DRM_ERROR("failed to init WARP engine: %d!\n", ret);
  902                 return ret;
  903         }
  904 
  905         dev_priv->prim.status = (u32 *) dev_priv->status->handle;
  906 
  907         mga_do_wait_for_idle(dev_priv);
  908 
  909         /* Init the primary DMA registers.
  910          */
  911         MGA_WRITE(MGA_PRIMADDRESS, dev_priv->primary->offset | MGA_DMA_GENERAL);
  912 #if 0
  913         MGA_WRITE(MGA_PRIMPTR, virt_to_bus((void *)dev_priv->prim.status) | MGA_PRIMPTREN0 |    /* Soft trap, SECEND, SETUPEND */
  914                   MGA_PRIMPTREN1);      /* DWGSYNC */
  915 #endif
  916 
  917         dev_priv->prim.start = (u8 *) dev_priv->primary->handle;
  918         dev_priv->prim.end = ((u8 *) dev_priv->primary->handle
  919                               + dev_priv->primary->size);
  920         dev_priv->prim.size = dev_priv->primary->size;
  921 
  922         dev_priv->prim.tail = 0;
  923         dev_priv->prim.space = dev_priv->prim.size;
  924         dev_priv->prim.wrapped = 0;
  925 
  926         dev_priv->prim.last_flush = 0;
  927         dev_priv->prim.last_wrap = 0;
  928 
  929         dev_priv->prim.high_mark = 256 * DMA_BLOCK_SIZE;
  930 
  931         dev_priv->prim.status[0] = dev_priv->primary->offset;
  932         dev_priv->prim.status[1] = 0;
  933 
  934         dev_priv->sarea_priv->last_wrap = 0;
  935         dev_priv->sarea_priv->last_frame.head = 0;
  936         dev_priv->sarea_priv->last_frame.wrap = 0;
  937 
  938         if (mga_freelist_init(dev, dev_priv) < 0) {
  939                 DRM_ERROR("could not initialize freelist\n");
  940                 return DRM_ERR(ENOMEM);
  941         }
  942 
  943         return 0;
  944 }
  945 
  946 static int mga_do_cleanup_dma(drm_device_t * dev, int full_cleanup)
  947 {
  948         int err = 0;
  949         DRM_DEBUG("\n");
  950 
  951         /* Make sure interrupts are disabled here because the uninstall ioctl
  952          * may not have been called from userspace and after dev_private
  953          * is freed, it's too late.
  954          */
  955         if (dev->irq_enabled)
  956                 drm_irq_uninstall(dev);
  957 
  958         if (dev->dev_private) {
  959                 drm_mga_private_t *dev_priv = dev->dev_private;
  960 
  961                 if ((dev_priv->warp != NULL)
  962                     && (dev_priv->warp->type != _DRM_CONSISTENT))
  963                         drm_core_ioremapfree(dev_priv->warp, dev);
  964 
  965                 if ((dev_priv->primary != NULL) 
  966                     && (dev_priv->primary->type != _DRM_CONSISTENT))
  967                         drm_core_ioremapfree(dev_priv->primary, dev);
  968 
  969                 if (dev->agp_buffer_map != NULL)
  970                         drm_core_ioremapfree(dev->agp_buffer_map, dev);
  971 
  972                 if (dev_priv->used_new_dma_init) {
  973                         if (dev_priv->agp_handle != 0) {
  974                                 drm_agp_binding_t unbind_req;
  975                                 drm_agp_buffer_t free_req;
  976 
  977                                 unbind_req.handle = dev_priv->agp_handle;
  978                                 drm_agp_unbind(dev, &unbind_req);
  979 
  980                                 free_req.handle = dev_priv->agp_handle;
  981                                 drm_agp_free(dev, &free_req);
  982 
  983                                 dev_priv->agp_textures = NULL;
  984                                 dev_priv->agp_size = 0;
  985                                 dev_priv->agp_handle = 0;
  986                         }
  987 
  988                         if ((dev->agp != NULL) && dev->agp->acquired) {
  989                                 err = drm_agp_release(dev);
  990                         }
  991                 }
  992 
  993                 dev_priv->warp = NULL;
  994                 dev_priv->primary = NULL;
  995                 dev_priv->sarea = NULL;
  996                 dev_priv->sarea_priv = NULL;
  997                 dev->agp_buffer_map = NULL;
  998 
  999                 if (full_cleanup) {
 1000                         dev_priv->mmio = NULL;
 1001                         dev_priv->status = NULL;
 1002                         dev_priv->used_new_dma_init = 0;
 1003                 }
 1004 
 1005                 memset(&dev_priv->prim, 0, sizeof(dev_priv->prim));
 1006                 dev_priv->warp_pipe = 0;
 1007                 memset(dev_priv->warp_pipe_phys, 0, sizeof(dev_priv->warp_pipe_phys));
 1008 
 1009                 if (dev_priv->head != NULL) {
 1010                         mga_freelist_cleanup(dev);
 1011                 }
 1012         }
 1013 
 1014         return 0;
 1015 }
 1016 
 1017 int mga_dma_init(DRM_IOCTL_ARGS)
 1018 {
 1019         DRM_DEVICE;
 1020         drm_mga_init_t init;
 1021         int err;
 1022 
 1023         LOCK_TEST_WITH_RETURN(dev, filp);
 1024 
 1025         DRM_COPY_FROM_USER_IOCTL(init, (drm_mga_init_t __user *) data,
 1026                                  sizeof(init));
 1027 
 1028         switch (init.func) {
 1029         case MGA_INIT_DMA:
 1030                 err = mga_do_init_dma(dev, &init);
 1031                 if (err) {
 1032                         (void) mga_do_cleanup_dma(dev, FULL_CLEANUP);
 1033                 }
 1034                 return err;
 1035         case MGA_CLEANUP_DMA:
 1036                 return mga_do_cleanup_dma(dev, FULL_CLEANUP);
 1037         }
 1038 
 1039         return DRM_ERR(EINVAL);
 1040 }
 1041 
 1042 /* ================================================================
 1043  * Primary DMA stream management
 1044  */
 1045 
 1046 int mga_dma_flush(DRM_IOCTL_ARGS)
 1047 {
 1048         DRM_DEVICE;
 1049         drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
 1050         drm_lock_t lock;
 1051 
 1052         LOCK_TEST_WITH_RETURN(dev, filp);
 1053 
 1054         DRM_COPY_FROM_USER_IOCTL(lock, (drm_lock_t __user *) data,
 1055                                  sizeof(lock));
 1056 
 1057         DRM_DEBUG("%s%s%s\n",
 1058                   (lock.flags & _DRM_LOCK_FLUSH) ? "flush, " : "",
 1059                   (lock.flags & _DRM_LOCK_FLUSH_ALL) ? "flush all, " : "",
 1060                   (lock.flags & _DRM_LOCK_QUIESCENT) ? "idle, " : "");
 1061 
 1062         WRAP_WAIT_WITH_RETURN(dev_priv);
 1063 
 1064         if (lock.flags & (_DRM_LOCK_FLUSH | _DRM_LOCK_FLUSH_ALL)) {
 1065                 mga_do_dma_flush(dev_priv);
 1066         }
 1067 
 1068         if (lock.flags & _DRM_LOCK_QUIESCENT) {
 1069 #if MGA_DMA_DEBUG
 1070                 int ret = mga_do_wait_for_idle(dev_priv);
 1071                 if (ret < 0)
 1072                         DRM_INFO("%s: -EBUSY\n", __FUNCTION__);
 1073                 return ret;
 1074 #else
 1075                 return mga_do_wait_for_idle(dev_priv);
 1076 #endif
 1077         } else {
 1078                 return 0;
 1079         }
 1080 }
 1081 
 1082 int mga_dma_reset(DRM_IOCTL_ARGS)
 1083 {
 1084         DRM_DEVICE;
 1085         drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
 1086 
 1087         LOCK_TEST_WITH_RETURN(dev, filp);
 1088 
 1089         return mga_do_dma_reset(dev_priv);
 1090 }
 1091 
 1092 /* ================================================================
 1093  * DMA buffer management
 1094  */
 1095 
 1096 static int mga_dma_get_buffers(DRMFILE filp, drm_device_t * dev, drm_dma_t * d)
 1097 {
 1098         drm_buf_t *buf;
 1099         int i;
 1100 
 1101         for (i = d->granted_count; i < d->request_count; i++) {
 1102                 buf = mga_freelist_get(dev);
 1103                 if (!buf)
 1104                         return DRM_ERR(EAGAIN);
 1105 
 1106                 buf->filp = filp;
 1107 
 1108                 if (DRM_COPY_TO_USER(&d->request_indices[i],
 1109                                      &buf->idx, sizeof(buf->idx)))
 1110                         return DRM_ERR(EFAULT);
 1111                 if (DRM_COPY_TO_USER(&d->request_sizes[i],
 1112                                      &buf->total, sizeof(buf->total)))
 1113                         return DRM_ERR(EFAULT);
 1114 
 1115                 d->granted_count++;
 1116         }
 1117         return 0;
 1118 }
 1119 
 1120 int mga_dma_buffers(DRM_IOCTL_ARGS)
 1121 {
 1122         DRM_DEVICE;
 1123         drm_device_dma_t *dma = dev->dma;
 1124         drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
 1125         drm_dma_t __user *argp = (void __user *)data;
 1126         drm_dma_t d;
 1127         int ret = 0;
 1128 
 1129         LOCK_TEST_WITH_RETURN(dev, filp);
 1130 
 1131         DRM_COPY_FROM_USER_IOCTL(d, argp, sizeof(d));
 1132 
 1133         /* Please don't send us buffers.
 1134          */
 1135         if (d.send_count != 0) {
 1136                 DRM_ERROR("Process %d trying to send %d buffers via drmDMA\n",
 1137                           DRM_CURRENTPID, d.send_count);
 1138                 return DRM_ERR(EINVAL);
 1139         }
 1140 
 1141         /* We'll send you buffers.
 1142          */
 1143         if (d.request_count < 0 || d.request_count > dma->buf_count) {
 1144                 DRM_ERROR("Process %d trying to get %d buffers (of %d max)\n",
 1145                           DRM_CURRENTPID, d.request_count, dma->buf_count);
 1146                 return DRM_ERR(EINVAL);
 1147         }
 1148 
 1149         WRAP_TEST_WITH_RETURN(dev_priv);
 1150 
 1151         d.granted_count = 0;
 1152 
 1153         if (d.request_count) {
 1154                 ret = mga_dma_get_buffers(filp, dev, &d);
 1155         }
 1156 
 1157         DRM_COPY_TO_USER_IOCTL(argp, d, sizeof(d));
 1158 
 1159         return ret;
 1160 }
 1161 
 1162 /**
 1163  * Called just before the module is unloaded.
 1164  */
 1165 int mga_driver_unload(drm_device_t * dev)
 1166 {
 1167         drm_free(dev->dev_private, sizeof(drm_mga_private_t), DRM_MEM_DRIVER);
 1168         dev->dev_private = NULL;
 1169 
 1170         return 0;
 1171 }
 1172 
 1173 /**
 1174  * Called when the last opener of the device is closed.
 1175  */
 1176 void mga_driver_lastclose(drm_device_t * dev)
 1177 {
 1178         mga_do_cleanup_dma(dev, FULL_CLEANUP);
 1179 }
 1180 
 1181 int mga_driver_dma_quiescent(drm_device_t * dev)
 1182 {
 1183         drm_mga_private_t *dev_priv = dev->dev_private;
 1184         return mga_do_wait_for_idle(dev_priv);
 1185 }

Cache object: 4be144bcfc9c5eafc51b6cd944ef89c8


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.