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$");
   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(struct drm_device *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 -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(struct drm_device * 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(struct drm_device * dev, drm_mga_private_t * dev_priv)
  252 {
  253         struct drm_device_dma *dma = dev->dma;
  254         struct drm_buf *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 -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 -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(struct drm_device * 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(struct drm_device * dev)
  318 {
  319         drm_device_dma_t *dma = dev->dma;
  320         struct drm_buf *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 struct drm_buf *mga_freelist_get(struct drm_device * 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(struct drm_device * dev, struct drm_buf * 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(struct drm_device *dev, unsigned long flags)
  400 {
  401         drm_mga_private_t *dev_priv;
  402         int ret;
  403 
  404         dev_priv = drm_alloc(sizeof(drm_mga_private_t), DRM_MEM_DRIVER);
  405         if (!dev_priv)
  406                 return -ENOMEM;
  407 
  408         dev->dev_private = (void *)dev_priv;
  409         memset(dev_priv, 0, sizeof(drm_mga_private_t));
  410 
  411         dev_priv->usec_timeout = MGA_DEFAULT_USEC_TIMEOUT;
  412         dev_priv->chipset = flags;
  413 
  414         dev_priv->mmio_base = drm_get_resource_start(dev, 1);
  415         dev_priv->mmio_size = drm_get_resource_len(dev, 1);
  416 
  417         dev->counters += 3;
  418         dev->types[6] = _DRM_STAT_IRQ;
  419         dev->types[7] = _DRM_STAT_PRIMARY;
  420         dev->types[8] = _DRM_STAT_SECONDARY;
  421 
  422         ret = drm_vblank_init(dev, 1);
  423 
  424         if (ret) {
  425                 (void) mga_driver_unload(dev);
  426                 return ret;
  427         }
  428 
  429         return 0;
  430 }
  431 
  432 /**
  433  * Bootstrap the driver for AGP DMA.
  434  *
  435  * \todo
  436  * Investigate whether there is any benifit to storing the WARP microcode in
  437  * AGP memory.  If not, the microcode may as well always be put in PCI
  438  * memory.
  439  *
  440  * \todo
  441  * This routine needs to set dma_bs->agp_mode to the mode actually configured
  442  * in the hardware.  Looking just at the Linux AGP driver code, I don't see
  443  * an easy way to determine this.
  444  *
  445  * \sa mga_do_dma_bootstrap, mga_do_pci_dma_bootstrap
  446  */
  447 static int mga_do_agp_dma_bootstrap(struct drm_device *dev,
  448                                     drm_mga_dma_bootstrap_t * dma_bs)
  449 {
  450         drm_mga_private_t *const dev_priv =
  451                 (drm_mga_private_t *)dev->dev_private;
  452         unsigned int warp_size = mga_warp_microcode_size(dev_priv);
  453         int err;
  454         unsigned offset;
  455         const unsigned secondary_size = dma_bs->secondary_bin_count
  456                 * dma_bs->secondary_bin_size;
  457         const unsigned agp_size = (dma_bs->agp_size << 20);
  458         struct drm_buf_desc req;
  459         struct drm_agp_mode mode;
  460         struct drm_agp_info info;
  461         struct drm_agp_buffer agp_req;
  462         struct drm_agp_binding bind_req;
  463 
  464         /* Acquire AGP. */
  465         err = drm_agp_acquire(dev);
  466         if (err) {
  467                 DRM_ERROR("Unable to acquire AGP: %d\n", err);
  468                 return err;
  469         }
  470 
  471         err = drm_agp_info(dev, &info);
  472         if (err) {
  473                 DRM_ERROR("Unable to get AGP info: %d\n", err);
  474                 return err;
  475         }
  476 
  477         mode.mode = (info.mode & ~0x07) | dma_bs->agp_mode;
  478         err = drm_agp_enable(dev, mode);
  479         if (err) {
  480                 DRM_ERROR("Unable to enable AGP (mode = 0x%lx)\n", mode.mode);
  481                 return err;
  482         }
  483 
  484         /* In addition to the usual AGP mode configuration, the G200 AGP cards
  485          * need to have the AGP mode "manually" set.
  486          */
  487 
  488         if (dev_priv->chipset == MGA_CARD_TYPE_G200) {
  489                 if (mode.mode & 0x02) {
  490                         MGA_WRITE(MGA_AGP_PLL, MGA_AGP2XPLL_ENABLE);
  491                 } else {
  492                         MGA_WRITE(MGA_AGP_PLL, MGA_AGP2XPLL_DISABLE);
  493                 }
  494         }
  495 
  496         /* Allocate and bind AGP memory. */
  497         agp_req.size = agp_size;
  498         agp_req.type = 0;
  499         err = drm_agp_alloc(dev, &agp_req);
  500         if (err) {
  501                 dev_priv->agp_size = 0;
  502                 DRM_ERROR("Unable to allocate %uMB AGP memory\n",
  503                           dma_bs->agp_size);
  504                 return err;
  505         }
  506 
  507         dev_priv->agp_size = agp_size;
  508         dev_priv->agp_handle = agp_req.handle;
  509 
  510         bind_req.handle = agp_req.handle;
  511         bind_req.offset = 0;
  512         err = drm_agp_bind( dev, &bind_req );
  513         if (err) {
  514                 DRM_ERROR("Unable to bind AGP memory: %d\n", err);
  515                 return err;
  516         }
  517 
  518         /* Make drm_addbufs happy by not trying to create a mapping for less
  519          * than a page.
  520          */
  521         if (warp_size < PAGE_SIZE)
  522                 warp_size = PAGE_SIZE;
  523 
  524         offset = 0;
  525         err = drm_addmap(dev, offset, warp_size,
  526                          _DRM_AGP, _DRM_READ_ONLY, &dev_priv->warp);
  527         if (err) {
  528                 DRM_ERROR("Unable to map WARP microcode: %d\n", err);
  529                 return err;
  530         }
  531 
  532         offset += warp_size;
  533         err = drm_addmap(dev, offset, dma_bs->primary_size,
  534                          _DRM_AGP, _DRM_READ_ONLY, & dev_priv->primary);
  535         if (err) {
  536                 DRM_ERROR("Unable to map primary DMA region: %d\n", err);
  537                 return err;
  538         }
  539 
  540         offset += dma_bs->primary_size;
  541         err = drm_addmap(dev, offset, secondary_size,
  542                          _DRM_AGP, 0, & dev->agp_buffer_map);
  543         if (err) {
  544                 DRM_ERROR("Unable to map secondary DMA region: %d\n", err);
  545                 return err;
  546         }
  547 
  548         (void)memset( &req, 0, sizeof(req) );
  549         req.count = dma_bs->secondary_bin_count;
  550         req.size = dma_bs->secondary_bin_size;
  551         req.flags = _DRM_AGP_BUFFER;
  552         req.agp_start = offset;
  553 
  554         err = drm_addbufs_agp(dev, &req);
  555         if (err) {
  556                 DRM_ERROR("Unable to add secondary DMA buffers: %d\n", err);
  557                 return err;
  558         }
  559 
  560 #ifdef __linux__
  561         {
  562                 struct drm_map_list *_entry;
  563                 unsigned long agp_token = 0;
  564 
  565                 list_for_each_entry(_entry, &dev->maplist, head) {
  566                         if (_entry->map == dev->agp_buffer_map)
  567                                 agp_token = _entry->user_token;
  568                 }
  569                 if (!agp_token)
  570                         return -EFAULT;
  571 
  572                 dev->agp_buffer_token = agp_token;
  573         }
  574 #endif
  575 
  576         offset += secondary_size;
  577         err = drm_addmap(dev, offset, agp_size - offset,
  578                          _DRM_AGP, 0, & dev_priv->agp_textures);
  579         if (err) {
  580                 DRM_ERROR("Unable to map AGP texture region: %d\n", err);
  581                 return err;
  582         }
  583 
  584         drm_core_ioremap(dev_priv->warp, dev);
  585         drm_core_ioremap(dev_priv->primary, dev);
  586         drm_core_ioremap(dev->agp_buffer_map, dev);
  587 
  588         if (!dev_priv->warp->virtual ||
  589             !dev_priv->primary->virtual || !dev->agp_buffer_map->virtual) {
  590                 DRM_ERROR("failed to ioremap agp regions! (%p, %p, %p)\n",
  591                           dev_priv->warp->virtual, dev_priv->primary->virtual,
  592                           dev->agp_buffer_map->virtual);
  593                 return -ENOMEM;
  594         }
  595 
  596         dev_priv->dma_access = MGA_PAGPXFER;
  597         dev_priv->wagp_enable = MGA_WAGP_ENABLE;
  598 
  599         DRM_INFO("Initialized card for AGP DMA.\n");
  600         return 0;
  601 }
  602 
  603 /**
  604  * Bootstrap the driver for PCI DMA.
  605  *
  606  * \todo
  607  * The algorithm for decreasing the size of the primary DMA buffer could be
  608  * better.  The size should be rounded up to the nearest page size, then
  609  * decrease the request size by a single page each pass through the loop.
  610  *
  611  * \todo
  612  * Determine whether the maximum address passed to drm_pci_alloc is correct.
  613  * The same goes for drm_addbufs_pci.
  614  *
  615  * \sa mga_do_dma_bootstrap, mga_do_agp_dma_bootstrap
  616  */
  617 static int mga_do_pci_dma_bootstrap(struct drm_device * dev,
  618                                     drm_mga_dma_bootstrap_t * dma_bs)
  619 {
  620         drm_mga_private_t *const dev_priv =
  621                 (drm_mga_private_t *) dev->dev_private;
  622         unsigned int warp_size = mga_warp_microcode_size(dev_priv);
  623         unsigned int primary_size;
  624         unsigned int bin_count;
  625         int err;
  626         struct drm_buf_desc req;
  627 
  628 
  629         if (dev->dma == NULL) {
  630                 DRM_ERROR("dev->dma is NULL\n");
  631                 return -EFAULT;
  632         }
  633 
  634         /* Make drm_addbufs happy by not trying to create a mapping for less
  635          * than a page.
  636          */
  637         if (warp_size < PAGE_SIZE)
  638                 warp_size = PAGE_SIZE;
  639 
  640         /* The proper alignment is 0x100 for this mapping */
  641         err = drm_addmap(dev, 0, warp_size, _DRM_CONSISTENT,
  642                          _DRM_READ_ONLY, &dev_priv->warp);
  643         if (err != 0) {
  644                 DRM_ERROR("Unable to create mapping for WARP microcode: %d\n",
  645                           err);
  646                 return err;
  647         }
  648 
  649         /* Other than the bottom two bits being used to encode other
  650          * information, there don't appear to be any restrictions on the
  651          * alignment of the primary or secondary DMA buffers.
  652          */
  653 
  654         for (primary_size = dma_bs->primary_size; primary_size != 0;
  655              primary_size >>= 1 ) {
  656                 /* The proper alignment for this mapping is 0x04 */
  657                 err = drm_addmap(dev, 0, primary_size, _DRM_CONSISTENT,
  658                                  _DRM_READ_ONLY, &dev_priv->primary);
  659                 if (!err)
  660                         break;
  661         }
  662 
  663         if (err != 0) {
  664                 DRM_ERROR("Unable to allocate primary DMA region: %d\n", err);
  665                 return -ENOMEM;
  666         }
  667 
  668         if (dev_priv->primary->size != dma_bs->primary_size) {
  669                 DRM_INFO("Primary DMA buffer size reduced from %u to %u.\n",
  670                          dma_bs->primary_size,
  671                          (unsigned)dev_priv->primary->size);
  672                 dma_bs->primary_size = dev_priv->primary->size;
  673         }
  674 
  675         for (bin_count = dma_bs->secondary_bin_count; bin_count > 0;
  676              bin_count-- ) {
  677                 (void)memset(&req, 0, sizeof(req));
  678                 req.count = bin_count;
  679                 req.size = dma_bs->secondary_bin_size;
  680 
  681                 err = drm_addbufs_pci(dev, &req);
  682                 if (!err) {
  683                         break;
  684                 }
  685         }
  686 
  687         if (bin_count == 0) {
  688                 DRM_ERROR("Unable to add secondary DMA buffers: %d\n", err);
  689                 return err;
  690         }
  691 
  692         if (bin_count != dma_bs->secondary_bin_count) {
  693                 DRM_INFO("Secondary PCI DMA buffer bin count reduced from %u "
  694                          "to %u.\n", dma_bs->secondary_bin_count, bin_count);
  695 
  696                 dma_bs->secondary_bin_count = bin_count;
  697         }
  698 
  699         dev_priv->dma_access = 0;
  700         dev_priv->wagp_enable = 0;
  701 
  702         dma_bs->agp_mode = 0;
  703 
  704         DRM_INFO("Initialized card for PCI DMA.\n");
  705         return 0;
  706 }
  707 
  708 
  709 static int mga_do_dma_bootstrap(struct drm_device *dev,
  710                                 drm_mga_dma_bootstrap_t *dma_bs)
  711 {
  712         const int is_agp = (dma_bs->agp_mode != 0) && drm_device_is_agp(dev);
  713         int err;
  714         drm_mga_private_t *const dev_priv =
  715                 (drm_mga_private_t *) dev->dev_private;
  716 
  717 
  718         dev_priv->used_new_dma_init = 1;
  719 
  720         /* The first steps are the same for both PCI and AGP based DMA.  Map
  721          * the cards MMIO registers and map a status page.
  722          */
  723         err = drm_addmap(dev, dev_priv->mmio_base, dev_priv->mmio_size,
  724                          _DRM_REGISTERS, _DRM_READ_ONLY, & dev_priv->mmio);
  725         if (err) {
  726                 DRM_ERROR("Unable to map MMIO region: %d\n", err);
  727                 return err;
  728         }
  729 
  730 
  731         err = drm_addmap(dev, 0, SAREA_MAX, _DRM_SHM,
  732                          _DRM_READ_ONLY | _DRM_LOCKED | _DRM_KERNEL,
  733                          & dev_priv->status);
  734         if (err) {
  735                 DRM_ERROR("Unable to map status region: %d\n", err);
  736                 return err;
  737         }
  738 
  739 
  740         /* The DMA initialization procedure is slightly different for PCI and
  741          * AGP cards.  AGP cards just allocate a large block of AGP memory and
  742          * carve off portions of it for internal uses.  The remaining memory
  743          * is returned to user-mode to be used for AGP textures.
  744          */
  745 
  746         if (is_agp) {
  747                 err = mga_do_agp_dma_bootstrap(dev, dma_bs);
  748         }
  749 
  750         /* If we attempted to initialize the card for AGP DMA but failed,
  751          * clean-up any mess that may have been created.
  752          */
  753 
  754         if (err) {
  755                 mga_do_cleanup_dma(dev, MINIMAL_CLEANUP);
  756         }
  757 
  758 
  759         /* Not only do we want to try and initialized PCI cards for PCI DMA,
  760          * but we also try to initialized AGP cards that could not be
  761          * initialized for AGP DMA.  This covers the case where we have an AGP
  762          * card in a system with an unsupported AGP chipset.  In that case the
  763          * card will be detected as AGP, but we won't be able to allocate any
  764          * AGP memory, etc.
  765          */
  766 
  767         if (!is_agp || err) {
  768                 err = mga_do_pci_dma_bootstrap(dev, dma_bs);
  769         }
  770 
  771 
  772         return err;
  773 }
  774 
  775 int mga_dma_bootstrap(struct drm_device *dev, void *data,
  776                       struct drm_file *file_priv)
  777 {
  778         drm_mga_dma_bootstrap_t *bootstrap = data;
  779         int err;
  780         static const int modes[] = { 0, 1, 2, 2, 4, 4, 4, 4 };
  781         const drm_mga_private_t *const dev_priv =
  782                 (drm_mga_private_t *) dev->dev_private;
  783 
  784 
  785         err = mga_do_dma_bootstrap(dev, bootstrap);
  786         if (err) {
  787                 mga_do_cleanup_dma(dev, FULL_CLEANUP);
  788                 return err;
  789         }
  790 
  791         if (dev_priv->agp_textures != NULL) {
  792                 bootstrap->texture_handle = dev_priv->agp_textures->offset;
  793                 bootstrap->texture_size = dev_priv->agp_textures->size;
  794         } else {
  795                 bootstrap->texture_handle = 0;
  796                 bootstrap->texture_size = 0;
  797         }
  798 
  799         bootstrap->agp_mode = modes[bootstrap->agp_mode & 0x07];
  800 
  801         return 0;
  802 }
  803 
  804 
  805 static int mga_do_init_dma(struct drm_device * 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         dev_priv->sarea = drm_getsarea(dev);
  837         if (!dev_priv->sarea) {
  838                 DRM_ERROR("failed to find sarea!\n");
  839                 return -EINVAL;
  840         }
  841 
  842         if (!dev_priv->used_new_dma_init) {
  843 
  844                 dev_priv->dma_access = MGA_PAGPXFER;
  845                 dev_priv->wagp_enable = MGA_WAGP_ENABLE;
  846 
  847                 dev_priv->status = drm_core_findmap(dev, init->status_offset);
  848                 if (!dev_priv->status) {
  849                         DRM_ERROR("failed to find status page!\n");
  850                         return -EINVAL;
  851                 }
  852                 dev_priv->mmio = drm_core_findmap(dev, init->mmio_offset);
  853                 if (!dev_priv->mmio) {
  854                         DRM_ERROR("failed to find mmio region!\n");
  855                         return -EINVAL;
  856                 }
  857                 dev_priv->warp = drm_core_findmap(dev, init->warp_offset);
  858                 if (!dev_priv->warp) {
  859                         DRM_ERROR("failed to find warp microcode region!\n");
  860                         return -EINVAL;
  861                 }
  862                 dev_priv->primary = drm_core_findmap(dev, init->primary_offset);
  863                 if (!dev_priv->primary) {
  864                         DRM_ERROR("failed to find primary dma region!\n");
  865                         return -EINVAL;
  866                 }
  867                 dev->agp_buffer_token = init->buffers_offset;
  868                 dev->agp_buffer_map =
  869                         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 -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->virtual +
  882                                  init->sarea_priv_offset);
  883 
  884         if (!dev_priv->warp->virtual ||
  885             !dev_priv->primary->virtual ||
  886             ((dev_priv->dma_access != 0) &&
  887              ((dev->agp_buffer_map == NULL) ||
  888               (dev->agp_buffer_map->virtual == NULL)))) {
  889                 DRM_ERROR("failed to ioremap agp regions!\n");
  890                 return -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->virtual;
  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 
  913         dev_priv->prim.start = (u8 *) dev_priv->primary->virtual;
  914         dev_priv->prim.end = ((u8 *) dev_priv->primary->virtual
  915                               + dev_priv->primary->size);
  916         dev_priv->prim.size = dev_priv->primary->size;
  917 
  918         dev_priv->prim.tail = 0;
  919         dev_priv->prim.space = dev_priv->prim.size;
  920         dev_priv->prim.wrapped = 0;
  921 
  922         dev_priv->prim.last_flush = 0;
  923         dev_priv->prim.last_wrap = 0;
  924 
  925         dev_priv->prim.high_mark = 256 * DMA_BLOCK_SIZE;
  926 
  927         dev_priv->prim.status[0] = dev_priv->primary->offset;
  928         dev_priv->prim.status[1] = 0;
  929 
  930         dev_priv->sarea_priv->last_wrap = 0;
  931         dev_priv->sarea_priv->last_frame.head = 0;
  932         dev_priv->sarea_priv->last_frame.wrap = 0;
  933 
  934         if (mga_freelist_init(dev, dev_priv) < 0) {
  935                 DRM_ERROR("could not initialize freelist\n");
  936                 return -ENOMEM;
  937         }
  938 
  939         return 0;
  940 }
  941 
  942 static int mga_do_cleanup_dma(struct drm_device *dev, int full_cleanup)
  943 {
  944         int err = 0;
  945         DRM_DEBUG("\n");
  946 
  947         /* Make sure interrupts are disabled here because the uninstall ioctl
  948          * may not have been called from userspace and after dev_private
  949          * is freed, it's too late.
  950          */
  951         if (dev->irq_enabled)
  952                 drm_irq_uninstall(dev);
  953 
  954         if (dev->dev_private) {
  955                 drm_mga_private_t *dev_priv = dev->dev_private;
  956 
  957                 if ((dev_priv->warp != NULL)
  958                     && (dev_priv->warp->type != _DRM_CONSISTENT))
  959                         drm_core_ioremapfree(dev_priv->warp, dev);
  960 
  961                 if ((dev_priv->primary != NULL)
  962                     && (dev_priv->primary->type != _DRM_CONSISTENT))
  963                         drm_core_ioremapfree(dev_priv->primary, dev);
  964 
  965                 if (dev->agp_buffer_map != NULL)
  966                         drm_core_ioremapfree(dev->agp_buffer_map, dev);
  967 
  968                 if (dev_priv->used_new_dma_init) {
  969                         if (dev_priv->agp_handle != 0) {
  970                                 struct drm_agp_binding unbind_req;
  971                                 struct drm_agp_buffer free_req;
  972 
  973                                 unbind_req.handle = dev_priv->agp_handle;
  974                                 drm_agp_unbind(dev, &unbind_req);
  975 
  976                                 free_req.handle = dev_priv->agp_handle;
  977                                 drm_agp_free(dev, &free_req);
  978 
  979                                 dev_priv->agp_textures = NULL;
  980                                 dev_priv->agp_size = 0;
  981                                 dev_priv->agp_handle = 0;
  982                         }
  983 
  984                         if ((dev->agp != NULL) && dev->agp->acquired) {
  985                                 err = drm_agp_release(dev);
  986                         }
  987                 }
  988 
  989                 dev_priv->warp = NULL;
  990                 dev_priv->primary = NULL;
  991                 dev_priv->sarea = NULL;
  992                 dev_priv->sarea_priv = NULL;
  993                 dev->agp_buffer_map = NULL;
  994 
  995                 if (full_cleanup) {
  996                         dev_priv->mmio = NULL;
  997                         dev_priv->status = NULL;
  998                         dev_priv->used_new_dma_init = 0;
  999                 }
 1000 
 1001                 memset(&dev_priv->prim, 0, sizeof(dev_priv->prim));
 1002                 dev_priv->warp_pipe = 0;
 1003                 memset(dev_priv->warp_pipe_phys, 0,
 1004                        sizeof(dev_priv->warp_pipe_phys));
 1005 
 1006                 if (dev_priv->head != NULL) {
 1007                         mga_freelist_cleanup(dev);
 1008                 }
 1009         }
 1010 
 1011         return err;
 1012 }
 1013 
 1014 int mga_dma_init(struct drm_device *dev, void *data,
 1015                  struct drm_file *file_priv)
 1016 {
 1017         drm_mga_init_t *init = data;
 1018         int err;
 1019 
 1020         LOCK_TEST_WITH_RETURN(dev, file_priv);
 1021 
 1022         switch (init->func) {
 1023         case MGA_INIT_DMA:
 1024                 err = mga_do_init_dma(dev, init);
 1025                 if (err) {
 1026                         (void)mga_do_cleanup_dma(dev, FULL_CLEANUP);
 1027                 }
 1028                 return err;
 1029         case MGA_CLEANUP_DMA:
 1030                 return mga_do_cleanup_dma(dev, FULL_CLEANUP);
 1031         }
 1032 
 1033         return -EINVAL;
 1034 }
 1035 
 1036 /* ================================================================
 1037  * Primary DMA stream management
 1038  */
 1039 
 1040 int mga_dma_flush(struct drm_device *dev, void *data,
 1041                   struct drm_file *file_priv)
 1042 {
 1043         drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
 1044         struct drm_lock *lock = data;
 1045 
 1046         LOCK_TEST_WITH_RETURN(dev, file_priv);
 1047 
 1048         DRM_DEBUG("%s%s%s\n",
 1049                   (lock->flags & _DRM_LOCK_FLUSH) ? "flush, " : "",
 1050                   (lock->flags & _DRM_LOCK_FLUSH_ALL) ? "flush all, " : "",
 1051                   (lock->flags & _DRM_LOCK_QUIESCENT) ? "idle, " : "");
 1052 
 1053         WRAP_WAIT_WITH_RETURN(dev_priv);
 1054 
 1055         if (lock->flags & (_DRM_LOCK_FLUSH | _DRM_LOCK_FLUSH_ALL)) {
 1056                 mga_do_dma_flush(dev_priv);
 1057         }
 1058 
 1059         if (lock->flags & _DRM_LOCK_QUIESCENT) {
 1060 #if MGA_DMA_DEBUG
 1061                 int ret = mga_do_wait_for_idle(dev_priv);
 1062                 if (ret < 0)
 1063                         DRM_INFO("-EBUSY\n");
 1064                 return ret;
 1065 #else
 1066                 return mga_do_wait_for_idle(dev_priv);
 1067 #endif
 1068         } else {
 1069                 return 0;
 1070         }
 1071 }
 1072 
 1073 int mga_dma_reset(struct drm_device *dev, void *data,
 1074                   struct drm_file *file_priv)
 1075 {
 1076         drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
 1077 
 1078         LOCK_TEST_WITH_RETURN(dev, file_priv);
 1079 
 1080         return mga_do_dma_reset(dev_priv);
 1081 }
 1082 
 1083 /* ================================================================
 1084  * DMA buffer management
 1085  */
 1086 
 1087 static int mga_dma_get_buffers(struct drm_device * dev,
 1088                                struct drm_file *file_priv, struct drm_dma * d)
 1089 {
 1090         struct drm_buf *buf;
 1091         int i;
 1092 
 1093         for (i = d->granted_count; i < d->request_count; i++) {
 1094                 buf = mga_freelist_get(dev);
 1095                 if (!buf)
 1096                         return -EAGAIN;
 1097 
 1098                 buf->file_priv = file_priv;
 1099 
 1100                 if (DRM_COPY_TO_USER(&d->request_indices[i],
 1101                                      &buf->idx, sizeof(buf->idx)))
 1102                         return -EFAULT;
 1103                 if (DRM_COPY_TO_USER(&d->request_sizes[i],
 1104                                      &buf->total, sizeof(buf->total)))
 1105                         return -EFAULT;
 1106 
 1107                 d->granted_count++;
 1108         }
 1109         return 0;
 1110 }
 1111 
 1112 int mga_dma_buffers(struct drm_device *dev, void *data,
 1113                     struct drm_file *file_priv)
 1114 {
 1115         struct drm_device_dma *dma = dev->dma;
 1116         drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
 1117         struct drm_dma *d = data;
 1118         int ret = 0;
 1119 
 1120         LOCK_TEST_WITH_RETURN(dev, file_priv);
 1121 
 1122         /* Please don't send us buffers.
 1123          */
 1124         if (d->send_count != 0) {
 1125                 DRM_ERROR("Process %d trying to send %d buffers via drmDMA\n",
 1126                           DRM_CURRENTPID, d->send_count);
 1127                 return -EINVAL;
 1128         }
 1129 
 1130         /* We'll send you buffers.
 1131          */
 1132         if (d->request_count < 0 || d->request_count > dma->buf_count) {
 1133                 DRM_ERROR("Process %d trying to get %d buffers (of %d max)\n",
 1134                           DRM_CURRENTPID, d->request_count, dma->buf_count);
 1135                 return -EINVAL;
 1136         }
 1137 
 1138         WRAP_TEST_WITH_RETURN(dev_priv);
 1139 
 1140         d->granted_count = 0;
 1141 
 1142         if (d->request_count) {
 1143                 ret = mga_dma_get_buffers(dev, file_priv, d);
 1144         }
 1145 
 1146         return ret;
 1147 }
 1148 
 1149 /**
 1150  * Called just before the module is unloaded.
 1151  */
 1152 int mga_driver_unload(struct drm_device * dev)
 1153 {
 1154         drm_free(dev->dev_private, sizeof(drm_mga_private_t), DRM_MEM_DRIVER);
 1155         dev->dev_private = NULL;
 1156 
 1157         return 0;
 1158 }
 1159 
 1160 /**
 1161  * Called when the last opener of the device is closed.
 1162  */
 1163 void mga_driver_lastclose(struct drm_device * dev)
 1164 {
 1165         mga_do_cleanup_dma(dev, FULL_CLEANUP);
 1166 }
 1167 
 1168 int mga_driver_dma_quiescent(struct drm_device * dev)
 1169 {
 1170         drm_mga_private_t *dev_priv = dev->dev_private;
 1171         return mga_do_wait_for_idle(dev_priv);
 1172 }

Cache object: 0fac35e8e681a07719ada7e21f34b810


[ 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.