Commit 399516ab0fee ("MAINTAINERS: Add a bunch of legacy (UMS) DRM drivers") marked mga driver obsolete 7 years ago. And the mesa UMD of this drm driver already in deprecated list in the link: https://docs.mesa3d.org/systems.html Matrox-->driver/gpu/drm/mga It's time to remove this driver.
Unified · Split
| @@ -414,15 +414,6 @@ config DRM_R128 · 413 unmodified lines | |||
| 414 | is selected, the module will be called r128. AGP support for | 414 | is selected, the module will be called r128. AGP support for |
| 415 | this card is strongly suggested (unless you have a PCI version). | 415 | this card is strongly suggested (unless you have a PCI version). |
| 416 | 416 | ||
| 417 | config DRM_MGA | ||
| 418 | tristate "Matrox g200/g400" | ||
| 419 | depends on DRM && PCI | ||
| 420 | select FW_LOADER | ||
| 421 | help | ||
| 422 | Choose this option if you have a Matrox G200, G400 or G450 graphics | ||
| 423 | card. If M is selected, the module will be called mga. AGP | ||
| 424 | support is required for this driver to work. | ||
| 425 | |||
| 426 | config DRM_SIS | 417 | config DRM_SIS |
| 427 | tristate "SiS video cards" | 418 | tristate "SiS video cards" |
| 428 | depends on DRM && AGP | 419 | depends on DRM && AGP |
| @@ -137,7 +137,6 @@ obj-$(CONFIG_DRM_TDFX) += tdfx/ · 136 unmodified lines | |||
| 137 | obj-$(CONFIG_DRM_R128) += r128/ | 137 | obj-$(CONFIG_DRM_R128) += r128/ |
| 138 | obj-$(CONFIG_DRM_RADEON)+= radeon/ | 138 | obj-$(CONFIG_DRM_RADEON)+= radeon/ |
| 139 | obj-$(CONFIG_DRM_AMDGPU)+= amd/amdgpu/ | 139 | obj-$(CONFIG_DRM_AMDGPU)+= amd/amdgpu/ |
| 140 | obj-$(CONFIG_DRM_MGA) += mga/ | ||
| 141 | obj-$(CONFIG_DRM_I915) += i915/ | 140 | obj-$(CONFIG_DRM_I915) += i915/ |
| 142 | obj-$(CONFIG_DRM_KMB_DISPLAY) += kmb/ | 141 | obj-$(CONFIG_DRM_KMB_DISPLAY) += kmb/ |
| 143 | obj-$(CONFIG_DRM_MGAG200) += mgag200/ | 142 | obj-$(CONFIG_DRM_MGAG200) += mgag200/ |
| @@ -1,11 +0,0 @@ | |||
| 1 | # SPDX-License-Identifier: GPL-2.0-only | ||
| 2 | # | ||
| 3 | # Makefile for the drm device driver. This driver provides support for the | ||
| 4 | # Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher. | ||
| 5 | |||
| 6 | mga-y := mga_drv.o mga_dma.o mga_state.o mga_warp.o mga_irq.o | ||
| 7 | |||
| 8 | mga-$(CONFIG_COMPAT) += mga_ioc32.o | ||
| 9 | |||
| 10 | obj-$(CONFIG_DRM_MGA) += mga.o | ||
| 11 | |||
| @@ -1,1168 +0,0 @@ | |||
| 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 | /* | ||
| 29 | * \file mga_dma.c | ||
| 30 | * DMA support for MGA G200 / G400. | ||
| 31 | * | ||
| 32 | * \author Rickard E. (Rik) Faith <faith@valinux.com> | ||
| 33 | * \author Jeff Hartmann <jhartmann@valinux.com> | ||
| 34 | * \author Keith Whitwell <keith@tungstengraphics.com> | ||
| 35 | * \author Gareth Hughes <gareth@valinux.com> | ||
| 36 | */ | ||
| 37 | |||
| 38 | #include <linux/delay.h> | ||
| 39 | |||
| 40 | #include "mga_drv.h" | ||
| 41 | |||
| 42 | #define MGA_DEFAULT_USEC_TIMEOUT 10000 | ||
| 43 | #define MGA_FREELIST_DEBUG 0 | ||
| 44 | |||
| 45 | #define MINIMAL_CLEANUP 0 | ||
| 46 | #define FULL_CLEANUP 1 | ||
| 47 | static int mga_do_cleanup_dma(struct drm_device *dev, int full_cleanup); | ||
| 48 | |||
| 49 | /* ================================================================ | ||
| 50 | * Engine control | ||
| 51 | */ | ||
| 52 | |||
| 53 | int mga_do_wait_for_idle(drm_mga_private_t *dev_priv) | ||
| 54 | { | ||
| 55 | u32 status = 0; | ||
| 56 | int i; | ||
| 57 | DRM_DEBUG("\n"); | ||
| 58 | |||
| 59 | for (i = 0; i < dev_priv->usec_timeout; i++) { | ||
| 60 | status = MGA_READ(MGA_STATUS) & MGA_ENGINE_IDLE_MASK; | ||
| 61 | if (status == MGA_ENDPRDMASTS) { | ||
| 62 | MGA_WRITE8(MGA_CRTC_INDEX, 0); | ||
| 63 | return 0; | ||
| 64 | } | ||
| 65 | udelay(1); | ||
| 66 | } | ||
| 67 | |||
| 68 | #if MGA_DMA_DEBUG | ||
| 69 | DRM_ERROR("failed!\n"); | ||
| 70 | DRM_INFO(" status=0x%08x\n", status); | ||
| 71 | #endif | ||
| 72 | return -EBUSY; | ||
| 73 | } | ||
| 74 | |||
| 75 | static int mga_do_dma_reset(drm_mga_private_t *dev_priv) | ||
| 76 | { | ||
| 77 | drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; | ||
| 78 | drm_mga_primary_buffer_t *primary = &dev_priv->prim; | ||
| 79 | |||
| 80 | DRM_DEBUG("\n"); | ||
| 81 | |||
| 82 | /* The primary DMA stream should look like new right about now. | ||
| 83 | */ | ||
| 84 | primary->tail = 0; | ||
| 85 | primary->space = primary->size; | ||
| 86 | primary->last_flush = 0; | ||
| 87 | |||
| 88 | sarea_priv->last_wrap = 0; | ||
| 89 | |||
| 90 | /* FIXME: Reset counters, buffer ages etc... | ||
| 91 | */ | ||
| 92 | |||
| 93 | /* FIXME: What else do we need to reinitialize? WARP stuff? | ||
| 94 | */ | ||
| 95 | |||
| 96 | return 0; | ||
| 97 | } | ||
| 98 | |||
| 99 | /* ================================================================ | ||
| 100 | * Primary DMA stream | ||
| 101 | */ | ||
| 102 | |||
| 103 | void mga_do_dma_flush(drm_mga_private_t *dev_priv) | ||
| 104 | { | ||
| 105 | drm_mga_primary_buffer_t *primary = &dev_priv->prim; | ||
| 106 | u32 head, tail; | ||
| 107 | u32 status = 0; | ||
| 108 | int i; | ||
| 109 | DMA_LOCALS; | ||
| 110 | DRM_DEBUG("\n"); | ||
| 111 | |||
| 112 | /* We need to wait so that we can do an safe flush */ | ||
| 113 | for (i = 0; i < dev_priv->usec_timeout; i++) { | ||
| 114 | status = MGA_READ(MGA_STATUS) & MGA_ENGINE_IDLE_MASK; | ||
| 115 | if (status == MGA_ENDPRDMASTS) | ||
| 116 | break; | ||
| 117 | udelay(1); | ||
| 118 | } | ||
| 119 | |||
| 120 | if (primary->tail == primary->last_flush) { | ||
| 121 | DRM_DEBUG(" bailing out...\n"); | ||
| 122 | return; | ||
| 123 | } | ||
| 124 | |||
| 125 | tail = primary->tail + dev_priv->primary->offset; | ||
| 126 | |||
| 127 | /* We need to pad the stream between flushes, as the card | ||
| 128 | * actually (partially?) reads the first of these commands. | ||
| 129 | * See page 4-16 in the G400 manual, middle of the page or so. | ||
| 130 | */ | ||
| 131 | BEGIN_DMA(1); | ||
| 132 | |||
| 133 | DMA_BLOCK(MGA_DMAPAD, 0x00000000, | ||
| 134 | MGA_DMAPAD, 0x00000000, | ||
| 135 | MGA_DMAPAD, 0x00000000, MGA_DMAPAD, 0x00000000); | ||
| 136 | |||
| 137 | ADVANCE_DMA(); | ||
| 138 | |||
| 139 | primary->last_flush = primary->tail; | ||
| 140 | |||
| 141 | head = MGA_READ(MGA_PRIMADDRESS); | ||
| 142 | |||
| 143 | if (head <= tail) | ||
| 144 | primary->space = primary->size - primary->tail; | ||
| 145 | else | ||
| 146 | primary->space = head - tail; | ||
| 147 | |||
| 148 | DRM_DEBUG(" head = 0x%06lx\n", (unsigned long)(head - dev_priv->primary->offset)); | ||
| 149 | DRM_DEBUG(" tail = 0x%06lx\n", (unsigned long)(tail - dev_priv->primary->offset)); | ||
| 150 | DRM_DEBUG(" space = 0x%06x\n", primary->space); | ||
| 151 | |||
| 152 | mga_flush_write_combine(); | ||
| 153 | MGA_WRITE(MGA_PRIMEND, tail | dev_priv->dma_access); | ||
| 154 | |||
| 155 | DRM_DEBUG("done.\n"); | ||
| 156 | } | ||
| 157 | |||
| 158 | void mga_do_dma_wrap_start(drm_mga_private_t *dev_priv) | ||
| 159 | { | ||
| 160 | drm_mga_primary_buffer_t *primary = &dev_priv->prim; | ||
| 161 | u32 head, tail; | ||
| 162 | DMA_LOCALS; | ||
| 163 | DRM_DEBUG("\n"); | ||
| 164 | |||
| 165 | BEGIN_DMA_WRAP(); | ||
| 166 | |||
| 167 | DMA_BLOCK(MGA_DMAPAD, 0x00000000, | ||
| 168 | MGA_DMAPAD, 0x00000000, | ||
| 169 | MGA_DMAPAD, 0x00000000, MGA_DMAPAD, 0x00000000); | ||
| 170 | |||
| 171 | ADVANCE_DMA(); | ||
| 172 | |||
| 173 | tail = primary->tail + dev_priv->primary->offset; | ||
| 174 | |||
| 175 | primary->tail = 0; | ||
| 176 | primary->last_flush = 0; | ||
| 177 | primary->last_wrap++; | ||
| 178 | |||
| 179 | head = MGA_READ(MGA_PRIMADDRESS); | ||
| 180 | |||
| 181 | if (head == dev_priv->primary->offset) | ||
| 182 | primary->space = primary->size; | ||
| 183 | else | ||
| 184 | primary->space = head - dev_priv->primary->offset; | ||
| 185 | |||
| 186 | DRM_DEBUG(" head = 0x%06lx\n", (unsigned long)(head - dev_priv->primary->offset)); | ||
| 187 | DRM_DEBUG(" tail = 0x%06x\n", primary->tail); | ||
| 188 | DRM_DEBUG(" wrap = %d\n", primary->last_wrap); | ||
| 189 | DRM_DEBUG(" space = 0x%06x\n", primary->space); | ||
| 190 | |||
| 191 | mga_flush_write_combine(); | ||
| 192 | MGA_WRITE(MGA_PRIMEND, tail | dev_priv->dma_access); | ||
| 193 | |||
| 194 | set_bit(0, &primary->wrapped); | ||
| 195 | DRM_DEBUG("done.\n"); | ||
| 196 | } | ||
| 197 | |||
| 198 | void mga_do_dma_wrap_end(drm_mga_private_t *dev_priv) | ||
| 199 | { | ||
| 200 | drm_mga_primary_buffer_t *primary = &dev_priv->prim; | ||
| 201 | drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; | ||
| 202 | u32 head = dev_priv->primary->offset; | ||
| 203 | DRM_DEBUG("\n"); | ||
| 204 | |||
| 205 | sarea_priv->last_wrap++; | ||
| 206 | DRM_DEBUG(" wrap = %d\n", sarea_priv->last_wrap); | ||
| 207 | |||
| 208 | mga_flush_write_combine(); | ||
| 209 | MGA_WRITE(MGA_PRIMADDRESS, head | MGA_DMA_GENERAL); | ||
| 210 | |||
| 211 | clear_bit(0, &primary->wrapped); | ||
| 212 | DRM_DEBUG("done.\n"); | ||
| 213 | } | ||
| 214 | |||
| 215 | /* ================================================================ | ||
| 216 | * Freelist management | ||
| 217 | */ | ||
| 218 | |||
| 219 | #define MGA_BUFFER_USED (~0) | ||
| 220 | #define MGA_BUFFER_FREE 0 | ||
| 221 | |||
| 222 | #if MGA_FREELIST_DEBUG | ||
| 223 | static void mga_freelist_print(struct drm_device *dev) | ||
| 224 | { | ||
| 225 | drm_mga_private_t *dev_priv = dev->dev_private; | ||
| 226 | drm_mga_freelist_t *entry; | ||
| 227 | |||
| 228 | DRM_INFO("\n"); | ||
| 229 | DRM_INFO("current dispatch: last=0x%x done=0x%x\n", | ||
| 230 | dev_priv->sarea_priv->last_dispatch, | ||
| 231 | (unsigned int)(MGA_READ(MGA_PRIMADDRESS) - | ||
| 232 | dev_priv->primary->offset)); | ||
| 233 | DRM_INFO("current freelist:\n"); | ||
| 234 | |||
| 235 | for (entry = dev_priv->head->next; entry; entry = entry->next) { | ||
| 236 | DRM_INFO(" %p idx=%2d age=0x%x 0x%06lx\n", | ||
| 237 | entry, entry->buf->idx, entry->age.head, | ||
| 238 | (unsigned long)(entry->age.head - dev_priv->primary->offset)); | ||
| 239 | } | ||
| 240 | DRM_INFO("\n"); | ||
| 241 | } | ||
| 242 | #endif | ||
| 243 | |||
| 244 | static int mga_freelist_init(struct drm_device *dev, drm_mga_private_t *dev_priv) | ||
| 245 | { | ||
| 246 | struct drm_device_dma *dma = dev->dma; | ||
| 247 | struct drm_buf *buf; | ||
| 248 | drm_mga_buf_priv_t *buf_priv; | ||
| 249 | drm_mga_freelist_t *entry; | ||
| 250 | int i; | ||
| 251 | DRM_DEBUG("count=%d\n", dma->buf_count); | ||
| 252 | |||
| 253 | dev_priv->head = kzalloc(sizeof(drm_mga_freelist_t), GFP_KERNEL); | ||
| 254 | if (dev_priv->head == NULL) | ||
| 255 | return -ENOMEM; | ||
| 256 | |||
| 257 | SET_AGE(&dev_priv->head->age, MGA_BUFFER_USED, 0); | ||
| 258 | |||
| 259 | for (i = 0; i < dma->buf_count; i++) { | ||
| 260 | buf = dma->buflist[i]; | ||
| 261 | buf_priv = buf->dev_private; | ||
| 262 | |||
| 263 | entry = kzalloc(sizeof(drm_mga_freelist_t), GFP_KERNEL); | ||
| 264 | if (entry == NULL) | ||
| 265 | return -ENOMEM; | ||
| 266 | |||
| 267 | entry->next = dev_priv->head->next; | ||
| 268 | entry->prev = dev_priv->head; | ||
| 269 | SET_AGE(&entry->age, MGA_BUFFER_FREE, 0); | ||
| 270 | entry->buf = buf; | ||
| 271 | |||
| 272 | if (dev_priv->head->next != NULL) | ||
| 273 | dev_priv->head->next->prev = entry; | ||
| 274 | if (entry->next == NULL) | ||
| 275 | dev_priv->tail = entry; | ||
| 276 | |||
| 277 | buf_priv->list_entry = entry; | ||
| 278 | buf_priv->discard = 0; | ||
| 279 | buf_priv->dispatched = 0; | ||
| 280 | |||
| 281 | dev_priv->head->next = entry; | ||
| 282 | } | ||
| 283 | |||
| 284 | return 0; | ||
| 285 | } | ||
| 286 | |||
| 287 | static void mga_freelist_cleanup(struct drm_device *dev) | ||
| 288 | { | ||
| 289 | drm_mga_private_t *dev_priv = dev->dev_private; | ||
| 290 | drm_mga_freelist_t *entry; | ||
| 291 | drm_mga_freelist_t *next; | ||
| 292 | DRM_DEBUG("\n"); | ||
| 293 | |||
| 294 | entry = dev_priv->head; | ||
| 295 | while (entry) { | ||
| 296 | next = entry->next; | ||
| 297 | kfree(entry); | ||
| 298 | entry = next; | ||
| 299 | } | ||
| 300 | |||
| 301 | dev_priv->head = dev_priv->tail = NULL; | ||
| 302 | } | ||
| 303 | |||
| 304 | #if 0 | ||
| 305 | /* FIXME: Still needed? | ||
| 306 | */ | ||
| 307 | static void mga_freelist_reset(struct drm_device *dev) | ||
| 308 | { | ||
| 309 | struct drm_device_dma *dma = dev->dma; | ||
| 310 | struct drm_buf *buf; | ||
| 311 | drm_mga_buf_priv_t *buf_priv; | ||
| 312 | int i; | ||
| 313 | |||
| 314 | for (i = 0; i < dma->buf_count; i++) { | ||
| 315 | buf = dma->buflist[i]; | ||
| 316 | buf_priv = buf->dev_private; | ||
| 317 | SET_AGE(&buf_priv->list_entry->age, MGA_BUFFER_FREE, 0); | ||
| 318 | } | ||
| 319 | } | ||
| 320 | #endif | ||
| 321 | |||
| 322 | static struct drm_buf *mga_freelist_get(struct drm_device * dev) | ||
| 323 | { | ||
| 324 | drm_mga_private_t *dev_priv = dev->dev_private; | ||
| 325 | drm_mga_freelist_t *next; | ||
| 326 | drm_mga_freelist_t *prev; | ||
| 327 | drm_mga_freelist_t *tail = dev_priv->tail; | ||
| 328 | u32 head, wrap; | ||
| 329 | DRM_DEBUG("\n"); | ||
| 330 | |||
| 331 | head = MGA_READ(MGA_PRIMADDRESS); | ||
| 332 | wrap = dev_priv->sarea_priv->last_wrap; | ||
| 333 | |||
| 334 | DRM_DEBUG(" tail=0x%06lx %d\n", | ||
| 335 | tail->age.head ? | ||
| 336 | (unsigned long)(tail->age.head - dev_priv->primary->offset) : 0, | ||
| 337 | tail->age.wrap); | ||
| 338 | DRM_DEBUG(" head=0x%06lx %d\n", | ||
| 339 | (unsigned long)(head - dev_priv->primary->offset), wrap); | ||
| 340 | |||
| 341 | if (TEST_AGE(&tail->age, head, wrap)) { | ||
| 342 | prev = dev_priv->tail->prev; | ||
| 343 | next = dev_priv->tail; | ||
| 344 | prev->next = NULL; | ||
| 345 | next->prev = next->next = NULL; | ||
| 346 | dev_priv->tail = prev; | ||
| 347 | SET_AGE(&next->age, MGA_BUFFER_USED, 0); | ||
| 348 | return next->buf; | ||
| 349 | } | ||
| 350 | |||
| 351 | DRM_DEBUG("returning NULL!\n"); | ||
| 352 | return NULL; | ||
| 353 | } | ||
| 354 | |||
| 355 | int mga_freelist_put(struct drm_device *dev, struct drm_buf *buf) | ||
| 356 | { | ||
| 357 | drm_mga_private_t *dev_priv = dev->dev_private; | ||
| 358 | drm_mga_buf_priv_t *buf_priv = buf->dev_private; | ||
| 359 | drm_mga_freelist_t *head, *entry, *prev; | ||
| 360 | |||
| 361 | DRM_DEBUG("age=0x%06lx wrap=%d\n", | ||
| 362 | (unsigned long)(buf_priv->list_entry->age.head - | ||
| 363 | dev_priv->primary->offset), | ||
| 364 | buf_priv->list_entry->age.wrap); | ||
| 365 | |||
| 366 | entry = buf_priv->list_entry; | ||
| 367 | head = dev_priv->head; | ||
| 368 | |||
| 369 | if (buf_priv->list_entry->age.head == MGA_BUFFER_USED) { | ||
| 370 | SET_AGE(&entry->age, MGA_BUFFER_FREE, 0); | ||
| 371 | prev = dev_priv->tail; | ||
| 372 | prev->next = entry; | ||
| 373 | entry->prev = prev; | ||
| 374 | entry->next = NULL; | ||
| 375 | } else { | ||
| 376 | prev = head->next; | ||
| 377 | head->next = entry; | ||
| 378 | prev->prev = entry; | ||
| 379 | entry->prev = head; | ||
| 380 | entry->next = prev; | ||
| 381 | } | ||
| 382 | |||
| 383 | return 0; | ||
| 384 | } | ||
| 385 | |||
| 386 | /* ================================================================ | ||
| 387 | * DMA initialization, cleanup | ||
| 388 | */ | ||
| 389 | |||
| 390 | int mga_driver_load(struct drm_device *dev, unsigned long flags) | ||
| 391 | { | ||
| 392 | struct pci_dev *pdev = to_pci_dev(dev->dev); | ||
| 393 | drm_mga_private_t *dev_priv; | ||
| 394 | int ret; | ||
| 395 | |||
| 396 | /* There are PCI versions of the G450. These cards have the | ||
| 397 | * same PCI ID as the AGP G450, but have an additional PCI-to-PCI | ||
| 398 | * bridge chip. We detect these cards, which are not currently | ||
| 399 | * supported by this driver, by looking at the device ID of the | ||
| 400 | * bus the "card" is on. If vendor is 0x3388 (Hint Corp) and the | ||
| 401 | * device is 0x0021 (HB6 Universal PCI-PCI bridge), we reject the | ||
| 402 | * device. | ||
| 403 | */ | ||
| 404 | if ((pdev->device == 0x0525) && pdev->bus->self | ||
| 405 | && (pdev->bus->self->vendor == 0x3388) | ||
| 406 | && (pdev->bus->self->device == 0x0021) | ||
| 407 | && dev->agp) { | ||
| 408 | /* FIXME: This should be quirked in the pci core, but oh well | ||
| 409 | * the hw probably stopped existing. */ | ||
| 410 | arch_phys_wc_del(dev->agp->agp_mtrr); | ||
| 411 | kfree(dev->agp); | ||
| 412 | dev->agp = NULL; | ||
| 413 | } | ||
| 414 | dev_priv = kzalloc(sizeof(drm_mga_private_t), GFP_KERNEL); | ||
| 415 | if (!dev_priv) | ||
| 416 | return -ENOMEM; | ||
| 417 | |||
| 418 | dev->dev_private = (void *)dev_priv; | ||
| 419 | |||
| 420 | dev_priv->usec_timeout = MGA_DEFAULT_USEC_TIMEOUT; | ||
| 421 | dev_priv->chipset = flags; | ||
| 422 | |||
| 423 | pci_set_master(pdev); | ||
| 424 | |||
| 425 | dev_priv->mmio_base = pci_resource_start(pdev, 1); | ||
| 426 | dev_priv->mmio_size = pci_resource_len(pdev, 1); | ||
| 427 | |||
| 428 | ret = drm_vblank_init(dev, 1); | ||
| 429 | |||
| 430 | if (ret) { | ||
| 431 | (void) mga_driver_unload(dev); | ||
| 432 | return ret; | ||
| 433 | } | ||
| 434 | |||
| 435 | return 0; | ||
| 436 | } | ||
| 437 | |||
| 438 | #if IS_ENABLED(CONFIG_AGP) | ||
| 439 | /* | ||
| 440 | * Bootstrap the driver for AGP DMA. | ||
| 441 | * | ||
| 442 | * \todo | ||
| 443 | * Investigate whether there is any benefit to storing the WARP microcode in | ||
| 444 | * AGP memory. If not, the microcode may as well always be put in PCI | ||
| 445 | * memory. | ||
| 446 | * | ||
| 447 | * \todo | ||
| 448 | * This routine needs to set dma_bs->agp_mode to the mode actually configured | ||
| 449 | * in the hardware. Looking just at the Linux AGP driver code, I don't see | ||
| 450 | * an easy way to determine this. | ||
| 451 | * | ||
| 452 | * \sa mga_do_dma_bootstrap, mga_do_pci_dma_bootstrap | ||
| 453 | */ | ||
| 454 | static int mga_do_agp_dma_bootstrap(struct drm_device *dev, | ||
| 455 | drm_mga_dma_bootstrap_t *dma_bs) | ||
| 456 | { | ||
| 457 | drm_mga_private_t *const dev_priv = | ||
| 458 | (drm_mga_private_t *) dev->dev_private; | ||
| 459 | unsigned int warp_size = MGA_WARP_UCODE_SIZE; | ||
| 460 | int err; | ||
| 461 | unsigned offset; | ||
| 462 | const unsigned secondary_size = dma_bs->secondary_bin_count | ||
| 463 | * dma_bs->secondary_bin_size; | ||
| 464 | const unsigned agp_size = (dma_bs->agp_size << 20); | ||
| 465 | struct drm_buf_desc req; | ||
| 466 | struct drm_agp_mode mode; | ||
| 467 | struct drm_agp_info info; | ||
| 468 | struct drm_agp_buffer agp_req; | ||
| 469 | struct drm_agp_binding bind_req; | ||
| 470 | |||
| 471 | /* Acquire AGP. */ | ||
| 472 | err = drm_legacy_agp_acquire(dev); | ||
| 473 | if (err) { | ||
| 474 | DRM_ERROR("Unable to acquire AGP: %d\n", err); | ||
| 475 | return err; | ||
| 476 | } | ||
| 477 | |||
| 478 | err = drm_legacy_agp_info(dev, &info); | ||
| 479 | if (err) { | ||
| 480 | DRM_ERROR("Unable to get AGP info: %d\n", err); | ||
| 481 | return err; | ||
| 482 | } | ||
| 483 | |||
| 484 | mode.mode = (info.mode & ~0x07) | dma_bs->agp_mode; | ||
| 485 | err = drm_legacy_agp_enable(dev, mode); | ||
| 486 | if (err) { | ||
| 487 | DRM_ERROR("Unable to enable AGP (mode = 0x%lx)\n", mode.mode); | ||
| 488 | return err; | ||
| 489 | } | ||
| 490 | |||
| 491 | /* In addition to the usual AGP mode configuration, the G200 AGP cards | ||
| 492 | * need to have the AGP mode "manually" set. | ||
| 493 | */ | ||
| 494 | |||
| 495 | if (dev_priv->chipset == MGA_CARD_TYPE_G200) { | ||
| 496 | if (mode.mode & 0x02) | ||
| 497 | MGA_WRITE(MGA_AGP_PLL, MGA_AGP2XPLL_ENABLE); | ||
| 498 | else | ||
| 499 | MGA_WRITE(MGA_AGP_PLL, MGA_AGP2XPLL_DISABLE); | ||
| 500 | } | ||
| 501 | |||
| 502 | /* Allocate and bind AGP memory. */ | ||
| 503 | agp_req.size = agp_size; | ||
| 504 | agp_req.type = 0; | ||
| 505 | err = drm_legacy_agp_alloc(dev, &agp_req); | ||
| 506 | if (err) { | ||
| 507 | dev_priv->agp_size = 0; | ||
| 508 | DRM_ERROR("Unable to allocate %uMB AGP memory\n", | ||
| 509 | dma_bs->agp_size); | ||
| 510 | return err; | ||
| 511 | } | ||
| 512 | |||
| 513 | dev_priv->agp_size = agp_size; | ||
| 514 | dev_priv->agp_handle = agp_req.handle; | ||
| 515 | |||
| 516 | bind_req.handle = agp_req.handle; | ||
| 517 | bind_req.offset = 0; | ||
| 518 | err = drm_legacy_agp_bind(dev, &bind_req); | ||
| 519 | if (err) { | ||
| 520 | DRM_ERROR("Unable to bind AGP memory: %d\n", err); | ||
| 521 | return err; | ||
| 522 | } | ||
| 523 | |||
| 524 | /* Make drm_legacy_addbufs happy by not trying to create a mapping for | ||
| 525 | * less than a page. | ||
| 526 | */ | ||
| 527 | if (warp_size < PAGE_SIZE) | ||
| 528 | warp_size = PAGE_SIZE; | ||
| 529 | |||
| 530 | offset = 0; | ||
| 531 | err = drm_legacy_addmap(dev, offset, warp_size, | ||
| 532 | _DRM_AGP, _DRM_READ_ONLY, &dev_priv->warp); | ||
| 533 | if (err) { | ||
| 534 | DRM_ERROR("Unable to map WARP microcode: %d\n", err); | ||
| 535 | return err; | ||
| 536 | } | ||
| 537 | |||
| 538 | offset += warp_size; | ||
| 539 | err = drm_legacy_addmap(dev, offset, dma_bs->primary_size, | ||
| 540 | _DRM_AGP, _DRM_READ_ONLY, &dev_priv->primary); | ||
| 541 | if (err) { | ||
| 542 | DRM_ERROR("Unable to map primary DMA region: %d\n", err); | ||
| 543 | return err; | ||
| 544 | } | ||
| 545 | |||
| 546 | offset += dma_bs->primary_size; | ||
| 547 | err = drm_legacy_addmap(dev, offset, secondary_size, | ||
| 548 | _DRM_AGP, 0, &dev->agp_buffer_map); | ||
| 549 | if (err) { | ||
| 550 | DRM_ERROR("Unable to map secondary DMA region: %d\n", err); | ||
| 551 | return err; | ||
| 552 | } | ||
| 553 | |||
| 554 | (void)memset(&req, 0, sizeof(req)); | ||
| 555 | req.count = dma_bs->secondary_bin_count; | ||
| 556 | req.size = dma_bs->secondary_bin_size; | ||
| 557 | req.flags = _DRM_AGP_BUFFER; | ||
| 558 | req.agp_start = offset; | ||
| 559 | |||
| 560 | err = drm_legacy_addbufs_agp(dev, &req); | ||
| 561 | if (err) { | ||
| 562 | DRM_ERROR("Unable to add secondary DMA buffers: %d\n", err); | ||
| 563 | return err; | ||
| 564 | } | ||
| 565 | |||
| 566 | { | ||
| 567 | struct drm_map_list *_entry; | ||
| 568 | unsigned long agp_token = 0; | ||
| 569 | |||
| 570 | list_for_each_entry(_entry, &dev->maplist, head) { | ||
| 571 | if (_entry->map == dev->agp_buffer_map) | ||
| 572 | agp_token = _entry->user_token; | ||
| 573 | } | ||
| 574 | if (!agp_token) | ||
| 575 | return -EFAULT; | ||
| 576 | |||
| 577 | dev->agp_buffer_token = agp_token; | ||
| 578 | } | ||
| 579 | |||
| 580 | offset += secondary_size; | ||
| 581 | err = drm_legacy_addmap(dev, offset, agp_size - offset, | ||
| 582 | _DRM_AGP, 0, &dev_priv->agp_textures); | ||
| 583 | if (err) { | ||
| 584 | DRM_ERROR("Unable to map AGP texture region %d\n", err); | ||
| 585 | return err; | ||
| 586 | } | ||
| 587 | |||
| 588 | drm_legacy_ioremap(dev_priv->warp, dev); | ||
| 589 | drm_legacy_ioremap(dev_priv->primary, dev); | ||
| 590 | drm_legacy_ioremap(dev->agp_buffer_map, dev); | ||
| 591 | |||
| 592 | if (!dev_priv->warp->handle || | ||
| 593 | !dev_priv->primary->handle || !dev->agp_buffer_map->handle) { | ||
| 594 | DRM_ERROR("failed to ioremap agp regions! (%p, %p, %p)\n", | ||
| 595 | dev_priv->warp->handle, dev_priv->primary->handle, | ||
| 596 | dev->agp_buffer_map->handle); | ||
| 597 | return -ENOMEM; | ||
| 598 | } | ||
| 599 | |||
| 600 | dev_priv->dma_access = MGA_PAGPXFER; | ||
| 601 | dev_priv->wagp_enable = MGA_WAGP_ENABLE; | ||
| 602 | |||
| 603 | DRM_INFO("Initialized card for AGP DMA.\n"); | ||
| 604 | return 0; | ||
| 605 | } | ||
| 606 | #else | ||
| 607 | static int mga_do_agp_dma_bootstrap(struct drm_device *dev, | ||
| 608 | drm_mga_dma_bootstrap_t *dma_bs) | ||
| 609 | { | ||
| 610 | return -EINVAL; | ||
| 611 | } | ||
| 612 | #endif | ||
| 613 | |||
| 614 | /* | ||
| 615 | * Bootstrap the driver for PCI DMA. | ||
| 616 | * | ||
| 617 | * \todo | ||
| 618 | * The algorithm for decreasing the size of the primary DMA buffer could be | ||
| 619 | * better. The size should be rounded up to the nearest page size, then | ||
| 620 | * decrease the request size by a single page each pass through the loop. | ||
| 621 | * | ||
| 622 | * \todo | ||
| 623 | * Determine whether the maximum address passed to drm_pci_alloc is correct. | ||
| 624 | * The same goes for drm_legacy_addbufs_pci. | ||
| 625 | * | ||
| 626 | * \sa mga_do_dma_bootstrap, mga_do_agp_dma_bootstrap | ||
| 627 | */ | ||
| 628 | static int mga_do_pci_dma_bootstrap(struct drm_device *dev, | ||
| 629 | drm_mga_dma_bootstrap_t *dma_bs) | ||
| 630 | { | ||
| 631 | drm_mga_private_t *const dev_priv = | ||
| 632 | (drm_mga_private_t *) dev->dev_private; | ||
| 633 | unsigned int warp_size = MGA_WARP_UCODE_SIZE; | ||
| 634 | unsigned int primary_size; | ||
| 635 | unsigned int bin_count; | ||
| 636 | int err; | ||
| 637 | struct drm_buf_desc req; | ||
| 638 | |||
| 639 | if (dev->dma == NULL) { | ||
| 640 | DRM_ERROR("dev->dma is NULL\n"); | ||
| 641 | return -EFAULT; | ||
| 642 | } | ||
| 643 | |||
| 644 | /* Make drm_legacy_addbufs happy by not trying to create a mapping for | ||
| 645 | * less than a page. | ||
| 646 | */ | ||
| 647 | if (warp_size < PAGE_SIZE) | ||
| 648 | warp_size = PAGE_SIZE; | ||
| 649 | |||
| 650 | /* The proper alignment is 0x100 for this mapping */ | ||
| 651 | err = drm_legacy_addmap(dev, 0, warp_size, _DRM_CONSISTENT, | ||
| 652 | _DRM_READ_ONLY, &dev_priv->warp); | ||
| 653 | if (err != 0) { | ||
| 654 | DRM_ERROR("Unable to create mapping for WARP microcode: %d\n", | ||
| 655 | err); | ||
| 656 | return err; | ||
| 657 | } | ||
| 658 | |||
| 659 | /* Other than the bottom two bits being used to encode other | ||
| 660 | * information, there don't appear to be any restrictions on the | ||
| 661 | * alignment of the primary or secondary DMA buffers. | ||
| 662 | */ | ||
| 663 | |||
| 664 | for (primary_size = dma_bs->primary_size; primary_size != 0; | ||
| 665 | primary_size >>= 1) { | ||
| 666 | /* The proper alignment for this mapping is 0x04 */ | ||
| 667 | err = drm_legacy_addmap(dev, 0, primary_size, _DRM_CONSISTENT, | ||
| 668 | _DRM_READ_ONLY, &dev_priv->primary); | ||
| 669 | if (!err) | ||
| 670 | break; | ||
| 671 | } | ||
| 672 | |||
| 673 | if (err != 0) { | ||
| 674 | DRM_ERROR("Unable to allocate primary DMA region: %d\n", err); | ||
| 675 | return -ENOMEM; | ||
| 676 | } | ||
| 677 | |||
| 678 | if (dev_priv->primary->size != dma_bs->primary_size) { | ||
| 679 | DRM_INFO("Primary DMA buffer size reduced from %u to %u.\n", | ||
| 680 | dma_bs->primary_size, | ||
| 681 | (unsigned)dev_priv->primary->size); | ||
| 682 | dma_bs->primary_size = dev_priv->primary->size; | ||
| 683 | } | ||
| 684 | |||
| 685 | for (bin_count = dma_bs->secondary_bin_count; bin_count > 0; | ||
| 686 | bin_count--) { | ||
| 687 | (void)memset(&req, 0, sizeof(req)); | ||
| 688 | req.count = bin_count; | ||
| 689 | req.size = dma_bs->secondary_bin_size; | ||
| 690 | |||
| 691 | err = drm_legacy_addbufs_pci(dev, &req); | ||
| 692 | if (!err) | ||
| 693 | break; | ||
| 694 | } | ||
| 695 | |||
| 696 | if (bin_count == 0) { | ||
| 697 | DRM_ERROR("Unable to add secondary DMA buffers: %d\n", err); | ||
| 698 | return err; | ||
| 699 | } | ||
| 700 | |||
| 701 | if (bin_count != dma_bs->secondary_bin_count) { | ||
| 702 | DRM_INFO("Secondary PCI DMA buffer bin count reduced from %u " | ||
| 703 | "to %u.\n", dma_bs->secondary_bin_count, bin_count); | ||
| 704 | |||
| 705 | dma_bs->secondary_bin_count = bin_count; | ||
| 706 | } | ||
| 707 | |||
| 708 | dev_priv->dma_access = 0; | ||
| 709 | dev_priv->wagp_enable = 0; | ||
| 710 | |||
| 711 | dma_bs->agp_mode = 0; | ||
| 712 | |||
| 713 | DRM_INFO("Initialized card for PCI DMA.\n"); | ||
| 714 | return 0; | ||
| 715 | } | ||
| 716 | |||
| 717 | static int mga_do_dma_bootstrap(struct drm_device *dev, | ||
| 718 | drm_mga_dma_bootstrap_t *dma_bs) | ||
| 719 | { | ||
| 720 | const int is_agp = (dma_bs->agp_mode != 0) && dev->agp; | ||
| 721 | int err; | ||
| 722 | drm_mga_private_t *const dev_priv = | ||
| 723 | (drm_mga_private_t *) dev->dev_private; | ||
| 724 | |||
| 725 | dev_priv->used_new_dma_init = 1; | ||
| 726 | |||
| 727 | /* The first steps are the same for both PCI and AGP based DMA. Map | ||
| 728 | * the cards MMIO registers and map a status page. | ||
| 729 | */ | ||
| 730 | err = drm_legacy_addmap(dev, dev_priv->mmio_base, dev_priv->mmio_size, | ||
| 731 | _DRM_REGISTERS, _DRM_READ_ONLY, | ||
| 732 | &dev_priv->mmio); | ||
| 733 | if (err) { | ||
| 734 | DRM_ERROR("Unable to map MMIO region: %d\n", err); | ||
| 735 | return err; | ||
| 736 | } | ||
| 737 | |||
| 738 | err = drm_legacy_addmap(dev, 0, SAREA_MAX, _DRM_SHM, | ||
| 739 | _DRM_READ_ONLY | _DRM_LOCKED | _DRM_KERNEL, | ||
| 740 | &dev_priv->status); | ||
| 741 | if (err) { | ||
| 742 | DRM_ERROR("Unable to map status region: %d\n", err); | ||
| 743 | return err; | ||
| 744 | } | ||
| 745 | |||
| 746 | /* The DMA initialization procedure is slightly different for PCI and | ||
| 747 | * AGP cards. AGP cards just allocate a large block of AGP memory and | ||
| 748 | * carve off portions of it for internal uses. The remaining memory | ||
| 749 | * is returned to user-mode to be used for AGP textures. | ||
| 750 | */ | ||
| 751 | if (is_agp) | ||
| 752 | err = mga_do_agp_dma_bootstrap(dev, dma_bs); | ||
| 753 | |||
| 754 | /* If we attempted to initialize the card for AGP DMA but failed, | ||
| 755 | * clean-up any mess that may have been created. | ||
| 756 | */ | ||
| 757 | |||
| 758 | if (err) | ||
| 759 | mga_do_cleanup_dma(dev, MINIMAL_CLEANUP); | ||
| 760 | |||
| 761 | /* Not only do we want to try and initialized PCI cards for PCI DMA, | ||
| 762 | * but we also try to initialized AGP cards that could not be | ||
| 763 | * initialized for AGP DMA. This covers the case where we have an AGP | ||
| 764 | * card in a system with an unsupported AGP chipset. In that case the | ||
| 765 | * card will be detected as AGP, but we won't be able to allocate any | ||
| 766 | * AGP memory, etc. | ||
| 767 | */ | ||
| 768 | |||
| 769 | if (!is_agp || err) | ||
| 770 | err = mga_do_pci_dma_bootstrap(dev, dma_bs); | ||
| 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 | err = mga_do_dma_bootstrap(dev, bootstrap); | ||
| 785 | if (err) { | ||
| 786 | mga_do_cleanup_dma(dev, FULL_CLEANUP); | ||
| 787 | return err; | ||
| 788 | } | ||
| 789 | |||
| 790 | if (dev_priv->agp_textures != NULL) { | ||
| 791 | bootstrap->texture_handle = dev_priv->agp_textures->offset; | ||
| 792 | bootstrap->texture_size = dev_priv->agp_textures->size; | ||
| 793 | } else { | ||
| 794 | bootstrap->texture_handle = 0; | ||
| 795 | bootstrap->texture_size = 0; | ||
| 796 | } | ||
| 797 | |||
| 798 | bootstrap->agp_mode = modes[bootstrap->agp_mode & 0x07]; | ||
| 799 | |||
| 800 | return err; | ||
| 801 | } | ||
| 802 | |||
| 803 | static int mga_do_init_dma(struct drm_device *dev, drm_mga_init_t *init) | ||
| 804 | { | ||
| 805 | drm_mga_private_t *dev_priv; | ||
| 806 | int ret; | ||
| 807 | DRM_DEBUG("\n"); | ||
| 808 | |||
| 809 | dev_priv = dev->dev_private; | ||
| 810 | |||
| 811 | if (init->sgram) | ||
| 812 | dev_priv->clear_cmd = MGA_DWGCTL_CLEAR | MGA_ATYPE_BLK; | ||
| 813 | else | ||
| 814 | dev_priv->clear_cmd = MGA_DWGCTL_CLEAR | MGA_ATYPE_RSTR; | ||
| 815 | dev_priv->maccess = init->maccess; | ||
| 816 | |||
| 817 | dev_priv->fb_cpp = init->fb_cpp; | ||
| 818 | dev_priv->front_offset = init->front_offset; | ||
| 819 | dev_priv->front_pitch = init->front_pitch; | ||
| 820 | dev_priv->back_offset = init->back_offset; | ||
| 821 | dev_priv->back_pitch = init->back_pitch; | ||
| 822 | |||
| 823 | dev_priv->depth_cpp = init->depth_cpp; | ||
| 824 | dev_priv->depth_offset = init->depth_offset; | ||
| 825 | dev_priv->depth_pitch = init->depth_pitch; | ||
| 826 | |||
| 827 | /* FIXME: Need to support AGP textures... | ||
| 828 | */ | ||
| 829 | dev_priv->texture_offset = init->texture_offset[0]; | ||
| 830 | dev_priv->texture_size = init->texture_size[0]; | ||
| 831 | |||
| 832 | dev_priv->sarea = drm_legacy_getsarea(dev); | ||
| 833 | if (!dev_priv->sarea) { | ||
| 834 | DRM_ERROR("failed to find sarea!\n"); | ||
| 835 | return -EINVAL; | ||
| 836 | } | ||
| 837 | |||
| 838 | if (!dev_priv->used_new_dma_init) { | ||
| 839 | |||
| 840 | dev_priv->dma_access = MGA_PAGPXFER; | ||
| 841 | dev_priv->wagp_enable = MGA_WAGP_ENABLE; | ||
| 842 | |||
| 843 | dev_priv->status = drm_legacy_findmap(dev, init->status_offset); | ||
| 844 | if (!dev_priv->status) { | ||
| 845 | DRM_ERROR("failed to find status page!\n"); | ||
| 846 | return -EINVAL; | ||
| 847 | } | ||
| 848 | dev_priv->mmio = drm_legacy_findmap(dev, init->mmio_offset); | ||
| 849 | if (!dev_priv->mmio) { | ||
| 850 | DRM_ERROR("failed to find mmio region!\n"); | ||
| 851 | return -EINVAL; | ||
| 852 | } | ||
| 853 | dev_priv->warp = drm_legacy_findmap(dev, init->warp_offset); | ||
| 854 | if (!dev_priv->warp) { | ||
| 855 | DRM_ERROR("failed to find warp microcode region!\n"); | ||
| 856 | return -EINVAL; | ||
| 857 | } | ||
| 858 | dev_priv->primary = drm_legacy_findmap(dev, init->primary_offset); | ||
| 859 | if (!dev_priv->primary) { | ||
| 860 | DRM_ERROR("failed to find primary dma region!\n"); | ||
| 861 | return -EINVAL; | ||
| 862 | } | ||
| 863 | dev->agp_buffer_token = init->buffers_offset; | ||
| 864 | dev->agp_buffer_map = | ||
| 865 | drm_legacy_findmap(dev, init->buffers_offset); | ||
| 866 | if (!dev->agp_buffer_map) { | ||
| 867 | DRM_ERROR("failed to find dma buffer region!\n"); | ||
| 868 | return -EINVAL; | ||
| 869 | } | ||
| 870 | |||
| 871 | drm_legacy_ioremap(dev_priv->warp, dev); | ||
| 872 | drm_legacy_ioremap(dev_priv->primary, dev); | ||
| 873 | drm_legacy_ioremap(dev->agp_buffer_map, dev); | ||
| 874 | } | ||
| 875 | |||
| 876 | dev_priv->sarea_priv = | ||
| 877 | (drm_mga_sarea_t *) ((u8 *) dev_priv->sarea->handle + | ||
| 878 | init->sarea_priv_offset); | ||
| 879 | |||
| 880 | if (!dev_priv->warp->handle || | ||
| 881 | !dev_priv->primary->handle || | ||
| 882 | ((dev_priv->dma_access != 0) && | ||
| 883 | ((dev->agp_buffer_map == NULL) || | ||
| 884 | (dev->agp_buffer_map->handle == NULL)))) { | ||
| 885 | DRM_ERROR("failed to ioremap agp regions!\n"); | ||
| 886 | return -ENOMEM; | ||
| 887 | } | ||
| 888 | |||
| 889 | ret = mga_warp_install_microcode(dev_priv); | ||
| 890 | if (ret < 0) { | ||
| 891 | DRM_ERROR("failed to install WARP ucode!: %d\n", ret); | ||
| 892 | return ret; | ||
| 893 | } | ||
| 894 | |||
| 895 | ret = mga_warp_init(dev_priv); | ||
| 896 | if (ret < 0) { | ||
| 897 | DRM_ERROR("failed to init WARP engine!: %d\n", ret); | ||
| 898 | return ret; | ||
| 899 | } | ||
| 900 | |||
| 901 | dev_priv->prim.status = (u32 *) dev_priv->status->handle; | ||
| 902 | |||
| 903 | mga_do_wait_for_idle(dev_priv); | ||
| 904 | |||
| 905 | /* Init the primary DMA registers. | ||
| 906 | */ | ||
| 907 | MGA_WRITE(MGA_PRIMADDRESS, dev_priv->primary->offset | MGA_DMA_GENERAL); | ||
| 908 | #if 0 | ||
| 909 | MGA_WRITE(MGA_PRIMPTR, virt_to_bus((void *)dev_priv->prim.status) | MGA_PRIMPTREN0 | /* Soft trap, SECEND, SETUPEND */ | ||
| 910 | MGA_PRIMPTREN1); /* DWGSYNC */ | ||
| 911 | #endif | ||
| 912 | |||
| 913 | dev_priv->prim.start = (u8 *) dev_priv->primary->handle; | ||
| 914 | dev_priv->prim.end = ((u8 *) dev_priv->primary->handle | ||
| 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_legacy_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_legacy_ioremapfree(dev_priv->warp, dev); | ||
| 960 | |||
| 961 | if ((dev_priv->primary != NULL) | ||
| 962 | && (dev_priv->primary->type != _DRM_CONSISTENT)) | ||
| 963 | drm_legacy_ioremapfree(dev_priv->primary, dev); | ||
| 964 | |||
| 965 | if (dev->agp_buffer_map != NULL) | ||
| 966 | drm_legacy_ioremapfree(dev->agp_buffer_map, dev); | ||
| 967 | |||
| 968 | if (dev_priv->used_new_dma_init) { | ||
| 969 | #if IS_ENABLED(CONFIG_AGP) | ||
| 970 | if (dev_priv->agp_handle != 0) { | ||
| 971 | struct drm_agp_binding unbind_req; | ||
| 972 | struct drm_agp_buffer free_req; | ||
| 973 | |||
| 974 | unbind_req.handle = dev_priv->agp_handle; | ||
| 975 | drm_legacy_agp_unbind(dev, &unbind_req); | ||
| 976 | |||
| 977 | free_req.handle = dev_priv->agp_handle; | ||
| 978 | drm_legacy_agp_free(dev, &free_req); | ||
| 979 | |||
| 980 | dev_priv->agp_textures = NULL; | ||
| 981 | dev_priv->agp_size = 0; | ||
| 982 | dev_priv->agp_handle = 0; | ||
| 983 | } | ||
| 984 | |||
| 985 | if ((dev->agp != NULL) && dev->agp->acquired) | ||
| 986 | err = drm_legacy_agp_release(dev); | ||
| 987 | #endif | ||
| 988 | } | ||
| 989 | |||
| 990 | dev_priv->warp = NULL; | ||
| 991 | dev_priv->primary = NULL; | ||
| 992 | dev_priv->sarea = NULL; | ||
| 993 | dev_priv->sarea_priv = NULL; | ||
| 994 | dev->agp_buffer_map = NULL; | ||
| 995 | |||
| 996 | if (full_cleanup) { | ||
| 997 | dev_priv->mmio = NULL; | ||
| 998 | dev_priv->status = NULL; | ||
| 999 | dev_priv->used_new_dma_init = 0; | ||
| 1000 | } | ||
| 1001 | |||
| 1002 | memset(&dev_priv->prim, 0, sizeof(dev_priv->prim)); | ||
| 1003 | dev_priv->warp_pipe = 0; | ||
| 1004 | memset(dev_priv->warp_pipe_phys, 0, | ||
| 1005 | sizeof(dev_priv->warp_pipe_phys)); | ||
| 1006 | |||
| 1007 | if (dev_priv->head != NULL) | ||
| 1008 | mga_freelist_cleanup(dev); | ||
| 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 | return err; | ||
| 1028 | case MGA_CLEANUP_DMA: | ||
| 1029 | return mga_do_cleanup_dma(dev, FULL_CLEANUP); | ||
| 1030 | } | ||
| 1031 | |||
| 1032 | return -EINVAL; | ||
| 1033 | } | ||
| 1034 | |||
| 1035 | /* ================================================================ | ||
| 1036 | * Primary DMA stream management | ||
| 1037 | */ | ||
| 1038 | |||
| 1039 | int mga_dma_flush(struct drm_device *dev, void *data, | ||
| 1040 | struct drm_file *file_priv) | ||
| 1041 | { | ||
| 1042 | drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private; | ||
| 1043 | struct drm_lock *lock = data; | ||
| 1044 | |||
| 1045 | LOCK_TEST_WITH_RETURN(dev, file_priv); | ||
| 1046 | |||
| 1047 | DRM_DEBUG("%s%s%s\n", | ||
| 1048 | (lock->flags & _DRM_LOCK_FLUSH) ? "flush, " : "", | ||
| 1049 | (lock->flags & _DRM_LOCK_FLUSH_ALL) ? "flush all, " : "", | ||
| 1050 | (lock->flags & _DRM_LOCK_QUIESCENT) ? "idle, " : ""); | ||
| 1051 | |||
| 1052 | WRAP_WAIT_WITH_RETURN(dev_priv); | ||
| 1053 | |||
| 1054 | if (lock->flags & (_DRM_LOCK_FLUSH | _DRM_LOCK_FLUSH_ALL)) | ||
| 1055 | mga_do_dma_flush(dev_priv); | ||
| 1056 | |||
| 1057 | if (lock->flags & _DRM_LOCK_QUIESCENT) { | ||
| 1058 | #if MGA_DMA_DEBUG | ||
| 1059 | int ret = mga_do_wait_for_idle(dev_priv); | ||
| 1060 | if (ret < 0) | ||
| 1061 | DRM_INFO("-EBUSY\n"); | ||
| 1062 | return ret; | ||
| 1063 | #else | ||
| 1064 | return mga_do_wait_for_idle(dev_priv); | ||
| 1065 | #endif | ||
| 1066 | } else { | ||
| 1067 | return 0; | ||
| 1068 | } | ||
| 1069 | } | ||
| 1070 | |||
| 1071 | int mga_dma_reset(struct drm_device *dev, void *data, | ||
| 1072 | struct drm_file *file_priv) | ||
| 1073 | { | ||
| 1074 | drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private; | ||
| 1075 | |||
| 1076 | LOCK_TEST_WITH_RETURN(dev, file_priv); | ||
| 1077 | |||
| 1078 | return mga_do_dma_reset(dev_priv); | ||
| 1079 | } | ||
| 1080 | |||
| 1081 | /* ================================================================ | ||
| 1082 | * DMA buffer management | ||
| 1083 | */ | ||
| 1084 | |||
| 1085 | static int mga_dma_get_buffers(struct drm_device *dev, | ||
| 1086 | struct drm_file *file_priv, struct drm_dma *d) | ||
| 1087 | { | ||
| 1088 | struct drm_buf *buf; | ||
| 1089 | int i; | ||
| 1090 | |||
| 1091 | for (i = d->granted_count; i < d->request_count; i++) { | ||
| 1092 | buf = mga_freelist_get(dev); | ||
| 1093 | if (!buf) | ||
| 1094 | return -EAGAIN; | ||
| 1095 | |||
| 1096 | buf->file_priv = file_priv; | ||
| 1097 | |||
| 1098 | if (copy_to_user(&d->request_indices[i], | ||
| 1099 | &buf->idx, sizeof(buf->idx))) | ||
| 1100 | return -EFAULT; | ||
| 1101 | if (copy_to_user(&d->request_sizes[i], | ||
| 1102 | &buf->total, sizeof(buf->total))) | ||
| 1103 | return -EFAULT; | ||
| 1104 | |||
| 1105 | d->granted_count++; | ||
| 1106 | } | ||
| 1107 | return 0; | ||
| 1108 | } | ||
| 1109 | |||
| 1110 | int mga_dma_buffers(struct drm_device *dev, void *data, | ||
| 1111 | struct drm_file *file_priv) | ||
| 1112 | { | ||
| 1113 | struct drm_device_dma *dma = dev->dma; | ||
| 1114 | drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private; | ||
| 1115 | struct drm_dma *d = data; | ||
| 1116 | int ret = 0; | ||
| 1117 | |||
| 1118 | LOCK_TEST_WITH_RETURN(dev, file_priv); | ||
| 1119 | |||
| 1120 | /* Please don't send us buffers. | ||
| 1121 | */ | ||
| 1122 | if (d->send_count != 0) { | ||
| 1123 | DRM_ERROR("Process %d trying to send %d buffers via drmDMA\n", | ||
| 1124 | task_pid_nr(current), d->send_count); | ||
| 1125 | return -EINVAL; | ||
| 1126 | } | ||
| 1127 | |||
| 1128 | /* We'll send you buffers. | ||
| 1129 | */ | ||
| 1130 | if (d->request_count < 0 || d->request_count > dma->buf_count) { | ||
| 1131 | DRM_ERROR("Process %d trying to get %d buffers (of %d max)\n", | ||
| 1132 | task_pid_nr(current), d->request_count, | ||
| 1133 | dma->buf_count); | ||
| 1134 | return -EINVAL; | ||
| 1135 | } | ||
| 1136 | |||
| 1137 | WRAP_TEST_WITH_RETURN(dev_priv); | ||
| 1138 | |||
| 1139 | d->granted_count = 0; | ||
| 1140 | |||
| 1141 | if (d->request_count) | ||
| 1142 | ret = mga_dma_get_buffers(dev, file_priv, d); | ||
| 1143 | |||
| 1144 | return ret; | ||
| 1145 | } | ||
| 1146 | |||
| 1147 | /* | ||
| 1148 | * Called just before the module is unloaded. | ||
| 1149 | */ | ||
| 1150 | void mga_driver_unload(struct drm_device *dev) | ||
| 1151 | { | ||
| 1152 | kfree(dev->dev_private); | ||
| 1153 | dev->dev_private = NULL; | ||
| 1154 | } | ||
| 1155 | |||
| 1156 | /* | ||
| 1157 | * Called when the last opener of the device is closed. | ||
| 1158 | */ | ||
| 1159 | void mga_driver_lastclose(struct drm_device *dev) | ||
| 1160 | { | ||
| 1161 | mga_do_cleanup_dma(dev, FULL_CLEANUP); | ||
| 1162 | } | ||
| 1163 | |||
| 1164 | int mga_driver_dma_quiescent(struct drm_device *dev) | ||
| 1165 | { | ||
| 1166 | drm_mga_private_t *dev_priv = dev->dev_private; | ||
| 1167 | return mga_do_wait_for_idle(dev_priv); | ||
| 1168 | } | ||
| @@ -1,104 +0,0 @@ | |||
| 1 | /* mga_drv.c -- Matrox G200/G400 driver -*- linux-c -*- | ||
| 2 | * Created: Mon Dec 13 01:56:22 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 | * VA LINUX SYSTEMS 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 | ||
| 25 | * OTHER DEALINGS IN THE SOFTWARE. | ||
| 26 | * | ||
| 27 | * Authors: | ||
| 28 | * Rickard E. (Rik) Faith <faith@valinux.com> | ||
| 29 | * Gareth Hughes <gareth@valinux.com> | ||
| 30 | */ | ||
| 31 | |||
| 32 | #include <linux/module.h> | ||
| 33 | |||
| 34 | #include <drm/drm_drv.h> | ||
| 35 | #include <drm/drm_pciids.h> | ||
| 36 | |||
| 37 | #include "mga_drv.h" | ||
| 38 | |||
| 39 | static struct pci_device_id pciidlist[] = { | ||
| 40 | mga_PCI_IDS | ||
| 41 | }; | ||
| 42 | |||
| 43 | static const struct file_operations mga_driver_fops = { | ||
| 44 | .owner = THIS_MODULE, | ||
| 45 | .open = drm_open, | ||
| 46 | .release = drm_release, | ||
| 47 | .unlocked_ioctl = drm_ioctl, | ||
| 48 | .mmap = drm_legacy_mmap, | ||
| 49 | .poll = drm_poll, | ||
| 50 | #ifdef CONFIG_COMPAT | ||
| 51 | .compat_ioctl = mga_compat_ioctl, | ||
| 52 | #endif | ||
| 53 | .llseek = noop_llseek, | ||
| 54 | }; | ||
| 55 | |||
| 56 | static struct drm_driver driver = { | ||
| 57 | .driver_features = | ||
| 58 | DRIVER_USE_AGP | DRIVER_PCI_DMA | DRIVER_LEGACY | | ||
| 59 | DRIVER_HAVE_DMA | DRIVER_HAVE_IRQ, | ||
| 60 | .dev_priv_size = sizeof(drm_mga_buf_priv_t), | ||
| 61 | .load = mga_driver_load, | ||
| 62 | .unload = mga_driver_unload, | ||
| 63 | .lastclose = mga_driver_lastclose, | ||
| 64 | .dma_quiescent = mga_driver_dma_quiescent, | ||
| 65 | .get_vblank_counter = mga_get_vblank_counter, | ||
| 66 | .enable_vblank = mga_enable_vblank, | ||
| 67 | .disable_vblank = mga_disable_vblank, | ||
| 68 | .irq_preinstall = mga_driver_irq_preinstall, | ||
| 69 | .irq_postinstall = mga_driver_irq_postinstall, | ||
| 70 | .irq_uninstall = mga_driver_irq_uninstall, | ||
| 71 | .irq_handler = mga_driver_irq_handler, | ||
| 72 | .ioctls = mga_ioctls, | ||
| 73 | .dma_ioctl = mga_dma_buffers, | ||
| 74 | .fops = &mga_driver_fops, | ||
| 75 | .name = DRIVER_NAME, | ||
| 76 | .desc = DRIVER_DESC, | ||
| 77 | .date = DRIVER_DATE, | ||
| 78 | .major = DRIVER_MAJOR, | ||
| 79 | .minor = DRIVER_MINOR, | ||
| 80 | .patchlevel = DRIVER_PATCHLEVEL, | ||
| 81 | }; | ||
| 82 | |||
| 83 | static struct pci_driver mga_pci_driver = { | ||
| 84 | .name = DRIVER_NAME, | ||
| 85 | .id_table = pciidlist, | ||
| 86 | }; | ||
| 87 | |||
| 88 | static int __init mga_init(void) | ||
| 89 | { | ||
| 90 | driver.num_ioctls = mga_max_ioctl; | ||
| 91 | return drm_legacy_pci_init(&driver, &mga_pci_driver); | ||
| 92 | } | ||
| 93 | |||
| 94 | static void __exit mga_exit(void) | ||
| 95 | { | ||
| 96 | drm_legacy_pci_exit(&driver, &mga_pci_driver); | ||
| 97 | } | ||
| 98 | |||
| 99 | module_init(mga_init); | ||
| 100 | module_exit(mga_exit); | ||
| 101 | |||
| 102 | MODULE_AUTHOR(DRIVER_AUTHOR); | ||
| 103 | MODULE_DESCRIPTION(DRIVER_DESC); | ||
| 104 | MODULE_LICENSE("GPL and additional rights"); | ||
| @@ -1,685 +0,0 @@ | |||
| 1 | /* mga_drv.h -- Private header for the Matrox G200/G400 driver -*- 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 | * VA LINUX SYSTEMS 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 | ||
| 25 | * OTHER DEALINGS IN THE SOFTWARE. | ||
| 26 | * | ||
| 27 | * Authors: | ||
| 28 | * Gareth Hughes <gareth@valinux.com> | ||
| 29 | */ | ||
| 30 | |||
| 31 | #ifndef __MGA_DRV_H__ | ||
| 32 | #define __MGA_DRV_H__ | ||
| 33 | |||
| 34 | #include <linux/irqreturn.h> | ||
| 35 | #include <linux/pci.h> | ||
| 36 | #include <linux/slab.h> | ||
| 37 | |||
| 38 | #include <drm/drm_device.h> | ||
| 39 | #include <drm/drm_file.h> | ||
| 40 | #include <drm/drm_ioctl.h> | ||
| 41 | #include <drm/drm_legacy.h> | ||
| 42 | #include <drm/drm_print.h> | ||
| 43 | #include <drm/drm_sarea.h> | ||
| 44 | #include <drm/drm_vblank.h> | ||
| 45 | #include <drm/mga_drm.h> | ||
| 46 | |||
| 47 | /* General customization: | ||
| 48 | */ | ||
| 49 | |||
| 50 | #define DRIVER_AUTHOR "Gareth Hughes, VA Linux Systems Inc." | ||
| 51 | |||
| 52 | #define DRIVER_NAME "mga" | ||
| 53 | #define DRIVER_DESC "Matrox G200/G400" | ||
| 54 | #define DRIVER_DATE "20051102" | ||
| 55 | |||
| 56 | #define DRIVER_MAJOR 3 | ||
| 57 | #define DRIVER_MINOR 2 | ||
| 58 | #define DRIVER_PATCHLEVEL 1 | ||
| 59 | |||
| 60 | typedef struct drm_mga_primary_buffer { | ||
| 61 | u8 *start; | ||
| 62 | u8 *end; | ||
| 63 | int size; | ||
| 64 | |||
| 65 | u32 tail; | ||
| 66 | int space; | ||
| 67 | volatile long wrapped; | ||
| 68 | |||
| 69 | volatile u32 *status; | ||
| 70 | |||
| 71 | u32 last_flush; | ||
| 72 | u32 last_wrap; | ||
| 73 | |||
| 74 | u32 high_mark; | ||
| 75 | } drm_mga_primary_buffer_t; | ||
| 76 | |||
| 77 | typedef struct drm_mga_freelist { | ||
| 78 | struct drm_mga_freelist *next; | ||
| 79 | struct drm_mga_freelist *prev; | ||
| 80 | drm_mga_age_t age; | ||
| 81 | struct drm_buf *buf; | ||
| 82 | } drm_mga_freelist_t; | ||
| 83 | |||
| 84 | typedef struct { | ||
| 85 | drm_mga_freelist_t *list_entry; | ||
| 86 | int discard; | ||
| 87 | int dispatched; | ||
| 88 | } drm_mga_buf_priv_t; | ||
| 89 | |||
| 90 | typedef struct drm_mga_private { | ||
| 91 | drm_mga_primary_buffer_t prim; | ||
| 92 | drm_mga_sarea_t *sarea_priv; | ||
| 93 | |||
| 94 | drm_mga_freelist_t *head; | ||
| 95 | drm_mga_freelist_t *tail; | ||
| 96 | |||
| 97 | unsigned int warp_pipe; | ||
| 98 | unsigned long warp_pipe_phys[MGA_MAX_WARP_PIPES]; | ||
| 99 | |||
| 100 | int chipset; | ||
| 101 | int usec_timeout; | ||
| 102 | |||
| 103 | /** | ||
| 104 | * If set, the new DMA initialization sequence was used. This is | ||
| 105 | * primarilly used to select how the driver should uninitialized its | ||
| 106 | * internal DMA structures. | ||
| 107 | */ | ||
| 108 | int used_new_dma_init; | ||
| 109 | |||
| 110 | /** | ||
| 111 | * If AGP memory is used for DMA buffers, this will be the value | ||
| 112 | * \c MGA_PAGPXFER. Otherwise, it will be zero (for a PCI transfer). | ||
| 113 | */ | ||
| 114 | u32 dma_access; | ||
| 115 | |||
| 116 | /** | ||
| 117 | * If AGP memory is used for DMA buffers, this will be the value | ||
| 118 | * \c MGA_WAGP_ENABLE. Otherwise, it will be zero (for a PCI | ||
| 119 | * transfer). | ||
| 120 | */ | ||
| 121 | u32 wagp_enable; | ||
| 122 | |||
| 123 | /** | ||
| 124 | * \name MMIO region parameters. | ||
| 125 | * | ||
| 126 | * \sa drm_mga_private_t::mmio | ||
| 127 | */ | ||
| 128 | /*@{ */ | ||
| 129 | resource_size_t mmio_base; /**< Bus address of base of MMIO. */ | ||
| 130 | resource_size_t mmio_size; /**< Size of the MMIO region. */ | ||
| 131 | /*@} */ | ||
| 132 | |||
| 133 | u32 clear_cmd; | ||
| 134 | u32 maccess; | ||
| 135 | |||
| 136 | atomic_t vbl_received; /**< Number of vblanks received. */ | ||
| 137 | wait_queue_head_t fence_queue; | ||
| 138 | atomic_t last_fence_retired; | ||
| 139 | u32 next_fence_to_post; | ||
| 140 | |||
| 141 | unsigned int fb_cpp; | ||
| 142 | unsigned int front_offset; | ||
| 143 | unsigned int front_pitch; | ||
| 144 | unsigned int back_offset; | ||
| 145 | unsigned int back_pitch; | ||
| 146 | |||
| 147 | unsigned int depth_cpp; | ||
| 148 | unsigned int depth_offset; | ||
| 149 | unsigned int depth_pitch; | ||
| 150 | |||
| 151 | unsigned int texture_offset; | ||
| 152 | unsigned int texture_size; | ||
| 153 | |||
| 154 | drm_local_map_t *sarea; | ||
| 155 | drm_local_map_t *mmio; | ||
| 156 | drm_local_map_t *status; | ||
| 157 | drm_local_map_t *warp; | ||
| 158 | drm_local_map_t *primary; | ||
| 159 | drm_local_map_t *agp_textures; | ||
| 160 | |||
| 161 | unsigned long agp_handle; | ||
| 162 | unsigned int agp_size; | ||
| 163 | } drm_mga_private_t; | ||
| 164 | |||
| 165 | extern const struct drm_ioctl_desc mga_ioctls[]; | ||
| 166 | extern int mga_max_ioctl; | ||
| 167 | |||
| 168 | /* mga_dma.c */ | ||
| 169 | extern int mga_dma_bootstrap(struct drm_device *dev, void *data, | ||
| 170 | struct drm_file *file_priv); | ||
| 171 | extern int mga_dma_init(struct drm_device *dev, void *data, | ||
| 172 | struct drm_file *file_priv); | ||
| 173 | extern int mga_getparam(struct drm_device *dev, void *data, | ||
| 174 | struct drm_file *file_priv); | ||
| 175 | extern int mga_dma_flush(struct drm_device *dev, void *data, | ||
| 176 | struct drm_file *file_priv); | ||
| 177 | extern int mga_dma_reset(struct drm_device *dev, void *data, | ||
| 178 | struct drm_file *file_priv); | ||
| 179 | extern int mga_dma_buffers(struct drm_device *dev, void *data, | ||
| 180 | struct drm_file *file_priv); | ||
| 181 | extern int mga_driver_load(struct drm_device *dev, unsigned long flags); | ||
| 182 | extern void mga_driver_unload(struct drm_device *dev); | ||
| 183 | extern void mga_driver_lastclose(struct drm_device *dev); | ||
| 184 | extern int mga_driver_dma_quiescent(struct drm_device *dev); | ||
| 185 | |||
| 186 | extern int mga_do_wait_for_idle(drm_mga_private_t *dev_priv); | ||
| 187 | |||
| 188 | extern void mga_do_dma_flush(drm_mga_private_t *dev_priv); | ||
| 189 | extern void mga_do_dma_wrap_start(drm_mga_private_t *dev_priv); | ||
| 190 | extern void mga_do_dma_wrap_end(drm_mga_private_t *dev_priv); | ||
| 191 | |||
| 192 | extern int mga_freelist_put(struct drm_device *dev, struct drm_buf *buf); | ||
| 193 | |||
| 194 | /* mga_warp.c */ | ||
| 195 | extern int mga_warp_install_microcode(drm_mga_private_t *dev_priv); | ||
| 196 | extern int mga_warp_init(drm_mga_private_t *dev_priv); | ||
| 197 | |||
| 198 | /* mga_irq.c */ | ||
| 199 | extern int mga_enable_vblank(struct drm_device *dev, unsigned int pipe); | ||
| 200 | extern void mga_disable_vblank(struct drm_device *dev, unsigned int pipe); | ||
| 201 | extern u32 mga_get_vblank_counter(struct drm_device *dev, unsigned int pipe); | ||
| 202 | extern void mga_driver_fence_wait(struct drm_device *dev, unsigned int *sequence); | ||
| 203 | extern int mga_driver_vblank_wait(struct drm_device *dev, unsigned int *sequence); | ||
| 204 | extern irqreturn_t mga_driver_irq_handler(int irq, void *arg); | ||
| 205 | extern void mga_driver_irq_preinstall(struct drm_device *dev); | ||
| 206 | extern int mga_driver_irq_postinstall(struct drm_device *dev); | ||
| 207 | extern void mga_driver_irq_uninstall(struct drm_device *dev); | ||
| 208 | extern long mga_compat_ioctl(struct file *filp, unsigned int cmd, | ||
| 209 | unsigned long arg); | ||
| 210 | |||
| 211 | #define mga_flush_write_combine() wmb() | ||
| 212 | |||
| 213 | #define MGA_READ8(reg) \ | ||
| 214 | readb(((void __iomem *)dev_priv->mmio->handle) + (reg)) | ||
| 215 | #define MGA_READ(reg) \ | ||
| 216 | readl(((void __iomem *)dev_priv->mmio->handle) + (reg)) | ||
| 217 | #define MGA_WRITE8(reg, val) \ | ||
| 218 | writeb(val, ((void __iomem *)dev_priv->mmio->handle) + (reg)) | ||
| 219 | #define MGA_WRITE(reg, val) \ | ||
| 220 | writel(val, ((void __iomem *)dev_priv->mmio->handle) + (reg)) | ||
| 221 | |||
| 222 | #define DWGREG0 0x1c00 | ||
| 223 | #define DWGREG0_END 0x1dff | ||
| 224 | #define DWGREG1 0x2c00 | ||
| 225 | #define DWGREG1_END 0x2dff | ||
| 226 | |||
| 227 | #define ISREG0(r) (r >= DWGREG0 && r <= DWGREG0_END) | ||
| 228 | #define DMAREG0(r) (u8)((r - DWGREG0) >> 2) | ||
| 229 | #define DMAREG1(r) (u8)(((r - DWGREG1) >> 2) | 0x80) | ||
| 230 | #define DMAREG(r) (ISREG0(r) ? DMAREG0(r) : DMAREG1(r)) | ||
| 231 | |||
| 232 | /* ================================================================ | ||
| 233 | * Helper macross... | ||
| 234 | */ | ||
| 235 | |||
| 236 | #define MGA_EMIT_STATE(dev_priv, dirty) \ | ||
| 237 | do { \ | ||
| 238 | if ((dirty) & ~MGA_UPLOAD_CLIPRECTS) { \ | ||
| 239 | if (dev_priv->chipset >= MGA_CARD_TYPE_G400) \ | ||
| 240 | mga_g400_emit_state(dev_priv); \ | ||
| 241 | else \ | ||
| 242 | mga_g200_emit_state(dev_priv); \ | ||
| 243 | } \ | ||
| 244 | } while (0) | ||
| 245 | |||
| 246 | #define WRAP_TEST_WITH_RETURN(dev_priv) \ | ||
| 247 | do { \ | ||
| 248 | if (test_bit(0, &dev_priv->prim.wrapped)) { \ | ||
| 249 | if (mga_is_idle(dev_priv)) { \ | ||
| 250 | mga_do_dma_wrap_end(dev_priv); \ | ||
| 251 | } else if (dev_priv->prim.space < \ | ||
| 252 | dev_priv->prim.high_mark) { \ | ||
| 253 | if (MGA_DMA_DEBUG) \ | ||
| 254 | DRM_INFO("wrap...\n"); \ | ||
| 255 | return -EBUSY; \ | ||
| 256 | } \ | ||
| 257 | } \ | ||
| 258 | } while (0) | ||
| 259 | |||
| 260 | #define WRAP_WAIT_WITH_RETURN(dev_priv) \ | ||
| 261 | do { \ | ||
| 262 | if (test_bit(0, &dev_priv->prim.wrapped)) { \ | ||
| 263 | if (mga_do_wait_for_idle(dev_priv) < 0) { \ | ||
| 264 | if (MGA_DMA_DEBUG) \ | ||
| 265 | DRM_INFO("wrap...\n"); \ | ||
| 266 | return -EBUSY; \ | ||
| 267 | } \ | ||
| 268 | mga_do_dma_wrap_end(dev_priv); \ | ||
| 269 | } \ | ||
| 270 | } while (0) | ||
| 271 | |||
| 272 | /* ================================================================ | ||
| 273 | * Primary DMA command stream | ||
| 274 | */ | ||
| 275 | |||
| 276 | #define MGA_VERBOSE 0 | ||
| 277 | |||
| 278 | #define DMA_LOCALS unsigned int write; volatile u8 *prim; | ||
| 279 | |||
| 280 | #define DMA_BLOCK_SIZE (5 * sizeof(u32)) | ||
| 281 | |||
| 282 | #define BEGIN_DMA(n) \ | ||
| 283 | do { \ | ||
| 284 | if (MGA_VERBOSE) { \ | ||
| 285 | DRM_INFO("BEGIN_DMA(%d)\n", (n)); \ | ||
| 286 | DRM_INFO(" space=0x%x req=0x%zx\n", \ | ||
| 287 | dev_priv->prim.space, (n) * DMA_BLOCK_SIZE); \ | ||
| 288 | } \ | ||
| 289 | prim = dev_priv->prim.start; \ | ||
| 290 | write = dev_priv->prim.tail; \ | ||
| 291 | } while (0) | ||
| 292 | |||
| 293 | #define BEGIN_DMA_WRAP() \ | ||
| 294 | do { \ | ||
| 295 | if (MGA_VERBOSE) { \ | ||
| 296 | DRM_INFO("BEGIN_DMA()\n"); \ | ||
| 297 | DRM_INFO(" space=0x%x\n", dev_priv->prim.space); \ | ||
| 298 | } \ | ||
| 299 | prim = dev_priv->prim.start; \ | ||
| 300 | write = dev_priv->prim.tail; \ | ||
| 301 | } while (0) | ||
| 302 | |||
| 303 | #define ADVANCE_DMA() \ | ||
| 304 | do { \ | ||
| 305 | dev_priv->prim.tail = write; \ | ||
| 306 | if (MGA_VERBOSE) \ | ||
| 307 | DRM_INFO("ADVANCE_DMA() tail=0x%05x sp=0x%x\n", \ | ||
| 308 | write, dev_priv->prim.space); \ | ||
| 309 | } while (0) | ||
| 310 | |||
| 311 | #define FLUSH_DMA() \ | ||
| 312 | do { \ | ||
| 313 | if (0) { \ | ||
| 314 | DRM_INFO("\n"); \ | ||
| 315 | DRM_INFO(" tail=0x%06x head=0x%06lx\n", \ | ||
| 316 | dev_priv->prim.tail, \ | ||
| 317 | (unsigned long)(MGA_READ(MGA_PRIMADDRESS) - \ | ||
| 318 | dev_priv->primary->offset)); \ | ||
| 319 | } \ | ||
| 320 | if (!test_bit(0, &dev_priv->prim.wrapped)) { \ | ||
| 321 | if (dev_priv->prim.space < dev_priv->prim.high_mark) \ | ||
| 322 | mga_do_dma_wrap_start(dev_priv); \ | ||
| 323 | else \ | ||
| 324 | mga_do_dma_flush(dev_priv); \ | ||
| 325 | } \ | ||
| 326 | } while (0) | ||
| 327 | |||
| 328 | /* Never use this, always use DMA_BLOCK(...) for primary DMA output. | ||
| 329 | */ | ||
| 330 | #define DMA_WRITE(offset, val) \ | ||
| 331 | do { \ | ||
| 332 | if (MGA_VERBOSE) \ | ||
| 333 | DRM_INFO(" DMA_WRITE( 0x%08x ) at 0x%04zx\n", \ | ||
| 334 | (u32)(val), write + (offset) * sizeof(u32)); \ | ||
| 335 | *(volatile u32 *)(prim + write + (offset) * sizeof(u32)) = val; \ | ||
| 336 | } while (0) | ||
| 337 | |||
| 338 | #define DMA_BLOCK(reg0, val0, reg1, val1, reg2, val2, reg3, val3) \ | ||
| 339 | do { \ | ||
| 340 | DMA_WRITE(0, ((DMAREG(reg0) << 0) | \ | ||
| 341 | (DMAREG(reg1) << 8) | \ | ||
| 342 | (DMAREG(reg2) << 16) | \ | ||
| 343 | (DMAREG(reg3) << 24))); \ | ||
| 344 | DMA_WRITE(1, val0); \ | ||
| 345 | DMA_WRITE(2, val1); \ | ||
| 346 | DMA_WRITE(3, val2); \ | ||
| 347 | DMA_WRITE(4, val3); \ | ||
| 348 | write += DMA_BLOCK_SIZE; \ | ||
| 349 | } while (0) | ||
| 350 | |||
| 351 | /* Buffer aging via primary DMA stream head pointer. | ||
| 352 | */ | ||
| 353 | |||
| 354 | #define SET_AGE(age, h, w) \ | ||
| 355 | do { \ | ||
| 356 | (age)->head = h; \ | ||
| 357 | (age)->wrap = w; \ | ||
| 358 | } while (0) | ||
| 359 | |||
| 360 | #define TEST_AGE(age, h, w) ((age)->wrap < w || \ | ||
| 361 | ((age)->wrap == w && \ | ||
| 362 | (age)->head < h)) | ||
| 363 | |||
| 364 | #define AGE_BUFFER(buf_priv) \ | ||
| 365 | do { \ | ||
| 366 | drm_mga_freelist_t *entry = (buf_priv)->list_entry; \ | ||
| 367 | if ((buf_priv)->dispatched) { \ | ||
| 368 | entry->age.head = (dev_priv->prim.tail + \ | ||
| 369 | dev_priv->primary->offset); \ | ||
| 370 | entry->age.wrap = dev_priv->sarea_priv->last_wrap; \ | ||
| 371 | } else { \ | ||
| 372 | entry->age.head = 0; \ | ||
| 373 | entry->age.wrap = 0; \ | ||
| 374 | } \ | ||
| 375 | } while (0) | ||
| 376 | |||
| 377 | #define MGA_ENGINE_IDLE_MASK (MGA_SOFTRAPEN | \ | ||
| 378 | MGA_DWGENGSTS | \ | ||
| 379 | MGA_ENDPRDMASTS) | ||
| 380 | #define MGA_DMA_IDLE_MASK (MGA_SOFTRAPEN | \ | ||
| 381 | MGA_ENDPRDMASTS) | ||
| 382 | |||
| 383 | #define MGA_DMA_DEBUG 0 | ||
| 384 | |||
| 385 | /* A reduced set of the mga registers. | ||
| 386 | */ | ||
| 387 | #define MGA_CRTC_INDEX 0x1fd4 | ||
| 388 | #define MGA_CRTC_DATA 0x1fd5 | ||
| 389 | |||
| 390 | /* CRTC11 */ | ||
| 391 | #define MGA_VINTCLR (1 << 4) | ||
| 392 | #define MGA_VINTEN (1 << 5) | ||
| 393 | |||
| 394 | #define MGA_ALPHACTRL 0x2c7c | ||
| 395 | #define MGA_AR0 0x1c60 | ||
| 396 | #define MGA_AR1 0x1c64 | ||
| 397 | #define MGA_AR2 0x1c68 | ||
| 398 | #define MGA_AR3 0x1c6c | ||
| 399 | #define MGA_AR4 0x1c70 | ||
| 400 | #define MGA_AR5 0x1c74 | ||
| 401 | #define MGA_AR6 0x1c78 | ||
| 402 | |||
| 403 | #define MGA_CXBNDRY 0x1c80 | ||
| 404 | #define MGA_CXLEFT 0x1ca0 | ||
| 405 | #define MGA_CXRIGHT 0x1ca4 | ||
| 406 | |||
| 407 | #define MGA_DMAPAD 0x1c54 | ||
| 408 | #define MGA_DSTORG 0x2cb8 | ||
| 409 | #define MGA_DWGCTL 0x1c00 | ||
| 410 | # define MGA_OPCOD_MASK (15 << 0) | ||
| 411 | # define MGA_OPCOD_TRAP (4 << 0) | ||
| 412 | # define MGA_OPCOD_TEXTURE_TRAP (6 << 0) | ||
| 413 | # define MGA_OPCOD_BITBLT (8 << 0) | ||
| 414 | # define MGA_OPCOD_ILOAD (9 << 0) | ||
| 415 | # define MGA_ATYPE_MASK (7 << 4) | ||
| 416 | # define MGA_ATYPE_RPL (0 << 4) | ||
| 417 | # define MGA_ATYPE_RSTR (1 << 4) | ||
| 418 | # define MGA_ATYPE_ZI (3 << 4) | ||
| 419 | # define MGA_ATYPE_BLK (4 << 4) | ||
| 420 | # define MGA_ATYPE_I (7 << 4) | ||
| 421 | # define MGA_LINEAR (1 << 7) | ||
| 422 | # define MGA_ZMODE_MASK (7 << 8) | ||
| 423 | # define MGA_ZMODE_NOZCMP (0 << 8) | ||
| 424 | # define MGA_ZMODE_ZE (2 << 8) | ||
| 425 | # define MGA_ZMODE_ZNE (3 << 8) | ||
| 426 | # define MGA_ZMODE_ZLT (4 << 8) | ||
| 427 | # define MGA_ZMODE_ZLTE (5 << 8) | ||
| 428 | # define MGA_ZMODE_ZGT (6 << 8) | ||
| 429 | # define MGA_ZMODE_ZGTE (7 << 8) | ||
| 430 | # define MGA_SOLID (1 << 11) | ||
| 431 | # define MGA_ARZERO (1 << 12) | ||
| 432 | # define MGA_SGNZERO (1 << 13) | ||
| 433 | # define MGA_SHIFTZERO (1 << 14) | ||
| 434 | # define MGA_BOP_MASK (15 << 16) | ||
| 435 | # define MGA_BOP_ZERO (0 << 16) | ||
| 436 | # define MGA_BOP_DST (10 << 16) | ||
| 437 | # define MGA_BOP_SRC (12 << 16) | ||
| 438 | # define MGA_BOP_ONE (15 << 16) | ||
| 439 | # define MGA_TRANS_SHIFT 20 | ||
| 440 | # define MGA_TRANS_MASK (15 << 20) | ||
| 441 | # define MGA_BLTMOD_MASK (15 << 25) | ||
| 442 | # define MGA_BLTMOD_BMONOLEF (0 << 25) | ||
| 443 | # define MGA_BLTMOD_BMONOWF (4 << 25) | ||
| 444 | # define MGA_BLTMOD_PLAN (1 << 25) | ||
| 445 | # define MGA_BLTMOD_BFCOL (2 << 25) | ||
| 446 | # define MGA_BLTMOD_BU32BGR (3 << 25) | ||
| 447 | # define MGA_BLTMOD_BU32RGB (7 << 25) | ||
| 448 | # define MGA_BLTMOD_BU24BGR (11 << 25) | ||
| 449 | # define MGA_BLTMOD_BU24RGB (15 << 25) | ||
| 450 | # define MGA_PATTERN (1 << 29) | ||
| 451 | # define MGA_TRANSC (1 << 30) | ||
| 452 | # define MGA_CLIPDIS (1 << 31) | ||
| 453 | #define MGA_DWGSYNC 0x2c4c | ||
| 454 | |||
| 455 | #define MGA_FCOL 0x1c24 | ||
| 456 | #define MGA_FIFOSTATUS 0x1e10 | ||
| 457 | #define MGA_FOGCOL 0x1cf4 | ||
| 458 | #define MGA_FXBNDRY 0x1c84 | ||
| 459 | #define MGA_FXLEFT 0x1ca8 | ||
| 460 | #define MGA_FXRIGHT 0x1cac | ||
| 461 | |||
| 462 | #define MGA_ICLEAR 0x1e18 | ||
| 463 | # define MGA_SOFTRAPICLR (1 << 0) | ||
| 464 | # define MGA_VLINEICLR (1 << 5) | ||
| 465 | #define MGA_IEN 0x1e1c | ||
| 466 | # define MGA_SOFTRAPIEN (1 << 0) | ||
| 467 | # define MGA_VLINEIEN (1 << 5) | ||
| 468 | |||
| 469 | #define MGA_LEN 0x1c5c | ||
| 470 | |||
| 471 | #define MGA_MACCESS 0x1c04 | ||
| 472 | |||
| 473 | #define MGA_PITCH 0x1c8c | ||
| 474 | #define MGA_PLNWT 0x1c1c | ||
| 475 | #define MGA_PRIMADDRESS 0x1e58 | ||
| 476 | # define MGA_DMA_GENERAL (0 << 0) | ||
| 477 | # define MGA_DMA_BLIT (1 << 0) | ||
| 478 | # define MGA_DMA_VECTOR (2 << 0) | ||
| 479 | # define MGA_DMA_VERTEX (3 << 0) | ||
| 480 | #define MGA_PRIMEND 0x1e5c | ||
| 481 | # define MGA_PRIMNOSTART (1 << 0) | ||
| 482 | # define MGA_PAGPXFER (1 << 1) | ||
| 483 | #define MGA_PRIMPTR 0x1e50 | ||
| 484 | # define MGA_PRIMPTREN0 (1 << 0) | ||
| 485 | # define MGA_PRIMPTREN1 (1 << 1) | ||
| 486 | |||
| 487 | #define MGA_RST 0x1e40 | ||
| 488 | # define MGA_SOFTRESET (1 << 0) | ||
| 489 | # define MGA_SOFTEXTRST (1 << 1) | ||
| 490 | |||
| 491 | #define MGA_SECADDRESS 0x2c40 | ||
| 492 | #define MGA_SECEND 0x2c44 | ||
| 493 | #define MGA_SETUPADDRESS 0x2cd0 | ||
| 494 | #define MGA_SETUPEND 0x2cd4 | ||
| 495 | #define MGA_SGN 0x1c58 | ||
| 496 | #define MGA_SOFTRAP 0x2c48 | ||
| 497 | #define MGA_SRCORG 0x2cb4 | ||
| 498 | # define MGA_SRMMAP_MASK (1 << 0) | ||
| 499 | # define MGA_SRCMAP_FB (0 << 0) | ||
| 500 | # define MGA_SRCMAP_SYSMEM (1 << 0) | ||
| 501 | # define MGA_SRCACC_MASK (1 << 1) | ||
| 502 | # define MGA_SRCACC_PCI (0 << 1) | ||
| 503 | # define MGA_SRCACC_AGP (1 << 1) | ||
| 504 | #define MGA_STATUS 0x1e14 | ||
| 505 | # define MGA_SOFTRAPEN (1 << 0) | ||
| 506 | # define MGA_VSYNCPEN (1 << 4) | ||
| 507 | # define MGA_VLINEPEN (1 << 5) | ||
| 508 | # define MGA_DWGENGSTS (1 << 16) | ||
| 509 | # define MGA_ENDPRDMASTS (1 << 17) | ||
| 510 | #define MGA_STENCIL 0x2cc8 | ||
| 511 | #define MGA_STENCILCTL 0x2ccc | ||
| 512 | |||
| 513 | #define MGA_TDUALSTAGE0 0x2cf8 | ||
| 514 | #define MGA_TDUALSTAGE1 0x2cfc | ||
| 515 | #define MGA_TEXBORDERCOL 0x2c5c | ||
| 516 | #define MGA_TEXCTL 0x2c30 | ||
| 517 | #define MGA_TEXCTL2 0x2c3c | ||
| 518 | # define MGA_DUALTEX (1 << 7) | ||
| 519 | # define MGA_G400_TC2_MAGIC (1 << 15) | ||
| 520 | # define MGA_MAP1_ENABLE (1 << 31) | ||
| 521 | #define MGA_TEXFILTER 0x2c58 | ||
| 522 | #define MGA_TEXHEIGHT 0x2c2c | ||
| 523 | #define MGA_TEXORG 0x2c24 | ||
| 524 | # define MGA_TEXORGMAP_MASK (1 << 0) | ||
| 525 | # define MGA_TEXORGMAP_FB (0 << 0) | ||
| 526 | # define MGA_TEXORGMAP_SYSMEM (1 << 0) | ||
| 527 | # define MGA_TEXORGACC_MASK (1 << 1) | ||
| 528 | # define MGA_TEXORGACC_PCI (0 << 1) | ||
| 529 | # define MGA_TEXORGACC_AGP (1 << 1) | ||
| 530 | #define MGA_TEXORG1 0x2ca4 | ||
| 531 | #define MGA_TEXORG2 0x2ca8 | ||
| 532 | #define MGA_TEXORG3 0x2cac | ||
| 533 | #define MGA_TEXORG4 0x2cb0 | ||
| 534 | #define MGA_TEXTRANS 0x2c34 | ||
| 535 | #define MGA_TEXTRANSHIGH 0x2c38 | ||
| 536 | #define MGA_TEXWIDTH 0x2c28 | ||
| 537 | |||
| 538 | #define MGA_WACCEPTSEQ 0x1dd4 | ||
| 539 | #define MGA_WCODEADDR 0x1e6c | ||
| 540 | #define MGA_WFLAG 0x1dc4 | ||
| 541 | #define MGA_WFLAG1 0x1de0 | ||
| 542 | #define MGA_WFLAGNB 0x1e64 | ||
| 543 | #define MGA_WFLAGNB1 0x1e08 | ||
| 544 | #define MGA_WGETMSB 0x1dc8 | ||
| 545 | #define MGA_WIADDR 0x1dc0 | ||
| 546 | #define MGA_WIADDR2 0x1dd8 | ||
| 547 | # define MGA_WMODE_SUSPEND (0 << 0) | ||
| 548 | # define MGA_WMODE_RESUME (1 << 0) | ||
| 549 | # define MGA_WMODE_JUMP (2 << 0) | ||
| 550 | # define MGA_WMODE_START (3 << 0) | ||
| 551 | # define MGA_WAGP_ENABLE (1 << 2) | ||
| 552 | #define MGA_WMISC 0x1e70 | ||
| 553 | # define MGA_WUCODECACHE_ENABLE (1 << 0) | ||
| 554 | # define MGA_WMASTER_ENABLE (1 << 1) | ||
| 555 | # define MGA_WCACHEFLUSH_ENABLE (1 << 3) | ||
| 556 | #define MGA_WVRTXSZ 0x1dcc | ||
| 557 | |||
| 558 | #define MGA_YBOT 0x1c9c | ||
| 559 | #define MGA_YDST 0x1c90 | ||
| 560 | #define MGA_YDSTLEN 0x1c88 | ||
| 561 | #define MGA_YDSTORG 0x1c94 | ||
| 562 | #define MGA_YTOP 0x1c98 | ||
| 563 | |||
| 564 | #define MGA_ZORG 0x1c0c | ||
| 565 | |||
| 566 | /* This finishes the current batch of commands | ||
| 567 | */ | ||
| 568 | #define MGA_EXEC 0x0100 | ||
| 569 | |||
| 570 | /* AGP PLL encoding (for G200 only). | ||
| 571 | */ | ||
| 572 | #define MGA_AGP_PLL 0x1e4c | ||
| 573 | # define MGA_AGP2XPLL_DISABLE (0 << 0) | ||
| 574 | # define MGA_AGP2XPLL_ENABLE (1 << 0) | ||
| 575 | |||
| 576 | /* Warp registers | ||
| 577 | */ | ||
| 578 | #define MGA_WR0 0x2d00 | ||
| 579 | #define MGA_WR1 0x2d04 | ||
| 580 | #define MGA_WR2 0x2d08 | ||
| 581 | #define MGA_WR3 0x2d0c | ||
| 582 | #define MGA_WR4 0x2d10 | ||
| 583 | #define MGA_WR5 0x2d14 | ||
| 584 | #define MGA_WR6 0x2d18 | ||
| 585 | #define MGA_WR7 0x2d1c | ||
| 586 | #define MGA_WR8 0x2d20 | ||
| 587 | #define MGA_WR9 0x2d24 | ||
| 588 | #define MGA_WR10 0x2d28 | ||
| 589 | #define MGA_WR11 0x2d2c | ||
| 590 | #define MGA_WR12 0x2d30 | ||
| 591 | #define MGA_WR13 0x2d34 | ||
| 592 | #define MGA_WR14 0x2d38 | ||
| 593 | #define MGA_WR15 0x2d3c | ||
| 594 | #define MGA_WR16 0x2d40 | ||
| 595 | #define MGA_WR17 0x2d44 | ||
| 596 | #define MGA_WR18 0x2d48 | ||
| 597 | #define MGA_WR19 0x2d4c | ||
| 598 | #define MGA_WR20 0x2d50 | ||
| 599 | #define MGA_WR21 0x2d54 | ||
| 600 | #define MGA_WR22 0x2d58 | ||
| 601 | #define MGA_WR23 0x2d5c | ||
| 602 | #define MGA_WR24 0x2d60 | ||
| 603 | #define MGA_WR25 0x2d64 | ||
| 604 | #define MGA_WR26 0x2d68 | ||
| 605 | #define MGA_WR27 0x2d6c | ||
| 606 | #define MGA_WR28 0x2d70 | ||
| 607 | #define MGA_WR29 0x2d74 | ||
| 608 | #define MGA_WR30 0x2d78 | ||
| 609 | #define MGA_WR31 0x2d7c | ||
| 610 | #define MGA_WR32 0x2d80 | ||
| 611 | #define MGA_WR33 0x2d84 | ||
| 612 | #define MGA_WR34 0x2d88 | ||
| 613 | #define MGA_WR35 0x2d8c | ||
| 614 | #define MGA_WR36 0x2d90 | ||
| 615 | #define MGA_WR37 0x2d94 | ||
| 616 | #define MGA_WR38 0x2d98 | ||
| 617 | #define MGA_WR39 0x2d9c | ||
| 618 | #define MGA_WR40 0x2da0 | ||
| 619 | #define MGA_WR41 0x2da4 | ||
| 620 | #define MGA_WR42 0x2da8 | ||
| 621 | #define MGA_WR43 0x2dac | ||
| 622 | #define MGA_WR44 0x2db0 | ||
| 623 | #define MGA_WR45 0x2db4 | ||
| 624 | #define MGA_WR46 0x2db8 | ||
| 625 | #define MGA_WR47 0x2dbc | ||
| 626 | #define MGA_WR48 0x2dc0 | ||
| 627 | #define MGA_WR49 0x2dc4 | ||
| 628 | #define MGA_WR50 0x2dc8 | ||
| 629 | #define MGA_WR51 0x2dcc | ||
| 630 | #define MGA_WR52 0x2dd0 | ||
| 631 | #define MGA_WR53 0x2dd4 | ||
| 632 | #define MGA_WR54 0x2dd8 | ||
| 633 | #define MGA_WR55 0x2ddc | ||
| 634 | #define MGA_WR56 0x2de0 | ||
| 635 | #define MGA_WR57 0x2de4 | ||
| 636 | #define MGA_WR58 0x2de8 | ||
| 637 | #define MGA_WR59 0x2dec | ||
| 638 | #define MGA_WR60 0x2df0 | ||
| 639 | #define MGA_WR61 0x2df4 | ||
| 640 | #define MGA_WR62 0x2df8 | ||
| 641 | #define MGA_WR63 0x2dfc | ||
| 642 | # define MGA_G400_WR_MAGIC (1 << 6) | ||
| 643 | # define MGA_G400_WR56_MAGIC 0x46480000 /* 12800.0f */ | ||
| 644 | |||
| 645 | #define MGA_ILOAD_ALIGN 64 | ||
| 646 | #define MGA_ILOAD_MASK (MGA_ILOAD_ALIGN - 1) | ||
| 647 | |||
| 648 | #define MGA_DWGCTL_FLUSH (MGA_OPCOD_TEXTURE_TRAP | \ | ||
| 649 | MGA_ATYPE_I | \ | ||
| 650 | MGA_ZMODE_NOZCMP | \ | ||
| 651 | MGA_ARZERO | \ | ||
| 652 | MGA_SGNZERO | \ | ||
| 653 | MGA_BOP_SRC | \ | ||
| 654 | (15 << MGA_TRANS_SHIFT)) | ||
| 655 | |||
| 656 | #define MGA_DWGCTL_CLEAR (MGA_OPCOD_TRAP | \ | ||
| 657 | MGA_ZMODE_NOZCMP | \ | ||
| 658 | MGA_SOLID | \ | ||
| 659 | MGA_ARZERO | \ | ||
| 660 | MGA_SGNZERO | \ | ||
| 661 | MGA_SHIFTZERO | \ | ||
| 662 | MGA_BOP_SRC | \ | ||
| 663 | (0 << MGA_TRANS_SHIFT) | \ | ||
| 664 | MGA_BLTMOD_BMONOLEF | \ | ||
| 665 | MGA_TRANSC | \ | ||
| 666 | MGA_CLIPDIS) | ||
| 667 | |||
| 668 | #define MGA_DWGCTL_COPY (MGA_OPCOD_BITBLT | \ | ||
| 669 | MGA_ATYPE_RPL | \ | ||
| 670 | MGA_SGNZERO | \ | ||
| 671 | MGA_SHIFTZERO | \ | ||
| 672 | MGA_BOP_SRC | \ | ||
| 673 | (0 << MGA_TRANS_SHIFT) | \ | ||
| 674 | MGA_BLTMOD_BFCOL | \ | ||
| 675 | MGA_CLIPDIS) | ||
| 676 | |||
| 677 | /* Simple idle test. | ||
| 678 | */ | ||
| 679 | static __inline__ int mga_is_idle(drm_mga_private_t *dev_priv) | ||
| 680 | { | ||
| 681 | u32 status = MGA_READ(MGA_STATUS) & MGA_ENGINE_IDLE_MASK; | ||
| 682 | return (status == MGA_ENDPRDMASTS); | ||
| 683 | } | ||
| 684 | |||
| 685 | #endif | ||
| @@ -1,197 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * \file mga_ioc32.c | ||
| 3 | * | ||
| 4 | * 32-bit ioctl compatibility routines for the MGA DRM. | ||
| 5 | * | ||
| 6 | * \author Dave Airlie <airlied@linux.ie> with code from patches by Egbert Eich | ||
| 7 | * | ||
| 8 | * | ||
| 9 | * Copyright (C) Paul Mackerras 2005 | ||
| 10 | * Copyright (C) Egbert Eich 2003,2004 | ||
| 11 | * Copyright (C) Dave Airlie 2005 | ||
| 12 | * All Rights Reserved. | ||
| 13 | * | ||
| 14 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
| 15 | * copy of this software and associated documentation files (the "Software"), | ||
| 16 | * to deal in the Software without restriction, including without limitation | ||
| 17 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
| 18 | * and/or sell copies of the Software, and to permit persons to whom the | ||
| 19 | * Software is furnished to do so, subject to the following conditions: | ||
| 20 | * | ||
| 21 | * The above copyright notice and this permission notice (including the next | ||
| 22 | * paragraph) shall be included in all copies or substantial portions of the | ||
| 23 | * Software. | ||
| 24 | * | ||
| 25 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 26 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 27 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
| 28 | * THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, | ||
| 29 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
| 30 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS | ||
| 31 | * IN THE SOFTWARE. | ||
| 32 | */ | ||
| 33 | |||
| 34 | #include <linux/compat.h> | ||
| 35 | |||
| 36 | #include "mga_drv.h" | ||
| 37 | |||
| 38 | typedef struct drm32_mga_init { | ||
| 39 | int func; | ||
| 40 | u32 sarea_priv_offset; | ||
| 41 | struct_group(always32bit, | ||
| 42 | int chipset; | ||
| 43 | int sgram; | ||
| 44 | unsigned int maccess; | ||
| 45 | unsigned int fb_cpp; | ||
| 46 | unsigned int front_offset, front_pitch; | ||
| 47 | unsigned int back_offset, back_pitch; | ||
| 48 | unsigned int depth_cpp; | ||
| 49 | unsigned int depth_offset, depth_pitch; | ||
| 50 | unsigned int texture_offset[MGA_NR_TEX_HEAPS]; | ||
| 51 | unsigned int texture_size[MGA_NR_TEX_HEAPS]; | ||
| 52 | ); | ||
| 53 | u32 fb_offset; | ||
| 54 | u32 mmio_offset; | ||
| 55 | u32 status_offset; | ||
| 56 | u32 warp_offset; | ||
| 57 | u32 primary_offset; | ||
| 58 | u32 buffers_offset; | ||
| 59 | } drm_mga_init32_t; | ||
| 60 | |||
| 61 | static int compat_mga_init(struct file *file, unsigned int cmd, | ||
| 62 | unsigned long arg) | ||
| 63 | { | ||
| 64 | drm_mga_init32_t init32; | ||
| 65 | drm_mga_init_t init; | ||
| 66 | |||
| 67 | if (copy_from_user(&init32, (void __user *)arg, sizeof(init32))) | ||
| 68 | return -EFAULT; | ||
| 69 | |||
| 70 | init.func = init32.func; | ||
| 71 | init.sarea_priv_offset = init32.sarea_priv_offset; | ||
| 72 | memcpy(&init.always32bit, &init32.always32bit, | ||
| 73 | sizeof(init32.always32bit)); | ||
| 74 | init.fb_offset = init32.fb_offset; | ||
| 75 | init.mmio_offset = init32.mmio_offset; | ||
| 76 | init.status_offset = init32.status_offset; | ||
| 77 | init.warp_offset = init32.warp_offset; | ||
| 78 | init.primary_offset = init32.primary_offset; | ||
| 79 | init.buffers_offset = init32.buffers_offset; | ||
| 80 | |||
| 81 | return drm_ioctl_kernel(file, mga_dma_init, &init, | ||
| 82 | DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY); | ||
| 83 | } | ||
| 84 | |||
| 85 | typedef struct drm_mga_getparam32 { | ||
| 86 | int param; | ||
| 87 | u32 value; | ||
| 88 | } drm_mga_getparam32_t; | ||
| 89 | |||
| 90 | static int compat_mga_getparam(struct file *file, unsigned int cmd, | ||
| 91 | unsigned long arg) | ||
| 92 | { | ||
| 93 | drm_mga_getparam32_t getparam32; | ||
| 94 | drm_mga_getparam_t getparam; | ||
| 95 | |||
| 96 | if (copy_from_user(&getparam32, (void __user *)arg, sizeof(getparam32))) | ||
| 97 | return -EFAULT; | ||
| 98 | |||
| 99 | getparam.param = getparam32.param; | ||
| 100 | getparam.value = compat_ptr(getparam32.value); | ||
| 101 | return drm_ioctl_kernel(file, mga_getparam, &getparam, DRM_AUTH); | ||
| 102 | } | ||
| 103 | |||
| 104 | typedef struct drm_mga_drm_bootstrap32 { | ||
| 105 | u32 texture_handle; | ||
| 106 | u32 texture_size; | ||
| 107 | u32 primary_size; | ||
| 108 | u32 secondary_bin_count; | ||
| 109 | u32 secondary_bin_size; | ||
| 110 | u32 agp_mode; | ||
| 111 | u8 agp_size; | ||
| 112 | } drm_mga_dma_bootstrap32_t; | ||
| 113 | |||
| 114 | static int compat_mga_dma_bootstrap(struct file *file, unsigned int cmd, | ||
| 115 | unsigned long arg) | ||
| 116 | { | ||
| 117 | drm_mga_dma_bootstrap32_t dma_bootstrap32; | ||
| 118 | drm_mga_dma_bootstrap_t dma_bootstrap; | ||
| 119 | int err; | ||
| 120 | |||
| 121 | if (copy_from_user(&dma_bootstrap32, (void __user *)arg, | ||
| 122 | sizeof(dma_bootstrap32))) | ||
| 123 | return -EFAULT; | ||
| 124 | |||
| 125 | dma_bootstrap.texture_handle = dma_bootstrap32.texture_handle; | ||
| 126 | dma_bootstrap.texture_size = dma_bootstrap32.texture_size; | ||
| 127 | dma_bootstrap.primary_size = dma_bootstrap32.primary_size; | ||
| 128 | dma_bootstrap.secondary_bin_count = dma_bootstrap32.secondary_bin_count; | ||
| 129 | dma_bootstrap.secondary_bin_size = dma_bootstrap32.secondary_bin_size; | ||
| 130 | dma_bootstrap.agp_mode = dma_bootstrap32.agp_mode; | ||
| 131 | dma_bootstrap.agp_size = dma_bootstrap32.agp_size; | ||
| 132 | |||
| 133 | err = drm_ioctl_kernel(file, mga_dma_bootstrap, &dma_bootstrap, | ||
| 134 | DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY); | ||
| 135 | if (err) | ||
| 136 | return err; | ||
| 137 | |||
| 138 | dma_bootstrap32.texture_handle = dma_bootstrap.texture_handle; | ||
| 139 | dma_bootstrap32.texture_size = dma_bootstrap.texture_size; | ||
| 140 | dma_bootstrap32.primary_size = dma_bootstrap.primary_size; | ||
| 141 | dma_bootstrap32.secondary_bin_count = dma_bootstrap.secondary_bin_count; | ||
| 142 | dma_bootstrap32.secondary_bin_size = dma_bootstrap.secondary_bin_size; | ||
| 143 | dma_bootstrap32.agp_mode = dma_bootstrap.agp_mode; | ||
| 144 | dma_bootstrap32.agp_size = dma_bootstrap.agp_size; | ||
| 145 | if (copy_to_user((void __user *)arg, &dma_bootstrap32, | ||
| 146 | sizeof(dma_bootstrap32))) | ||
| 147 | return -EFAULT; | ||
| 148 | |||
| 149 | return 0; | ||
| 150 | } | ||
| 151 | |||
| 152 | static struct { | ||
| 153 | drm_ioctl_compat_t *fn; | ||
| 154 | char *name; | ||
| 155 | } mga_compat_ioctls[] = { | ||
| 156 | #define DRM_IOCTL32_DEF(n, f)[DRM_##n] = {.fn = f, .name = #n} | ||
| 157 | DRM_IOCTL32_DEF(MGA_INIT, compat_mga_init), | ||
| 158 | DRM_IOCTL32_DEF(MGA_GETPARAM, compat_mga_getparam), | ||
| 159 | DRM_IOCTL32_DEF(MGA_DMA_BOOTSTRAP, compat_mga_dma_bootstrap), | ||
| 160 | }; | ||
| 161 | |||
| 162 | /** | ||
| 163 | * mga_compat_ioctl - Called whenever a 32-bit process running under | ||
| 164 | * a 64-bit kernel performs an ioctl on /dev/dri/card<n>. | ||
| 165 | * | ||
| 166 | * @filp: file pointer. | ||
| 167 | * @cmd: command. | ||
| 168 | * @arg: user argument. | ||
| 169 | * return: zero on success or negative number on failure. | ||
| 170 | */ | ||
| 171 | long mga_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) | ||
| 172 | { | ||
| 173 | unsigned int nr = DRM_IOCTL_NR(cmd); | ||
| 174 | struct drm_file *file_priv = filp->private_data; | ||
| 175 | drm_ioctl_compat_t *fn = NULL; | ||
| 176 | int ret; | ||
| 177 | |||
| 178 | if (nr < DRM_COMMAND_BASE) | ||
| 179 | return drm_compat_ioctl(filp, cmd, arg); | ||
| 180 | |||
| 181 | if (nr >= DRM_COMMAND_BASE + ARRAY_SIZE(mga_compat_ioctls)) | ||
| 182 | return drm_ioctl(filp, cmd, arg); | ||
| 183 | |||
| 184 | fn = mga_compat_ioctls[nr - DRM_COMMAND_BASE].fn; | ||
| 185 | if (!fn) | ||
| 186 | return drm_ioctl(filp, cmd, arg); | ||
| 187 | |||
| 188 | DRM_DEBUG("pid=%d, dev=0x%lx, auth=%d, %s\n", | ||
| 189 | task_pid_nr(current), | ||
| 190 | (long)old_encode_dev(file_priv->minor->kdev->devt), | ||
| 191 | file_priv->authenticated, | ||
| 192 | mga_compat_ioctls[nr - DRM_COMMAND_BASE].name); | ||
| 193 | ret = (*fn) (filp, cmd, arg); | ||
| 194 | if (ret) | ||
| 195 | DRM_DEBUG("ret = %d\n", ret); | ||
| 196 | return ret; | ||
| 197 | } | ||
| @@ -1,169 +0,0 @@ | |||
| 1 | /* mga_irq.c -- IRQ handling for radeon -*- linux-c -*- | ||
| 2 | */ | ||
| 3 | /* | ||
| 4 | * Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved. | ||
| 5 | * | ||
| 6 | * The Weather Channel (TM) funded Tungsten Graphics to develop the | ||
| 7 | * initial release of the Radeon 8500 driver under the XFree86 license. | ||
| 8 | * This notice must be preserved. | ||
| 9 | * | ||
| 10 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
| 11 | * copy of this software and associated documentation files (the "Software"), | ||
| 12 | * to deal in the Software without restriction, including without limitation | ||
| 13 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
| 14 | * and/or sell copies of the Software, and to permit persons to whom the | ||
| 15 | * Software is furnished to do so, subject to the following conditions: | ||
| 16 | * | ||
| 17 | * The above copyright notice and this permission notice (including the next | ||
| 18 | * paragraph) shall be included in all copies or substantial portions of the | ||
| 19 | * Software. | ||
| 20 | * | ||
| 21 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 22 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 23 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
| 24 | * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR | ||
| 25 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | ||
| 26 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | ||
| 27 | * DEALINGS IN THE SOFTWARE. | ||
| 28 | * | ||
| 29 | * Authors: | ||
| 30 | * Keith Whitwell <keith@tungstengraphics.com> | ||
| 31 | * Eric Anholt <anholt@FreeBSD.org> | ||
| 32 | */ | ||
| 33 | |||
| 34 | #include "mga_drv.h" | ||
| 35 | |||
| 36 | u32 mga_get_vblank_counter(struct drm_device *dev, unsigned int pipe) | ||
| 37 | { | ||
| 38 | const drm_mga_private_t *const dev_priv = | ||
| 39 | (drm_mga_private_t *) dev->dev_private; | ||
| 40 | |||
| 41 | if (pipe != 0) | ||
| 42 | return 0; | ||
| 43 | |||
| 44 | return atomic_read(&dev_priv->vbl_received); | ||
| 45 | } | ||
| 46 | |||
| 47 | |||
| 48 | irqreturn_t mga_driver_irq_handler(int irq, void *arg) | ||
| 49 | { | ||
| 50 | struct drm_device *dev = (struct drm_device *) arg; | ||
| 51 | drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private; | ||
| 52 | int status; | ||
| 53 | int handled = 0; | ||
| 54 | |||
| 55 | status = MGA_READ(MGA_STATUS); | ||
| 56 | |||
| 57 | /* VBLANK interrupt */ | ||
| 58 | if (status & MGA_VLINEPEN) { | ||
| 59 | MGA_WRITE(MGA_ICLEAR, MGA_VLINEICLR); | ||
| 60 | atomic_inc(&dev_priv->vbl_received); | ||
| 61 | drm_handle_vblank(dev, 0); | ||
| 62 | handled = 1; | ||
| 63 | } | ||
| 64 | |||
| 65 | /* SOFTRAP interrupt */ | ||
| 66 | if (status & MGA_SOFTRAPEN) { | ||
| 67 | const u32 prim_start = MGA_READ(MGA_PRIMADDRESS); | ||
| 68 | const u32 prim_end = MGA_READ(MGA_PRIMEND); | ||
| 69 | |||
| 70 | |||
| 71 | MGA_WRITE(MGA_ICLEAR, MGA_SOFTRAPICLR); | ||
| 72 | |||
| 73 | /* In addition to clearing the interrupt-pending bit, we | ||
| 74 | * have to write to MGA_PRIMEND to re-start the DMA operation. | ||
| 75 | */ | ||
| 76 | if ((prim_start & ~0x03) != (prim_end & ~0x03)) | ||
| 77 | MGA_WRITE(MGA_PRIMEND, prim_end); | ||
| 78 | |||
| 79 | atomic_inc(&dev_priv->last_fence_retired); | ||
| 80 | wake_up(&dev_priv->fence_queue); | ||
| 81 | handled = 1; | ||
| 82 | } | ||
| 83 | |||
| 84 | if (handled) | ||
| 85 | return IRQ_HANDLED; | ||
| 86 | return IRQ_NONE; | ||
| 87 | } | ||
| 88 | |||
| 89 | int mga_enable_vblank(struct drm_device *dev, unsigned int pipe) | ||
| 90 | { | ||
| 91 | drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private; | ||
| 92 | |||
| 93 | if (pipe != 0) { | ||
| 94 | DRM_ERROR("tried to enable vblank on non-existent crtc %u\n", | ||
| 95 | pipe); | ||
| 96 | return 0; | ||
| 97 | } | ||
| 98 | |||
| 99 | MGA_WRITE(MGA_IEN, MGA_VLINEIEN | MGA_SOFTRAPEN); | ||
| 100 | return 0; | ||
| 101 | } | ||
| 102 | |||
| 103 | |||
| 104 | void mga_disable_vblank(struct drm_device *dev, unsigned int pipe) | ||
| 105 | { | ||
| 106 | if (pipe != 0) { | ||
| 107 | DRM_ERROR("tried to disable vblank on non-existent crtc %u\n", | ||
| 108 | pipe); | ||
| 109 | } | ||
| 110 | |||
| 111 | /* Do *NOT* disable the vertical refresh interrupt. MGA doesn't have | ||
| 112 | * a nice hardware counter that tracks the number of refreshes when | ||
| 113 | * the interrupt is disabled, and the kernel doesn't know the refresh | ||
| 114 | * rate to calculate an estimate. | ||
| 115 | */ | ||
| 116 | /* MGA_WRITE(MGA_IEN, MGA_VLINEIEN | MGA_SOFTRAPEN); */ | ||
| 117 | } | ||
| 118 | |||
| 119 | void mga_driver_fence_wait(struct drm_device *dev, unsigned int *sequence) | ||
| 120 | { | ||
| 121 | drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private; | ||
| 122 | unsigned int cur_fence; | ||
| 123 | |||
| 124 | /* Assume that the user has missed the current sequence number | ||
| 125 | * by about a day rather than she wants to wait for years | ||
| 126 | * using fences. | ||
| 127 | */ | ||
| 128 | wait_event_timeout(dev_priv->fence_queue, | ||
| 129 | (((cur_fence = atomic_read(&dev_priv->last_fence_retired)) | ||
| 130 | - *sequence) <= (1 << 23)), | ||
| 131 | msecs_to_jiffies(3000)); | ||
| 132 | |||
| 133 | *sequence = cur_fence; | ||
| 134 | } | ||
| 135 | |||
| 136 | void mga_driver_irq_preinstall(struct drm_device *dev) | ||
| 137 | { | ||
| 138 | drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private; | ||
| 139 | |||
| 140 | /* Disable *all* interrupts */ | ||
| 141 | MGA_WRITE(MGA_IEN, 0); | ||
| 142 | /* Clear bits if they're already high */ | ||
| 143 | MGA_WRITE(MGA_ICLEAR, ~0); | ||
| 144 | } | ||
| 145 | |||
| 146 | int mga_driver_irq_postinstall(struct drm_device *dev) | ||
| 147 | { | ||
| 148 | drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private; | ||
| 149 | |||
| 150 | init_waitqueue_head(&dev_priv->fence_queue); | ||
| 151 | |||
| 152 | /* Turn on soft trap interrupt. Vertical blank interrupts are enabled | ||
| 153 | * in mga_enable_vblank. | ||
| 154 | */ | ||
| 155 | MGA_WRITE(MGA_IEN, MGA_SOFTRAPEN); | ||
| 156 | return 0; | ||
| 157 | } | ||
| 158 | |||
| 159 | void mga_driver_irq_uninstall(struct drm_device *dev) | ||
| 160 | { | ||
| 161 | drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private; | ||
| 162 | if (!dev_priv) | ||
| 163 | return; | ||
| 164 | |||
| 165 | /* Disable *all* interrupts */ | ||
| 166 | MGA_WRITE(MGA_IEN, 0); | ||
| 167 | |||
| 168 | dev->irq_enabled = false; | ||
| 169 | } | ||
| @@ -1,1099 +0,0 @@ | |||
| 1 | /* mga_state.c -- State support for MGA G200/G400 -*- linux-c -*- | ||
| 2 | * Created: Thu Jan 27 02:53:43 2000 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 | * VA LINUX SYSTEMS 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 | ||
| 25 | * OTHER DEALINGS IN THE SOFTWARE. | ||
| 26 | * | ||
| 27 | * Authors: | ||
| 28 | * Jeff Hartmann <jhartmann@valinux.com> | ||
| 29 | * Keith Whitwell <keith@tungstengraphics.com> | ||
| 30 | * | ||
| 31 | * Rewritten by: | ||
| 32 | * Gareth Hughes <gareth@valinux.com> | ||
| 33 | */ | ||
| 34 | |||
| 35 | #include "mga_drv.h" | ||
| 36 | |||
| 37 | /* ================================================================ | ||
| 38 | * DMA hardware state programming functions | ||
| 39 | */ | ||
| 40 | |||
| 41 | static void mga_emit_clip_rect(drm_mga_private_t *dev_priv, | ||
| 42 | struct drm_clip_rect *box) | ||
| 43 | { | ||
| 44 | drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; | ||
| 45 | drm_mga_context_regs_t *ctx = &sarea_priv->context_state; | ||
| 46 | unsigned int pitch = dev_priv->front_pitch; | ||
| 47 | DMA_LOCALS; | ||
| 48 | |||
| 49 | BEGIN_DMA(2); | ||
| 50 | |||
| 51 | /* Force reset of DWGCTL on G400 (eliminates clip disable bit). | ||
| 52 | */ | ||
| 53 | if (dev_priv->chipset >= MGA_CARD_TYPE_G400) { | ||
| 54 | DMA_BLOCK(MGA_DWGCTL, ctx->dwgctl, | ||
| 55 | MGA_LEN + MGA_EXEC, 0x80000000, | ||
| 56 | MGA_DWGCTL, ctx->dwgctl, | ||
| 57 | MGA_LEN + MGA_EXEC, 0x80000000); | ||
| 58 | } | ||
| 59 | DMA_BLOCK(MGA_DMAPAD, 0x00000000, | ||
| 60 | MGA_CXBNDRY, ((box->x2 - 1) << 16) | box->x1, | ||
| 61 | MGA_YTOP, box->y1 * pitch, MGA_YBOT, (box->y2 - 1) * pitch); | ||
| 62 | |||
| 63 | ADVANCE_DMA(); | ||
| 64 | } | ||
| 65 | |||
| 66 | static __inline__ void mga_g200_emit_context(drm_mga_private_t *dev_priv) | ||
| 67 | { | ||
| 68 | drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; | ||
| 69 | drm_mga_context_regs_t *ctx = &sarea_priv->context_state; | ||
| 70 | DMA_LOCALS; | ||
| 71 | |||
| 72 | BEGIN_DMA(3); | ||
| 73 | |||
| 74 | DMA_BLOCK(MGA_DSTORG, ctx->dstorg, | ||
| 75 | MGA_MACCESS, ctx->maccess, | ||
| 76 | MGA_PLNWT, ctx->plnwt, MGA_DWGCTL, ctx->dwgctl); | ||
| 77 | |||
| 78 | DMA_BLOCK(MGA_ALPHACTRL, ctx->alphactrl, | ||
| 79 | MGA_FOGCOL, ctx->fogcolor, | ||
| 80 | MGA_WFLAG, ctx->wflag, MGA_ZORG, dev_priv->depth_offset); | ||
| 81 | |||
| 82 | DMA_BLOCK(MGA_FCOL, ctx->fcol, | ||
| 83 | MGA_DMAPAD, 0x00000000, | ||
| 84 | MGA_DMAPAD, 0x00000000, MGA_DMAPAD, 0x00000000); | ||
| 85 | |||
| 86 | ADVANCE_DMA(); | ||
| 87 | } | ||
| 88 | |||
| 89 | static __inline__ void mga_g400_emit_context(drm_mga_private_t *dev_priv) | ||
| 90 | { | ||
| 91 | drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; | ||
| 92 | drm_mga_context_regs_t *ctx = &sarea_priv->context_state; | ||
| 93 | DMA_LOCALS; | ||
| 94 | |||
| 95 | BEGIN_DMA(4); | ||
| 96 | |||
| 97 | DMA_BLOCK(MGA_DSTORG, ctx->dstorg, | ||
| 98 | MGA_MACCESS, ctx->maccess, | ||
| 99 | MGA_PLNWT, ctx->plnwt, MGA_DWGCTL, ctx->dwgctl); | ||
| 100 | |||
| 101 | DMA_BLOCK(MGA_ALPHACTRL, ctx->alphactrl, | ||
| 102 | MGA_FOGCOL, ctx->fogcolor, | ||
| 103 | MGA_WFLAG, ctx->wflag, MGA_ZORG, dev_priv->depth_offset); | ||
| 104 | |||
| 105 | DMA_BLOCK(MGA_WFLAG1, ctx->wflag, | ||
| 106 | MGA_TDUALSTAGE0, ctx->tdualstage0, | ||
| 107 | MGA_TDUALSTAGE1, ctx->tdualstage1, MGA_FCOL, ctx->fcol); | ||
| 108 | |||
| 109 | DMA_BLOCK(MGA_STENCIL, ctx->stencil, | ||
| 110 | MGA_STENCILCTL, ctx->stencilctl, | ||
| 111 | MGA_DMAPAD, 0x00000000, MGA_DMAPAD, 0x00000000); | ||
| 112 | |||
| 113 | ADVANCE_DMA(); | ||
| 114 | } | ||
| 115 | |||
| 116 | static __inline__ void mga_g200_emit_tex0(drm_mga_private_t *dev_priv) | ||
| 117 | { | ||
| 118 | drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; | ||
| 119 | drm_mga_texture_regs_t *tex = &sarea_priv->tex_state[0]; | ||
| 120 | DMA_LOCALS; | ||
| 121 | |||
| 122 | BEGIN_DMA(4); | ||
| 123 | |||
| 124 | DMA_BLOCK(MGA_TEXCTL2, tex->texctl2, | ||
| 125 | MGA_TEXCTL, tex->texctl, | ||
| 126 | MGA_TEXFILTER, tex->texfilter, | ||
| 127 | MGA_TEXBORDERCOL, tex->texbordercol); | ||
| 128 | |||
| 129 | DMA_BLOCK(MGA_TEXORG, tex->texorg, | ||
| 130 | MGA_TEXORG1, tex->texorg1, | ||
| 131 | MGA_TEXORG2, tex->texorg2, MGA_TEXORG3, tex->texorg3); | ||
| 132 | |||
| 133 | DMA_BLOCK(MGA_TEXORG4, tex->texorg4, | ||
| 134 | MGA_TEXWIDTH, tex->texwidth, | ||
| 135 | MGA_TEXHEIGHT, tex->texheight, MGA_WR24, tex->texwidth); | ||
| 136 | |||
| 137 | DMA_BLOCK(MGA_WR34, tex->texheight, | ||
| 138 | MGA_TEXTRANS, 0x0000ffff, | ||
| 139 | MGA_TEXTRANSHIGH, 0x0000ffff, MGA_DMAPAD, 0x00000000); | ||
| 140 | |||
| 141 | ADVANCE_DMA(); | ||
| 142 | } | ||
| 143 | |||
| 144 | static __inline__ void mga_g400_emit_tex0(drm_mga_private_t *dev_priv) | ||
| 145 | { | ||
| 146 | drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; | ||
| 147 | drm_mga_texture_regs_t *tex = &sarea_priv->tex_state[0]; | ||
| 148 | DMA_LOCALS; | ||
| 149 | |||
| 150 | /* printk("mga_g400_emit_tex0 %x %x %x\n", tex->texorg, */ | ||
| 151 | /* tex->texctl, tex->texctl2); */ | ||
| 152 | |||
| 153 | BEGIN_DMA(6); | ||
| 154 | |||
| 155 | DMA_BLOCK(MGA_TEXCTL2, tex->texctl2 | MGA_G400_TC2_MAGIC, | ||
| 156 | MGA_TEXCTL, tex->texctl, | ||
| 157 | MGA_TEXFILTER, tex->texfilter, | ||
| 158 | MGA_TEXBORDERCOL, tex->texbordercol); | ||
| 159 | |||
| 160 | DMA_BLOCK(MGA_TEXORG, tex->texorg, | ||
| 161 | MGA_TEXORG1, tex->texorg1, | ||
| 162 | MGA_TEXORG2, tex->texorg2, MGA_TEXORG3, tex->texorg3); | ||
| 163 | |||
| 164 | DMA_BLOCK(MGA_TEXORG4, tex->texorg4, | ||
| 165 | MGA_TEXWIDTH, tex->texwidth, | ||
| 166 | MGA_TEXHEIGHT, tex->texheight, MGA_WR49, 0x00000000); | ||
| 167 | |||
| 168 | DMA_BLOCK(MGA_WR57, 0x00000000, | ||
| 169 | MGA_WR53, 0x00000000, | ||
| 170 | MGA_WR61, 0x00000000, MGA_WR52, MGA_G400_WR_MAGIC); | ||
| 171 | |||
| 172 | DMA_BLOCK(MGA_WR60, MGA_G400_WR_MAGIC, | ||
| 173 | MGA_WR54, tex->texwidth | MGA_G400_WR_MAGIC, | ||
| 174 | MGA_WR62, tex->texheight | MGA_G400_WR_MAGIC, | ||
| 175 | MGA_DMAPAD, 0x00000000); | ||
| 176 | |||
| 177 | DMA_BLOCK(MGA_DMAPAD, 0x00000000, | ||
| 178 | MGA_DMAPAD, 0x00000000, | ||
| 179 | MGA_TEXTRANS, 0x0000ffff, MGA_TEXTRANSHIGH, 0x0000ffff); | ||
| 180 | |||
| 181 | ADVANCE_DMA(); | ||
| 182 | } | ||
| 183 | |||
| 184 | static __inline__ void mga_g400_emit_tex1(drm_mga_private_t *dev_priv) | ||
| 185 | { | ||
| 186 | drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; | ||
| 187 | drm_mga_texture_regs_t *tex = &sarea_priv->tex_state[1]; | ||
| 188 | DMA_LOCALS; | ||
| 189 | |||
| 190 | /* printk("mga_g400_emit_tex1 %x %x %x\n", tex->texorg, */ | ||
| 191 | /* tex->texctl, tex->texctl2); */ | ||
| 192 | |||
| 193 | BEGIN_DMA(5); | ||
| 194 | |||
| 195 | DMA_BLOCK(MGA_TEXCTL2, (tex->texctl2 | | ||
| 196 | MGA_MAP1_ENABLE | | ||
| 197 | MGA_G400_TC2_MAGIC), | ||
| 198 | MGA_TEXCTL, tex->texctl, | ||
| 199 | MGA_TEXFILTER, tex->texfilter, | ||
| 200 | MGA_TEXBORDERCOL, tex->texbordercol); | ||
| 201 | |||
| 202 | DMA_BLOCK(MGA_TEXORG, tex->texorg, | ||
| 203 | MGA_TEXORG1, tex->texorg1, | ||
| 204 | MGA_TEXORG2, tex->texorg2, MGA_TEXORG3, tex->texorg3); | ||
| 205 | |||
| 206 | DMA_BLOCK(MGA_TEXORG4, tex->texorg4, | ||
| 207 | MGA_TEXWIDTH, tex->texwidth, | ||
| 208 | MGA_TEXHEIGHT, tex->texheight, MGA_WR49, 0x00000000); | ||
| 209 | |||
| 210 | DMA_BLOCK(MGA_WR57, 0x00000000, | ||
| 211 | MGA_WR53, 0x00000000, | ||
| 212 | MGA_WR61, 0x00000000, | ||
| 213 | MGA_WR52, tex->texwidth | MGA_G400_WR_MAGIC); | ||
| 214 | |||
| 215 | DMA_BLOCK(MGA_WR60, tex->texheight | MGA_G400_WR_MAGIC, | ||
| 216 | MGA_TEXTRANS, 0x0000ffff, | ||
| 217 | MGA_TEXTRANSHIGH, 0x0000ffff, | ||
| 218 | MGA_TEXCTL2, tex->texctl2 | MGA_G400_TC2_MAGIC); | ||
| 219 | |||
| 220 | ADVANCE_DMA(); | ||
| 221 | } | ||
| 222 | |||
| 223 | static __inline__ void mga_g200_emit_pipe(drm_mga_private_t *dev_priv) | ||
| 224 | { | ||
| 225 | drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; | ||
| 226 | unsigned int pipe = sarea_priv->warp_pipe; | ||
| 227 | DMA_LOCALS; | ||
| 228 | |||
| 229 | BEGIN_DMA(3); | ||
| 230 | |||
| 231 | DMA_BLOCK(MGA_WIADDR, MGA_WMODE_SUSPEND, | ||
| 232 | MGA_WVRTXSZ, 0x00000007, | ||
| 233 | MGA_WFLAG, 0x00000000, MGA_WR24, 0x00000000); | ||
| 234 | |||
| 235 | DMA_BLOCK(MGA_WR25, 0x00000100, | ||
| 236 | MGA_WR34, 0x00000000, | ||
| 237 | MGA_WR42, 0x0000ffff, MGA_WR60, 0x0000ffff); | ||
| 238 | |||
| 239 | /* Padding required due to hardware bug. | ||
| 240 | */ | ||
| 241 | DMA_BLOCK(MGA_DMAPAD, 0xffffffff, | ||
| 242 | MGA_DMAPAD, 0xffffffff, | ||
| 243 | MGA_DMAPAD, 0xffffffff, | ||
| 244 | MGA_WIADDR, (dev_priv->warp_pipe_phys[pipe] | | ||
| 245 | MGA_WMODE_START | dev_priv->wagp_enable)); | ||
| 246 | |||
| 247 | ADVANCE_DMA(); | ||
| 248 | } | ||
| 249 | |||
| 250 | static __inline__ void mga_g400_emit_pipe(drm_mga_private_t *dev_priv) | ||
| 251 | { | ||
| 252 | drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; | ||
| 253 | unsigned int pipe = sarea_priv->warp_pipe; | ||
| 254 | DMA_LOCALS; | ||
| 255 | |||
| 256 | /* printk("mga_g400_emit_pipe %x\n", pipe); */ | ||
| 257 | |||
| 258 | BEGIN_DMA(10); | ||
| 259 | |||
| 260 | DMA_BLOCK(MGA_WIADDR2, MGA_WMODE_SUSPEND, | ||
| 261 | MGA_DMAPAD, 0x00000000, | ||
| 262 | MGA_DMAPAD, 0x00000000, MGA_DMAPAD, 0x00000000); | ||
| 263 | |||
| 264 | if (pipe & MGA_T2) { | ||
| 265 | DMA_BLOCK(MGA_WVRTXSZ, 0x00001e09, | ||
| 266 | MGA_DMAPAD, 0x00000000, | ||
| 267 | MGA_DMAPAD, 0x00000000, MGA_DMAPAD, 0x00000000); | ||
| 268 | |||
| 269 | DMA_BLOCK(MGA_WACCEPTSEQ, 0x00000000, | ||
| 270 | MGA_WACCEPTSEQ, 0x00000000, | ||
| 271 | MGA_WACCEPTSEQ, 0x00000000, | ||
| 272 | MGA_WACCEPTSEQ, 0x1e000000); | ||
| 273 | } else { | ||
| 274 | if (dev_priv->warp_pipe & MGA_T2) { | ||
| 275 | /* Flush the WARP pipe */ | ||
| 276 | DMA_BLOCK(MGA_YDST, 0x00000000, | ||
| 277 | MGA_FXLEFT, 0x00000000, | ||
| 278 | MGA_FXRIGHT, 0x00000001, | ||
| 279 | MGA_DWGCTL, MGA_DWGCTL_FLUSH); | ||
| 280 | |||
| 281 | DMA_BLOCK(MGA_LEN + MGA_EXEC, 0x00000001, | ||
| 282 | MGA_DWGSYNC, 0x00007000, | ||
| 283 | MGA_TEXCTL2, MGA_G400_TC2_MAGIC, | ||
| 284 | MGA_LEN + MGA_EXEC, 0x00000000); | ||
| 285 | |||
| 286 | DMA_BLOCK(MGA_TEXCTL2, (MGA_DUALTEX | | ||
| 287 | MGA_G400_TC2_MAGIC), | ||
| 288 | MGA_LEN + MGA_EXEC, 0x00000000, | ||
| 289 | MGA_TEXCTL2, MGA_G400_TC2_MAGIC, | ||
| 290 | MGA_DMAPAD, 0x00000000); | ||
| 291 | } | ||
| 292 | |||
| 293 | DMA_BLOCK(MGA_WVRTXSZ, 0x00001807, | ||
| 294 | MGA_DMAPAD, 0x00000000, | ||
| 295 | MGA_DMAPAD, 0x00000000, MGA_DMAPAD, 0x00000000); | ||
| 296 | |||
| 297 | DMA_BLOCK(MGA_WACCEPTSEQ, 0x00000000, | ||
| 298 | MGA_WACCEPTSEQ, 0x00000000, | ||
| 299 | MGA_WACCEPTSEQ, 0x00000000, | ||
| 300 | MGA_WACCEPTSEQ, 0x18000000); | ||
| 301 | } | ||
| 302 | |||
| 303 | DMA_BLOCK(MGA_WFLAG, 0x00000000, | ||
| 304 | MGA_WFLAG1, 0x00000000, | ||
| 305 | MGA_WR56, MGA_G400_WR56_MAGIC, MGA_DMAPAD, 0x00000000); | ||
| 306 | |||
| 307 | DMA_BLOCK(MGA_WR49, 0x00000000, /* tex0 */ | ||
| 308 | MGA_WR57, 0x00000000, /* tex0 */ | ||
| 309 | MGA_WR53, 0x00000000, /* tex1 */ | ||
| 310 | MGA_WR61, 0x00000000); /* tex1 */ | ||
| 311 | |||
| 312 | DMA_BLOCK(MGA_WR54, MGA_G400_WR_MAGIC, /* tex0 width */ | ||
| 313 | MGA_WR62, MGA_G400_WR_MAGIC, /* tex0 height */ | ||
| 314 | MGA_WR52, MGA_G400_WR_MAGIC, /* tex1 width */ | ||
| 315 | MGA_WR60, MGA_G400_WR_MAGIC); /* tex1 height */ | ||
| 316 | |||
| 317 | /* Padding required due to hardware bug */ | ||
| 318 | DMA_BLOCK(MGA_DMAPAD, 0xffffffff, | ||
| 319 | MGA_DMAPAD, 0xffffffff, | ||
| 320 | MGA_DMAPAD, 0xffffffff, | ||
| 321 | MGA_WIADDR2, (dev_priv->warp_pipe_phys[pipe] | | ||
| 322 | MGA_WMODE_START | dev_priv->wagp_enable)); | ||
| 323 | |||
| 324 | ADVANCE_DMA(); | ||
| 325 | } | ||
| 326 | |||
| 327 | static void mga_g200_emit_state(drm_mga_private_t *dev_priv) | ||
| 328 | { | ||
| 329 | drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; | ||
| 330 | unsigned int dirty = sarea_priv->dirty; | ||
| 331 | |||
| 332 | if (sarea_priv->warp_pipe != dev_priv->warp_pipe) { | ||
| 333 | mga_g200_emit_pipe(dev_priv); | ||
| 334 | dev_priv->warp_pipe = sarea_priv->warp_pipe; | ||
| 335 | } | ||
| 336 | |||
| 337 | if (dirty & MGA_UPLOAD_CONTEXT) { | ||
| 338 | mga_g200_emit_context(dev_priv); | ||
| 339 | sarea_priv->dirty &= ~MGA_UPLOAD_CONTEXT; | ||
| 340 | } | ||
| 341 | |||
| 342 | if (dirty & MGA_UPLOAD_TEX0) { | ||
| 343 | mga_g200_emit_tex0(dev_priv); | ||
| 344 | sarea_priv->dirty &= ~MGA_UPLOAD_TEX0; | ||
| 345 | } | ||
| 346 | } | ||
| 347 | |||
| 348 | static void mga_g400_emit_state(drm_mga_private_t *dev_priv) | ||
| 349 | { | ||
| 350 | drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; | ||
| 351 | unsigned int dirty = sarea_priv->dirty; | ||
| 352 | int multitex = sarea_priv->warp_pipe & MGA_T2; | ||
| 353 | |||
| 354 | if (sarea_priv->warp_pipe != dev_priv->warp_pipe) { | ||
| 355 | mga_g400_emit_pipe(dev_priv); | ||
| 356 | dev_priv->warp_pipe = sarea_priv->warp_pipe; | ||
| 357 | } | ||
| 358 | |||
| 359 | if (dirty & MGA_UPLOAD_CONTEXT) { | ||
| 360 | mga_g400_emit_context(dev_priv); | ||
| 361 | sarea_priv->dirty &= ~MGA_UPLOAD_CONTEXT; | ||
| 362 | } | ||
| 363 | |||
| 364 | if (dirty & MGA_UPLOAD_TEX0) { | ||
| 365 | mga_g400_emit_tex0(dev_priv); | ||
| 366 | sarea_priv->dirty &= ~MGA_UPLOAD_TEX0; | ||
| 367 | } | ||
| 368 | |||
| 369 | if ((dirty & MGA_UPLOAD_TEX1) && multitex) { | ||
| 370 | mga_g400_emit_tex1(dev_priv); | ||
| 371 | sarea_priv->dirty &= ~MGA_UPLOAD_TEX1; | ||
| 372 | } | ||
| 373 | } | ||
| 374 | |||
| 375 | /* ================================================================ | ||
| 376 | * SAREA state verification | ||
| 377 | */ | ||
| 378 | |||
| 379 | /* Disallow all write destinations except the front and backbuffer. | ||
| 380 | */ | ||
| 381 | static int mga_verify_context(drm_mga_private_t *dev_priv) | ||
| 382 | { | ||
| 383 | drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; | ||
| 384 | drm_mga_context_regs_t *ctx = &sarea_priv->context_state; | ||
| 385 | |||
| 386 | if (ctx->dstorg != dev_priv->front_offset && | ||
| 387 | ctx->dstorg != dev_priv->back_offset) { | ||
| 388 | DRM_ERROR("*** bad DSTORG: %x (front %x, back %x)\n\n", | ||
| 389 | ctx->dstorg, dev_priv->front_offset, | ||
| 390 | dev_priv->back_offset); | ||
| 391 | ctx->dstorg = 0; | ||
| 392 | return -EINVAL; | ||
| 393 | } | ||
| 394 | |||
| 395 | return 0; | ||
| 396 | } | ||
| 397 | |||
| 398 | /* Disallow texture reads from PCI space. | ||
| 399 | */ | ||
| 400 | static int mga_verify_tex(drm_mga_private_t *dev_priv, int unit) | ||
| 401 | { | ||
| 402 | drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; | ||
| 403 | drm_mga_texture_regs_t *tex = &sarea_priv->tex_state[unit]; | ||
| 404 | unsigned int org; | ||
| 405 | |||
| 406 | org = tex->texorg & (MGA_TEXORGMAP_MASK | MGA_TEXORGACC_MASK); | ||
| 407 | |||
| 408 | if (org == (MGA_TEXORGMAP_SYSMEM | MGA_TEXORGACC_PCI)) { | ||
| 409 | DRM_ERROR("*** bad TEXORG: 0x%x, unit %d\n", tex->texorg, unit); | ||
| 410 | tex->texorg = 0; | ||
| 411 | return -EINVAL; | ||
| 412 | } | ||
| 413 | |||
| 414 | return 0; | ||
| 415 | } | ||
| 416 | |||
| 417 | static int mga_verify_state(drm_mga_private_t *dev_priv) | ||
| 418 | { | ||
| 419 | drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; | ||
| 420 | unsigned int dirty = sarea_priv->dirty; | ||
| 421 | int ret = 0; | ||
| 422 | |||
| 423 | if (sarea_priv->nbox > MGA_NR_SAREA_CLIPRECTS) | ||
| 424 | sarea_priv->nbox = MGA_NR_SAREA_CLIPRECTS; | ||
| 425 | |||
| 426 | if (dirty & MGA_UPLOAD_CONTEXT) | ||
| 427 | ret |= mga_verify_context(dev_priv); | ||
| 428 | |||
| 429 | if (dirty & MGA_UPLOAD_TEX0) | ||
| 430 | ret |= mga_verify_tex(dev_priv, 0); | ||
| 431 | |||
| 432 | if (dev_priv->chipset >= MGA_CARD_TYPE_G400) { | ||
| 433 | if (dirty & MGA_UPLOAD_TEX1) | ||
| 434 | ret |= mga_verify_tex(dev_priv, 1); | ||
| 435 | |||
| 436 | if (dirty & MGA_UPLOAD_PIPE) | ||
| 437 | ret |= (sarea_priv->warp_pipe > MGA_MAX_G400_PIPES); | ||
| 438 | } else { | ||
| 439 | if (dirty & MGA_UPLOAD_PIPE) | ||
| 440 | ret |= (sarea_priv->warp_pipe > MGA_MAX_G200_PIPES); | ||
| 441 | } | ||
| 442 | |||
| 443 | return (ret == 0); | ||
| 444 | } | ||
| 445 | |||
| 446 | static int mga_verify_iload(drm_mga_private_t *dev_priv, | ||
| 447 | unsigned int dstorg, unsigned int length) | ||
| 448 | { | ||
| 449 | if (dstorg < dev_priv->texture_offset || | ||
| 450 | dstorg + length > (dev_priv->texture_offset + | ||
| 451 | dev_priv->texture_size)) { | ||
| 452 | DRM_ERROR("*** bad iload DSTORG: 0x%x\n", dstorg); | ||
| 453 | return -EINVAL; | ||
| 454 | } | ||
| 455 | |||
| 456 | if (length & MGA_ILOAD_MASK) { | ||
| 457 | DRM_ERROR("*** bad iload length: 0x%x\n", | ||
| 458 | length & MGA_ILOAD_MASK); | ||
| 459 | return -EINVAL; | ||
| 460 | } | ||
| 461 | |||
| 462 | return 0; | ||
| 463 | } | ||
| 464 | |||
| 465 | static int mga_verify_blit(drm_mga_private_t *dev_priv, | ||
| 466 | unsigned int srcorg, unsigned int dstorg) | ||
| 467 | { | ||
| 468 | if ((srcorg & 0x3) == (MGA_SRCACC_PCI | MGA_SRCMAP_SYSMEM) || | ||
| 469 | (dstorg & 0x3) == (MGA_SRCACC_PCI | MGA_SRCMAP_SYSMEM)) { | ||
| 470 | DRM_ERROR("*** bad blit: src=0x%x dst=0x%x\n", srcorg, dstorg); | ||
| 471 | return -EINVAL; | ||
| 472 | } | ||
| 473 | return 0; | ||
| 474 | } | ||
| 475 | |||
| 476 | /* ================================================================ | ||
| 477 | * | ||
| 478 | */ | ||
| 479 | |||
| 480 | static void mga_dma_dispatch_clear(struct drm_device *dev, drm_mga_clear_t *clear) | ||
| 481 | { | ||
| 482 | drm_mga_private_t *dev_priv = dev->dev_private; | ||
| 483 | drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; | ||
| 484 | drm_mga_context_regs_t *ctx = &sarea_priv->context_state; | ||
| 485 | struct drm_clip_rect *pbox = sarea_priv->boxes; | ||
| 486 | int nbox = sarea_priv->nbox; | ||
| 487 | int i; | ||
| 488 | DMA_LOCALS; | ||
| 489 | DRM_DEBUG("\n"); | ||
| 490 | |||
| 491 | BEGIN_DMA(1); | ||
| 492 | |||
| 493 | DMA_BLOCK(MGA_DMAPAD, 0x00000000, | ||
| 494 | MGA_DMAPAD, 0x00000000, | ||
| 495 | MGA_DWGSYNC, 0x00007100, MGA_DWGSYNC, 0x00007000); | ||
| 496 | |||
| 497 | ADVANCE_DMA(); | ||
| 498 | |||
| 499 | for (i = 0; i < nbox; i++) { | ||
| 500 | struct drm_clip_rect *box = &pbox[i]; | ||
| 501 | u32 height = box->y2 - box->y1; | ||
| 502 | |||
| 503 | DRM_DEBUG(" from=%d,%d to=%d,%d\n", | ||
| 504 | box->x1, box->y1, box->x2, box->y2); | ||
| 505 | |||
| 506 | if (clear->flags & MGA_FRONT) { | ||
| 507 | BEGIN_DMA(2); | ||
| 508 | |||
| 509 | DMA_BLOCK(MGA_DMAPAD, 0x00000000, | ||
| 510 | MGA_PLNWT, clear->color_mask, | ||
| 511 | MGA_YDSTLEN, (box->y1 << 16) | height, | ||
| 512 | MGA_FXBNDRY, (box->x2 << 16) | box->x1); | ||
| 513 | |||
| 514 | DMA_BLOCK(MGA_DMAPAD, 0x00000000, | ||
| 515 | MGA_FCOL, clear->clear_color, | ||
| 516 | MGA_DSTORG, dev_priv->front_offset, | ||
| 517 | MGA_DWGCTL + MGA_EXEC, dev_priv->clear_cmd); | ||
| 518 | |||
| 519 | ADVANCE_DMA(); | ||
| 520 | } | ||
| 521 | |||
| 522 | if (clear->flags & MGA_BACK) { | ||
| 523 | BEGIN_DMA(2); | ||
| 524 | |||
| 525 | DMA_BLOCK(MGA_DMAPAD, 0x00000000, | ||
| 526 | MGA_PLNWT, clear->color_mask, | ||
| 527 | MGA_YDSTLEN, (box->y1 << 16) | height, | ||
| 528 | MGA_FXBNDRY, (box->x2 << 16) | box->x1); | ||
| 529 | |||
| 530 | DMA_BLOCK(MGA_DMAPAD, 0x00000000, | ||
| 531 | MGA_FCOL, clear->clear_color, | ||
| 532 | MGA_DSTORG, dev_priv->back_offset, | ||
| 533 | MGA_DWGCTL + MGA_EXEC, dev_priv->clear_cmd); | ||
| 534 | |||
| 535 | ADVANCE_DMA(); | ||
| 536 | } | ||
| 537 | |||
| 538 | if (clear->flags & MGA_DEPTH) { | ||
| 539 | BEGIN_DMA(2); | ||
| 540 | |||
| 541 | DMA_BLOCK(MGA_DMAPAD, 0x00000000, | ||
| 542 | MGA_PLNWT, clear->depth_mask, | ||
| 543 | MGA_YDSTLEN, (box->y1 << 16) | height, | ||
| 544 | MGA_FXBNDRY, (box->x2 << 16) | box->x1); | ||
| 545 | |||
| 546 | DMA_BLOCK(MGA_DMAPAD, 0x00000000, | ||
| 547 | MGA_FCOL, clear->clear_depth, | ||
| 548 | MGA_DSTORG, dev_priv->depth_offset, | ||
| 549 | MGA_DWGCTL + MGA_EXEC, dev_priv->clear_cmd); | ||
| 550 | |||
| 551 | ADVANCE_DMA(); | ||
| 552 | } | ||
| 553 | |||
| 554 | } | ||
| 555 | |||
| 556 | BEGIN_DMA(1); | ||
| 557 | |||
| 558 | /* Force reset of DWGCTL */ | ||
| 559 | DMA_BLOCK(MGA_DMAPAD, 0x00000000, | ||
| 560 | MGA_DMAPAD, 0x00000000, | ||
| 561 | MGA_PLNWT, ctx->plnwt, MGA_DWGCTL, ctx->dwgctl); | ||
| 562 | |||
| 563 | ADVANCE_DMA(); | ||
| 564 | |||
| 565 | FLUSH_DMA(); | ||
| 566 | } | ||
| 567 | |||
| 568 | static void mga_dma_dispatch_swap(struct drm_device *dev) | ||
| 569 | { | ||
| 570 | drm_mga_private_t *dev_priv = dev->dev_private; | ||
| 571 | drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; | ||
| 572 | drm_mga_context_regs_t *ctx = &sarea_priv->context_state; | ||
| 573 | struct drm_clip_rect *pbox = sarea_priv->boxes; | ||
| 574 | int nbox = sarea_priv->nbox; | ||
| 575 | int i; | ||
| 576 | DMA_LOCALS; | ||
| 577 | DRM_DEBUG("\n"); | ||
| 578 | |||
| 579 | sarea_priv->last_frame.head = dev_priv->prim.tail; | ||
| 580 | sarea_priv->last_frame.wrap = dev_priv->prim.last_wrap; | ||
| 581 | |||
| 582 | BEGIN_DMA(4 + nbox); | ||
| 583 | |||
| 584 | DMA_BLOCK(MGA_DMAPAD, 0x00000000, | ||
| 585 | MGA_DMAPAD, 0x00000000, | ||
| 586 | MGA_DWGSYNC, 0x00007100, MGA_DWGSYNC, 0x00007000); | ||
| 587 | |||
| 588 | DMA_BLOCK(MGA_DSTORG, dev_priv->front_offset, | ||
| 589 | MGA_MACCESS, dev_priv->maccess, | ||
| 590 | MGA_SRCORG, dev_priv->back_offset, | ||
| 591 | MGA_AR5, dev_priv->front_pitch); | ||
| 592 | |||
| 593 | DMA_BLOCK(MGA_DMAPAD, 0x00000000, | ||
| 594 | MGA_DMAPAD, 0x00000000, | ||
| 595 | MGA_PLNWT, 0xffffffff, MGA_DWGCTL, MGA_DWGCTL_COPY); | ||
| 596 | |||
| 597 | for (i = 0; i < nbox; i++) { | ||
| 598 | struct drm_clip_rect *box = &pbox[i]; | ||
| 599 | u32 height = box->y2 - box->y1; | ||
| 600 | u32 start = box->y1 * dev_priv->front_pitch; | ||
| 601 | |||
| 602 | DRM_DEBUG(" from=%d,%d to=%d,%d\n", | ||
| 603 | box->x1, box->y1, box->x2, box->y2); | ||
| 604 | |||
| 605 | DMA_BLOCK(MGA_AR0, start + box->x2 - 1, | ||
| 606 | MGA_AR3, start + box->x1, | ||
| 607 | MGA_FXBNDRY, ((box->x2 - 1) << 16) | box->x1, | ||
| 608 | MGA_YDSTLEN + MGA_EXEC, (box->y1 << 16) | height); | ||
| 609 | } | ||
| 610 | |||
| 611 | DMA_BLOCK(MGA_DMAPAD, 0x00000000, | ||
| 612 | MGA_PLNWT, ctx->plnwt, | ||
| 613 | MGA_SRCORG, dev_priv->front_offset, MGA_DWGCTL, ctx->dwgctl); | ||
| 614 | |||
| 615 | ADVANCE_DMA(); | ||
| 616 | |||
| 617 | FLUSH_DMA(); | ||
| 618 | |||
| 619 | DRM_DEBUG("... done.\n"); | ||
| 620 | } | ||
| 621 | |||
| 622 | static void mga_dma_dispatch_vertex(struct drm_device *dev, struct drm_buf *buf) | ||
| 623 | { | ||
| 624 | drm_mga_private_t *dev_priv = dev->dev_private; | ||
| 625 | drm_mga_buf_priv_t *buf_priv = buf->dev_private; | ||
| 626 | drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; | ||
| 627 | u32 address = (u32) buf->bus_address; | ||
| 628 | u32 length = (u32) buf->used; | ||
| 629 | int i = 0; | ||
| 630 | DMA_LOCALS; | ||
| 631 | DRM_DEBUG("buf=%d used=%d\n", buf->idx, buf->used); | ||
| 632 | |||
| 633 | if (buf->used) { | ||
| 634 | buf_priv->dispatched = 1; | ||
| 635 | |||
| 636 | MGA_EMIT_STATE(dev_priv, sarea_priv->dirty); | ||
| 637 | |||
| 638 | do { | ||
| 639 | if (i < sarea_priv->nbox) { | ||
| 640 | mga_emit_clip_rect(dev_priv, | ||
| 641 | &sarea_priv->boxes[i]); | ||
| 642 | } | ||
| 643 | |||
| 644 | BEGIN_DMA(1); | ||
| 645 | |||
| 646 | DMA_BLOCK(MGA_DMAPAD, 0x00000000, | ||
| 647 | MGA_DMAPAD, 0x00000000, | ||
| 648 | MGA_SECADDRESS, (address | | ||
| 649 | MGA_DMA_VERTEX), | ||
| 650 | MGA_SECEND, ((address + length) | | ||
| 651 | dev_priv->dma_access)); | ||
| 652 | |||
| 653 | ADVANCE_DMA(); | ||
| 654 | } while (++i < sarea_priv->nbox); | ||
| 655 | } | ||
| 656 | |||
| 657 | if (buf_priv->discard) { | ||
| 658 | AGE_BUFFER(buf_priv); | ||
| 659 | buf->pending = 0; | ||
| 660 | buf->used = 0; | ||
| 661 | buf_priv->dispatched = 0; | ||
| 662 | |||
| 663 | mga_freelist_put(dev, buf); | ||
| 664 | } | ||
| 665 | |||
| 666 | FLUSH_DMA(); | ||
| 667 | } | ||
| 668 | |||
| 669 | static void mga_dma_dispatch_indices(struct drm_device *dev, struct drm_buf *buf, | ||
| 670 | unsigned int start, unsigned int end) | ||
| 671 | { | ||
| 672 | drm_mga_private_t *dev_priv = dev->dev_private; | ||
| 673 | drm_mga_buf_priv_t *buf_priv = buf->dev_private; | ||
| 674 | drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; | ||
| 675 | u32 address = (u32) buf->bus_address; | ||
| 676 | int i = 0; | ||
| 677 | DMA_LOCALS; | ||
| 678 | DRM_DEBUG("buf=%d start=%d end=%d\n", buf->idx, start, end); | ||
| 679 | |||
| 680 | if (start != end) { | ||
| 681 | buf_priv->dispatched = 1; | ||
| 682 | |||
| 683 | MGA_EMIT_STATE(dev_priv, sarea_priv->dirty); | ||
| 684 | |||
| 685 | do { | ||
| 686 | if (i < sarea_priv->nbox) { | ||
| 687 | mga_emit_clip_rect(dev_priv, | ||
| 688 | &sarea_priv->boxes[i]); | ||
| 689 | } | ||
| 690 | |||
| 691 | BEGIN_DMA(1); | ||
| 692 | |||
| 693 | DMA_BLOCK(MGA_DMAPAD, 0x00000000, | ||
| 694 | MGA_DMAPAD, 0x00000000, | ||
| 695 | MGA_SETUPADDRESS, address + start, | ||
| 696 | MGA_SETUPEND, ((address + end) | | ||
| 697 | dev_priv->dma_access)); | ||
| 698 | |||
| 699 | ADVANCE_DMA(); | ||
| 700 | } while (++i < sarea_priv->nbox); | ||
| 701 | } | ||
| 702 | |||
| 703 | if (buf_priv->discard) { | ||
| 704 | AGE_BUFFER(buf_priv); | ||
| 705 | buf->pending = 0; | ||
| 706 | buf->used = 0; | ||
| 707 | buf_priv->dispatched = 0; | ||
| 708 | |||
| 709 | mga_freelist_put(dev, buf); | ||
| 710 | } | ||
| 711 | |||
| 712 | FLUSH_DMA(); | ||
| 713 | } | ||
| 714 | |||
| 715 | /* This copies a 64 byte aligned agp region to the frambuffer with a | ||
| 716 | * standard blit, the ioctl needs to do checking. | ||
| 717 | */ | ||
| 718 | static void mga_dma_dispatch_iload(struct drm_device *dev, struct drm_buf *buf, | ||
| 719 | unsigned int dstorg, unsigned int length) | ||
| 720 | { | ||
| 721 | drm_mga_private_t *dev_priv = dev->dev_private; | ||
| 722 | drm_mga_buf_priv_t *buf_priv = buf->dev_private; | ||
| 723 | drm_mga_context_regs_t *ctx = &dev_priv->sarea_priv->context_state; | ||
| 724 | u32 srcorg = | ||
| 725 | buf->bus_address | dev_priv->dma_access | MGA_SRCMAP_SYSMEM; | ||
| 726 | u32 y2; | ||
| 727 | DMA_LOCALS; | ||
| 728 | DRM_DEBUG("buf=%d used=%d\n", buf->idx, buf->used); | ||
| 729 | |||
| 730 | y2 = length / 64; | ||
| 731 | |||
| 732 | BEGIN_DMA(5); | ||
| 733 | |||
| 734 | DMA_BLOCK(MGA_DMAPAD, 0x00000000, | ||
| 735 | MGA_DMAPAD, 0x00000000, | ||
| 736 | MGA_DWGSYNC, 0x00007100, MGA_DWGSYNC, 0x00007000); | ||
| 737 | |||
| 738 | DMA_BLOCK(MGA_DSTORG, dstorg, | ||
| 739 | MGA_MACCESS, 0x00000000, MGA_SRCORG, srcorg, MGA_AR5, 64); | ||
| 740 | |||
| 741 | DMA_BLOCK(MGA_PITCH, 64, | ||
| 742 | MGA_PLNWT, 0xffffffff, | ||
| 743 | MGA_DMAPAD, 0x00000000, MGA_DWGCTL, MGA_DWGCTL_COPY); | ||
| 744 | |||
| 745 | DMA_BLOCK(MGA_AR0, 63, | ||
| 746 | MGA_AR3, 0, | ||
| 747 | MGA_FXBNDRY, (63 << 16) | 0, MGA_YDSTLEN + MGA_EXEC, y2); | ||
| 748 | |||
| 749 | DMA_BLOCK(MGA_PLNWT, ctx->plnwt, | ||
| 750 | MGA_SRCORG, dev_priv->front_offset, | ||
| 751 | MGA_PITCH, dev_priv->front_pitch, MGA_DWGSYNC, 0x00007000); | ||
| 752 | |||
| 753 | ADVANCE_DMA(); | ||
| 754 | |||
| 755 | AGE_BUFFER(buf_priv); | ||
| 756 | |||
| 757 | buf->pending = 0; | ||
| 758 | buf->used = 0; | ||
| 759 | buf_priv->dispatched = 0; | ||
| 760 | |||
| 761 | mga_freelist_put(dev, buf); | ||
| 762 | |||
| 763 | FLUSH_DMA(); | ||
| 764 | } | ||
| 765 | |||
| 766 | static void mga_dma_dispatch_blit(struct drm_device *dev, drm_mga_blit_t *blit) | ||
| 767 | { | ||
| 768 | drm_mga_private_t *dev_priv = dev->dev_private; | ||
| 769 | drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; | ||
| 770 | drm_mga_context_regs_t *ctx = &sarea_priv->context_state; | ||
| 771 | struct drm_clip_rect *pbox = sarea_priv->boxes; | ||
| 772 | int nbox = sarea_priv->nbox; | ||
| 773 | u32 scandir = 0, i; | ||
| 774 | DMA_LOCALS; | ||
| 775 | DRM_DEBUG("\n"); | ||
| 776 | |||
| 777 | BEGIN_DMA(4 + nbox); | ||
| 778 | |||
| 779 | DMA_BLOCK(MGA_DMAPAD, 0x00000000, | ||
| 780 | MGA_DMAPAD, 0x00000000, | ||
| 781 | MGA_DWGSYNC, 0x00007100, MGA_DWGSYNC, 0x00007000); | ||
| 782 | |||
| 783 | DMA_BLOCK(MGA_DWGCTL, MGA_DWGCTL_COPY, | ||
| 784 | MGA_PLNWT, blit->planemask, | ||
| 785 | MGA_SRCORG, blit->srcorg, MGA_DSTORG, blit->dstorg); | ||
| 786 | |||
| 787 | DMA_BLOCK(MGA_SGN, scandir, | ||
| 788 | MGA_MACCESS, dev_priv->maccess, | ||
| 789 | MGA_AR5, blit->ydir * blit->src_pitch, | ||
| 790 | MGA_PITCH, blit->dst_pitch); | ||
| 791 | |||
| 792 | for (i = 0; i < nbox; i++) { | ||
| 793 | int srcx = pbox[i].x1 + blit->delta_sx; | ||
| 794 | int srcy = pbox[i].y1 + blit->delta_sy; | ||
| 795 | int dstx = pbox[i].x1 + blit->delta_dx; | ||
| 796 | int dsty = pbox[i].y1 + blit->delta_dy; | ||
| 797 | int h = pbox[i].y2 - pbox[i].y1; | ||
| 798 | int w = pbox[i].x2 - pbox[i].x1 - 1; | ||
| 799 | int start; | ||
| 800 | |||
| 801 | if (blit->ydir == -1) | ||
| 802 | srcy = blit->height - srcy - 1; | ||
| 803 | |||
| 804 | start = srcy * blit->src_pitch + srcx; | ||
| 805 | |||
| 806 | DMA_BLOCK(MGA_AR0, start + w, | ||
| 807 | MGA_AR3, start, | ||
| 808 | MGA_FXBNDRY, ((dstx + w) << 16) | (dstx & 0xffff), | ||
| 809 | MGA_YDSTLEN + MGA_EXEC, (dsty << 16) | h); | ||
| 810 | } | ||
| 811 | |||
| 812 | /* Do something to flush AGP? | ||
| 813 | */ | ||
| 814 | |||
| 815 | /* Force reset of DWGCTL */ | ||
| 816 | DMA_BLOCK(MGA_DMAPAD, 0x00000000, | ||
| 817 | MGA_PLNWT, ctx->plnwt, | ||
| 818 | MGA_PITCH, dev_priv->front_pitch, MGA_DWGCTL, ctx->dwgctl); | ||
| 819 | |||
| 820 | ADVANCE_DMA(); | ||
| 821 | } | ||
| 822 | |||
| 823 | /* ================================================================ | ||
| 824 | * | ||
| 825 | */ | ||
| 826 | |||
| 827 | static int mga_dma_clear(struct drm_device *dev, void *data, struct drm_file *file_priv) | ||
| 828 | { | ||
| 829 | drm_mga_private_t *dev_priv = dev->dev_private; | ||
| 830 | drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; | ||
| 831 | drm_mga_clear_t *clear = data; | ||
| 832 | |||
| 833 | LOCK_TEST_WITH_RETURN(dev, file_priv); | ||
| 834 | |||
| 835 | if (sarea_priv->nbox > MGA_NR_SAREA_CLIPRECTS) | ||
| 836 | sarea_priv->nbox = MGA_NR_SAREA_CLIPRECTS; | ||
| 837 | |||
| 838 | WRAP_TEST_WITH_RETURN(dev_priv); | ||
| 839 | |||
| 840 | mga_dma_dispatch_clear(dev, clear); | ||
| 841 | |||
| 842 | /* Make sure we restore the 3D state next time. | ||
| 843 | */ | ||
| 844 | dev_priv->sarea_priv->dirty |= MGA_UPLOAD_CONTEXT; | ||
| 845 | |||
| 846 | return 0; | ||
| 847 | } | ||
| 848 | |||
| 849 | static int mga_dma_swap(struct drm_device *dev, void *data, struct drm_file *file_priv) | ||
| 850 | { | ||
| 851 | drm_mga_private_t *dev_priv = dev->dev_private; | ||
| 852 | drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; | ||
| 853 | |||
| 854 | LOCK_TEST_WITH_RETURN(dev, file_priv); | ||
| 855 | |||
| 856 | if (sarea_priv->nbox > MGA_NR_SAREA_CLIPRECTS) | ||
| 857 | sarea_priv->nbox = MGA_NR_SAREA_CLIPRECTS; | ||
| 858 | |||
| 859 | WRAP_TEST_WITH_RETURN(dev_priv); | ||
| 860 | |||
| 861 | mga_dma_dispatch_swap(dev); | ||
| 862 | |||
| 863 | /* Make sure we restore the 3D state next time. | ||
| 864 | */ | ||
| 865 | dev_priv->sarea_priv->dirty |= MGA_UPLOAD_CONTEXT; | ||
| 866 | |||
| 867 | return 0; | ||
| 868 | } | ||
| 869 | |||
| 870 | static int mga_dma_vertex(struct drm_device *dev, void *data, struct drm_file *file_priv) | ||
| 871 | { | ||
| 872 | drm_mga_private_t *dev_priv = dev->dev_private; | ||
| 873 | struct drm_device_dma *dma = dev->dma; | ||
| 874 | struct drm_buf *buf; | ||
| 875 | drm_mga_buf_priv_t *buf_priv; | ||
| 876 | drm_mga_vertex_t *vertex = data; | ||
| 877 | |||
| 878 | LOCK_TEST_WITH_RETURN(dev, file_priv); | ||
| 879 | |||
| 880 | if (vertex->idx < 0 || vertex->idx > dma->buf_count) | ||
| 881 | return -EINVAL; | ||
| 882 | buf = dma->buflist[vertex->idx]; | ||
| 883 | buf_priv = buf->dev_private; | ||
| 884 | |||
| 885 | buf->used = vertex->used; | ||
| 886 | buf_priv->discard = vertex->discard; | ||
| 887 | |||
| 888 | if (!mga_verify_state(dev_priv)) { | ||
| 889 | if (vertex->discard) { | ||
| 890 | if (buf_priv->dispatched == 1) | ||
| 891 | AGE_BUFFER(buf_priv); | ||
| 892 | buf_priv->dispatched = 0; | ||
| 893 | mga_freelist_put(dev, buf); | ||
| 894 | } | ||
| 895 | return -EINVAL; | ||
| 896 | } | ||
| 897 | |||
| 898 | WRAP_TEST_WITH_RETURN(dev_priv); | ||
| 899 | |||
| 900 | mga_dma_dispatch_vertex(dev, buf); | ||
| 901 | |||
| 902 | return 0; | ||
| 903 | } | ||
| 904 | |||
| 905 | static int mga_dma_indices(struct drm_device *dev, void *data, struct drm_file *file_priv) | ||
| 906 | { | ||
| 907 | drm_mga_private_t *dev_priv = dev->dev_private; | ||
| 908 | struct drm_device_dma *dma = dev->dma; | ||
| 909 | struct drm_buf *buf; | ||
| 910 | drm_mga_buf_priv_t *buf_priv; | ||
| 911 | drm_mga_indices_t *indices = data; | ||
| 912 | |||
| 913 | LOCK_TEST_WITH_RETURN(dev, file_priv); | ||
| 914 | |||
| 915 | if (indices->idx < 0 || indices->idx > dma->buf_count) | ||
| 916 | return -EINVAL; | ||
| 917 | |||
| 918 | buf = dma->buflist[indices->idx]; | ||
| 919 | buf_priv = buf->dev_private; | ||
| 920 | |||
| 921 | buf_priv->discard = indices->discard; | ||
| 922 | |||
| 923 | if (!mga_verify_state(dev_priv)) { | ||
| 924 | if (indices->discard) { | ||
| 925 | if (buf_priv->dispatched == 1) | ||
| 926 | AGE_BUFFER(buf_priv); | ||
| 927 | buf_priv->dispatched = 0; | ||
| 928 | mga_freelist_put(dev, buf); | ||
| 929 | } | ||
| 930 | return -EINVAL; | ||
| 931 | } | ||
| 932 | |||
| 933 | WRAP_TEST_WITH_RETURN(dev_priv); | ||
| 934 | |||
| 935 | mga_dma_dispatch_indices(dev, buf, indices->start, indices->end); | ||
| 936 | |||
| 937 | return 0; | ||
| 938 | } | ||
| 939 | |||
| 940 | static int mga_dma_iload(struct drm_device *dev, void *data, struct drm_file *file_priv) | ||
| 941 | { | ||
| 942 | struct drm_device_dma *dma = dev->dma; | ||
| 943 | drm_mga_private_t *dev_priv = dev->dev_private; | ||
| 944 | struct drm_buf *buf; | ||
| 945 | drm_mga_iload_t *iload = data; | ||
| 946 | DRM_DEBUG("\n"); | ||
| 947 | |||
| 948 | LOCK_TEST_WITH_RETURN(dev, file_priv); | ||
| 949 | |||
| 950 | #if 0 | ||
| 951 | if (mga_do_wait_for_idle(dev_priv) < 0) { | ||
| 952 | if (MGA_DMA_DEBUG) | ||
| 953 | DRM_INFO("-EBUSY\n"); | ||
| 954 | return -EBUSY; | ||
| 955 | } | ||
| 956 | #endif | ||
| 957 | if (iload->idx < 0 || iload->idx > dma->buf_count) | ||
| 958 | return -EINVAL; | ||
| 959 | |||
| 960 | buf = dma->buflist[iload->idx]; | ||
| 961 | |||
| 962 | if (mga_verify_iload(dev_priv, iload->dstorg, iload->length)) { | ||
| 963 | mga_freelist_put(dev, buf); | ||
| 964 | return -EINVAL; | ||
| 965 | } | ||
| 966 | |||
| 967 | WRAP_TEST_WITH_RETURN(dev_priv); | ||
| 968 | |||
| 969 | mga_dma_dispatch_iload(dev, buf, iload->dstorg, iload->length); | ||
| 970 | |||
| 971 | /* Make sure we restore the 3D state next time. | ||
| 972 | */ | ||
| 973 | dev_priv->sarea_priv->dirty |= MGA_UPLOAD_CONTEXT; | ||
| 974 | |||
| 975 | return 0; | ||
| 976 | } | ||
| 977 | |||
| 978 | static int mga_dma_blit(struct drm_device *dev, void *data, struct drm_file *file_priv) | ||
| 979 | { | ||
| 980 | drm_mga_private_t *dev_priv = dev->dev_private; | ||
| 981 | drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; | ||
| 982 | drm_mga_blit_t *blit = data; | ||
| 983 | DRM_DEBUG("\n"); | ||
| 984 | |||
| 985 | LOCK_TEST_WITH_RETURN(dev, file_priv); | ||
| 986 | |||
| 987 | if (sarea_priv->nbox > MGA_NR_SAREA_CLIPRECTS) | ||
| 988 | sarea_priv->nbox = MGA_NR_SAREA_CLIPRECTS; | ||
| 989 | |||
| 990 | if (mga_verify_blit(dev_priv, blit->srcorg, blit->dstorg)) | ||
| 991 | return -EINVAL; | ||
| 992 | |||
| 993 | WRAP_TEST_WITH_RETURN(dev_priv); | ||
| 994 | |||
| 995 | mga_dma_dispatch_blit(dev, blit); | ||
| 996 | |||
| 997 | /* Make sure we restore the 3D state next time. | ||
| 998 | */ | ||
| 999 | dev_priv->sarea_priv->dirty |= MGA_UPLOAD_CONTEXT; | ||
| 1000 | |||
| 1001 | return 0; | ||
| 1002 | } | ||
| 1003 | |||
| 1004 | int mga_getparam(struct drm_device *dev, void *data, struct drm_file *file_priv) | ||
| 1005 | { | ||
| 1006 | drm_mga_private_t *dev_priv = dev->dev_private; | ||
| 1007 | drm_mga_getparam_t *param = data; | ||
| 1008 | struct pci_dev *pdev = to_pci_dev(dev->dev); | ||
| 1009 | int value; | ||
| 1010 | |||
| 1011 | if (!dev_priv) { | ||
| 1012 | DRM_ERROR("called with no initialization\n"); | ||
| 1013 | return -EINVAL; | ||
| 1014 | } | ||
| 1015 | |||
| 1016 | DRM_DEBUG("pid=%d\n", task_pid_nr(current)); | ||
| 1017 | |||
| 1018 | switch (param->param) { | ||
| 1019 | case MGA_PARAM_IRQ_NR: | ||
| 1020 | value = pdev->irq; | ||
| 1021 | break; | ||
| 1022 | case MGA_PARAM_CARD_TYPE: | ||
| 1023 | value = dev_priv->chipset; | ||
| 1024 | break; | ||
| 1025 | default: | ||
| 1026 | return -EINVAL; | ||
| 1027 | } | ||
| 1028 | |||
| 1029 | if (copy_to_user(param->value, &value, sizeof(int))) { | ||
| 1030 | DRM_ERROR("copy_to_user\n"); | ||
| 1031 | return -EFAULT; | ||
| 1032 | } | ||
| 1033 | |||
| 1034 | return 0; | ||
| 1035 | } | ||
| 1036 | |||
| 1037 | static int mga_set_fence(struct drm_device *dev, void *data, struct drm_file *file_priv) | ||
| 1038 | { | ||
| 1039 | drm_mga_private_t *dev_priv = dev->dev_private; | ||
| 1040 | u32 *fence = data; | ||
| 1041 | DMA_LOCALS; | ||
| 1042 | |||
| 1043 | if (!dev_priv) { | ||
| 1044 | DRM_ERROR("called with no initialization\n"); | ||
| 1045 | return -EINVAL; | ||
| 1046 | } | ||
| 1047 | |||
| 1048 | DRM_DEBUG("pid=%d\n", task_pid_nr(current)); | ||
| 1049 | |||
| 1050 | /* I would normal do this assignment in the declaration of fence, | ||
| 1051 | * but dev_priv may be NULL. | ||
| 1052 | */ | ||
| 1053 | |||
| 1054 | *fence = dev_priv->next_fence_to_post; | ||
| 1055 | dev_priv->next_fence_to_post++; | ||
| 1056 | |||
| 1057 | BEGIN_DMA(1); | ||
| 1058 | DMA_BLOCK(MGA_DMAPAD, 0x00000000, | ||
| 1059 | MGA_DMAPAD, 0x00000000, | ||
| 1060 | MGA_DMAPAD, 0x00000000, MGA_SOFTRAP, 0x00000000); | ||
| 1061 | ADVANCE_DMA(); | ||
| 1062 | |||
| 1063 | return 0; | ||
| 1064 | } | ||
| 1065 | |||
| 1066 | static int mga_wait_fence(struct drm_device *dev, void *data, struct drm_file * | ||
| 1067 | file_priv) | ||
| 1068 | { | ||
| 1069 | drm_mga_private_t *dev_priv = dev->dev_private; | ||
| 1070 | u32 *fence = data; | ||
| 1071 | |||
| 1072 | if (!dev_priv) { | ||
| 1073 | DRM_ERROR("called with no initialization\n"); | ||
| 1074 | return -EINVAL; | ||
| 1075 | } | ||
| 1076 | |||
| 1077 | DRM_DEBUG("pid=%d\n", task_pid_nr(current)); | ||
| 1078 | |||
| 1079 | mga_driver_fence_wait(dev, fence); | ||
| 1080 | return 0; | ||
| 1081 | } | ||
| 1082 | |||
| 1083 | const struct drm_ioctl_desc mga_ioctls[] = { | ||
| 1084 | DRM_IOCTL_DEF_DRV(MGA_INIT, mga_dma_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), | ||
| 1085 | DRM_IOCTL_DEF_DRV(MGA_FLUSH, mga_dma_flush, DRM_AUTH), | ||
| 1086 | DRM_IOCTL_DEF_DRV(MGA_RESET, mga_dma_reset, DRM_AUTH), | ||
| 1087 | DRM_IOCTL_DEF_DRV(MGA_SWAP, mga_dma_swap, DRM_AUTH), | ||
| 1088 | DRM_IOCTL_DEF_DRV(MGA_CLEAR, mga_dma_clear, DRM_AUTH), | ||
| 1089 | DRM_IOCTL_DEF_DRV(MGA_VERTEX, mga_dma_vertex, DRM_AUTH), | ||
| 1090 | DRM_IOCTL_DEF_DRV(MGA_INDICES, mga_dma_indices, DRM_AUTH), | ||
| 1091 | DRM_IOCTL_DEF_DRV(MGA_ILOAD, mga_dma_iload, DRM_AUTH), | ||
| 1092 | DRM_IOCTL_DEF_DRV(MGA_BLIT, mga_dma_blit, DRM_AUTH), | ||
| 1093 | DRM_IOCTL_DEF_DRV(MGA_GETPARAM, mga_getparam, DRM_AUTH), | ||
| 1094 | DRM_IOCTL_DEF_DRV(MGA_SET_FENCE, mga_set_fence, DRM_AUTH), | ||
| 1095 | DRM_IOCTL_DEF_DRV(MGA_WAIT_FENCE, mga_wait_fence, DRM_AUTH), | ||
| 1096 | DRM_IOCTL_DEF_DRV(MGA_DMA_BOOTSTRAP, mga_dma_bootstrap, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), | ||
| 1097 | }; | ||
| 1098 | |||
| 1099 | int mga_max_ioctl = ARRAY_SIZE(mga_ioctls); | ||
| @@ -1,167 +0,0 @@ | |||
| 1 | /* mga_warp.c -- Matrox G200/G400 WARP engine management -*- linux-c -*- | ||
| 2 | * Created: Thu Jan 11 21:29:32 2001 by gareth@valinux.com | ||
| 3 | * | ||
| 4 | * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. | ||
| 5 | * All Rights Reserved. | ||
| 6 | * | ||
| 7 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
| 8 | * copy of this software and associated documentation files (the "Software"), | ||
| 9 | * to deal in the Software without restriction, including without limitation | ||
| 10 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
| 11 | * and/or sell copies of the Software, and to permit persons to whom the | ||
| 12 | * Software is furnished to do so, subject to the following conditions: | ||
| 13 | * | ||
| 14 | * The above copyright notice and this permission notice (including the next | ||
| 15 | * paragraph) shall be included in all copies or substantial portions of the | ||
| 16 | * Software. | ||
| 17 | * | ||
| 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
| 21 | * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR | ||
| 22 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | ||
| 23 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | ||
| 24 | * OTHER DEALINGS IN THE SOFTWARE. | ||
| 25 | * | ||
| 26 | * Authors: | ||
| 27 | * Gareth Hughes <gareth@valinux.com> | ||
| 28 | */ | ||
| 29 | |||
| 30 | #include <linux/firmware.h> | ||
| 31 | #include <linux/ihex.h> | ||
| 32 | #include <linux/module.h> | ||
| 33 | #include <linux/platform_device.h> | ||
| 34 | |||
| 35 | #include "mga_drv.h" | ||
| 36 | |||
| 37 | #define FIRMWARE_G200 "matrox/g200_warp.fw" | ||
| 38 | #define FIRMWARE_G400 "matrox/g400_warp.fw" | ||
| 39 | |||
| 40 | MODULE_FIRMWARE(FIRMWARE_G200); | ||
| 41 | MODULE_FIRMWARE(FIRMWARE_G400); | ||
| 42 | |||
| 43 | #define MGA_WARP_CODE_ALIGN 256 /* in bytes */ | ||
| 44 | |||
| 45 | #define WARP_UCODE_SIZE(size) ALIGN(size, MGA_WARP_CODE_ALIGN) | ||
| 46 | |||
| 47 | int mga_warp_install_microcode(drm_mga_private_t *dev_priv) | ||
| 48 | { | ||
| 49 | unsigned char *vcbase = dev_priv->warp->handle; | ||
| 50 | unsigned long pcbase = dev_priv->warp->offset; | ||
| 51 | const char *firmware_name; | ||
| 52 | struct platform_device *pdev; | ||
| 53 | const struct firmware *fw = NULL; | ||
| 54 | const struct ihex_binrec *rec; | ||
| 55 | unsigned int size; | ||
| 56 | int n_pipes, where; | ||
| 57 | int rc = 0; | ||
| 58 | |||
| 59 | switch (dev_priv->chipset) { | ||
| 60 | case MGA_CARD_TYPE_G400: | ||
| 61 | case MGA_CARD_TYPE_G550: | ||
| 62 | firmware_name = FIRMWARE_G400; | ||
| 63 | n_pipes = MGA_MAX_G400_PIPES; | ||
| 64 | break; | ||
| 65 | case MGA_CARD_TYPE_G200: | ||
| 66 | firmware_name = FIRMWARE_G200; | ||
| 67 | n_pipes = MGA_MAX_G200_PIPES; | ||
| 68 | break; | ||
| 69 | default: | ||
| 70 | return -EINVAL; | ||
| 71 | } | ||
| 72 | |||
| 73 | pdev = platform_device_register_simple("mga_warp", 0, NULL, 0); | ||
| 74 | if (IS_ERR(pdev)) { | ||
| 75 | DRM_ERROR("mga: Failed to register microcode\n"); | ||
| 76 | return PTR_ERR(pdev); | ||
| 77 | } | ||
| 78 | rc = request_ihex_firmware(&fw, firmware_name, &pdev->dev); | ||
| 79 | platform_device_unregister(pdev); | ||
| 80 | if (rc) { | ||
| 81 | DRM_ERROR("mga: Failed to load microcode \"%s\"\n", | ||
| 82 | firmware_name); | ||
| 83 | return rc; | ||
| 84 | } | ||
| 85 | |||
| 86 | size = 0; | ||
| 87 | where = 0; | ||
| 88 | for (rec = (const struct ihex_binrec *)fw->data; | ||
| 89 | rec; | ||
| 90 | rec = ihex_next_binrec(rec)) { | ||
| 91 | size += WARP_UCODE_SIZE(be16_to_cpu(rec->len)); | ||
| 92 | where++; | ||
| 93 | } | ||
| 94 | |||
| 95 | if (where != n_pipes) { | ||
| 96 | DRM_ERROR("mga: Invalid microcode \"%s\"\n", firmware_name); | ||
| 97 | rc = -EINVAL; | ||
| 98 | goto out; | ||
| 99 | } | ||
| 100 | size = PAGE_ALIGN(size); | ||
| 101 | DRM_DEBUG("MGA ucode size = %d bytes\n", size); | ||
| 102 | if (size > dev_priv->warp->size) { | ||
| 103 | DRM_ERROR("microcode too large! (%u > %lu)\n", | ||
| 104 | size, dev_priv->warp->size); | ||
| 105 | rc = -ENOMEM; | ||
| 106 | goto out; | ||
| 107 | } | ||
| 108 | |||
| 109 | memset(dev_priv->warp_pipe_phys, 0, sizeof(dev_priv->warp_pipe_phys)); | ||
| 110 | |||
| 111 | where = 0; | ||
| 112 | for (rec = (const struct ihex_binrec *)fw->data; | ||
| 113 | rec; | ||
| 114 | rec = ihex_next_binrec(rec)) { | ||
| 115 | unsigned int src_size, dst_size; | ||
| 116 | |||
| 117 | DRM_DEBUG(" pcbase = 0x%08lx vcbase = %p\n", pcbase, vcbase); | ||
| 118 | dev_priv->warp_pipe_phys[where] = pcbase; | ||
| 119 | src_size = be16_to_cpu(rec->len); | ||
| 120 | dst_size = WARP_UCODE_SIZE(src_size); | ||
| 121 | memcpy(vcbase, rec->data, src_size); | ||
| 122 | pcbase += dst_size; | ||
| 123 | vcbase += dst_size; | ||
| 124 | where++; | ||
| 125 | } | ||
| 126 | |||
| 127 | out: | ||
| 128 | release_firmware(fw); | ||
| 129 | return rc; | ||
| 130 | } | ||
| 131 | |||
| 132 | #define WMISC_EXPECTED (MGA_WUCODECACHE_ENABLE | MGA_WMASTER_ENABLE) | ||
| 133 | |||
| 134 | int mga_warp_init(drm_mga_private_t *dev_priv) | ||
| 135 | { | ||
| 136 | u32 wmisc; | ||
| 137 | |||
| 138 | /* FIXME: Get rid of these damned magic numbers... | ||
| 139 | */ | ||
| 140 | switch (dev_priv->chipset) { | ||
| 141 | case MGA_CARD_TYPE_G400: | ||
| 142 | case MGA_CARD_TYPE_G550: | ||
| 143 | MGA_WRITE(MGA_WIADDR2, MGA_WMODE_SUSPEND); | ||
| 144 | MGA_WRITE(MGA_WGETMSB, 0x00000E00); | ||
| 145 | MGA_WRITE(MGA_WVRTXSZ, 0x00001807); | ||
| 146 | MGA_WRITE(MGA_WACCEPTSEQ, 0x18000000); | ||
| 147 | break; | ||
| 148 | case MGA_CARD_TYPE_G200: | ||
| 149 | MGA_WRITE(MGA_WIADDR, MGA_WMODE_SUSPEND); | ||
| 150 | MGA_WRITE(MGA_WGETMSB, 0x1606); | ||
| 151 | MGA_WRITE(MGA_WVRTXSZ, 7); | ||
| 152 | break; | ||
| 153 | default: | ||
| 154 | return -EINVAL; | ||
| 155 | } | ||
| 156 | |||
| 157 | MGA_WRITE(MGA_WMISC, (MGA_WUCODECACHE_ENABLE | | ||
| 158 | MGA_WMASTER_ENABLE | MGA_WCACHEFLUSH_ENABLE)); | ||
| 159 | wmisc = MGA_READ(MGA_WMISC); | ||
| 160 | if (wmisc != WMISC_EXPECTED) { | ||
| 161 | DRM_ERROR("WARP engine config failed! 0x%x != 0x%x\n", | ||
| 162 | wmisc, WMISC_EXPECTED); | ||
| 163 | return -EINVAL; | ||
| 164 | } | ||
| 165 | |||
| 166 | return 0; | ||
| 167 | } | ||
| @@ -1,429 +0,0 @@ | |||
| 1 | /* mga_drm.h -- Public header for the Matrox g200/g400 driver -*- linux-c -*- | ||
| 2 | * Created: Tue Jan 25 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 | * VA LINUX SYSTEMS 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 | ||
| 25 | * OTHER DEALINGS IN THE SOFTWARE. | ||
| 26 | * | ||
| 27 | * Authors: | ||
| 28 | * Jeff Hartmann <jhartmann@valinux.com> | ||
| 29 | * Keith Whitwell <keith@tungstengraphics.com> | ||
| 30 | * | ||
| 31 | * Rewritten by: | ||
| 32 | * Gareth Hughes <gareth@valinux.com> | ||
| 33 | */ | ||
| 34 | |||
| 35 | #ifndef __MGA_DRM_H__ | ||
| 36 | #define __MGA_DRM_H__ | ||
| 37 | |||
| 38 | #include "drm.h" | ||
| 39 | |||
| 40 | #if defined(__cplusplus) | ||
| 41 | extern "C" { | ||
| 42 | #endif | ||
| 43 | |||
| 44 | /* WARNING: If you change any of these defines, make sure to change the | ||
| 45 | * defines in the Xserver file (mga_sarea.h) | ||
| 46 | */ | ||
| 47 | |||
| 48 | #ifndef __MGA_SAREA_DEFINES__ | ||
| 49 | #define __MGA_SAREA_DEFINES__ | ||
| 50 | |||
| 51 | /* WARP pipe flags | ||
| 52 | */ | ||
| 53 | #define MGA_F 0x1 /* fog */ | ||
| 54 | #define MGA_A 0x2 /* alpha */ | ||
| 55 | #define MGA_S 0x4 /* specular */ | ||
| 56 | #define MGA_T2 0x8 /* multitexture */ | ||
| 57 | |||
| 58 | #define MGA_WARP_TGZ 0 | ||
| 59 | #define MGA_WARP_TGZF (MGA_F) | ||
| 60 | #define MGA_WARP_TGZA (MGA_A) | ||
| 61 | #define MGA_WARP_TGZAF (MGA_F|MGA_A) | ||
| 62 | #define MGA_WARP_TGZS (MGA_S) | ||
| 63 | #define MGA_WARP_TGZSF (MGA_S|MGA_F) | ||
| 64 | #define MGA_WARP_TGZSA (MGA_S|MGA_A) | ||
| 65 | #define MGA_WARP_TGZSAF (MGA_S|MGA_F|MGA_A) | ||
| 66 | #define MGA_WARP_T2GZ (MGA_T2) | ||
| 67 | #define MGA_WARP_T2GZF (MGA_T2|MGA_F) | ||
| 68 | #define MGA_WARP_T2GZA (MGA_T2|MGA_A) | ||
| 69 | #define MGA_WARP_T2GZAF (MGA_T2|MGA_A|MGA_F) | ||
| 70 | #define MGA_WARP_T2GZS (MGA_T2|MGA_S) | ||
| 71 | #define MGA_WARP_T2GZSF (MGA_T2|MGA_S|MGA_F) | ||
| 72 | #define MGA_WARP_T2GZSA (MGA_T2|MGA_S|MGA_A) | ||
| 73 | #define MGA_WARP_T2GZSAF (MGA_T2|MGA_S|MGA_F|MGA_A) | ||
| 74 | |||
| 75 | #define MGA_MAX_G200_PIPES 8 /* no multitex */ | ||
| 76 | #define MGA_MAX_G400_PIPES 16 | ||
| 77 | #define MGA_MAX_WARP_PIPES MGA_MAX_G400_PIPES | ||
| 78 | #define MGA_WARP_UCODE_SIZE 32768 /* in bytes */ | ||
| 79 | |||
| 80 | #define MGA_CARD_TYPE_G200 1 | ||
| 81 | #define MGA_CARD_TYPE_G400 2 | ||
| 82 | #define MGA_CARD_TYPE_G450 3 /* not currently used */ | ||
| 83 | #define MGA_CARD_TYPE_G550 4 | ||
| 84 | |||
| 85 | #define MGA_FRONT 0x1 | ||
| 86 | #define MGA_BACK 0x2 | ||
| 87 | #define MGA_DEPTH 0x4 | ||
| 88 | |||
| 89 | /* What needs to be changed for the current vertex dma buffer? | ||
| 90 | */ | ||
| 91 | #define MGA_UPLOAD_CONTEXT 0x1 | ||
| 92 | #define MGA_UPLOAD_TEX0 0x2 | ||
| 93 | #define MGA_UPLOAD_TEX1 0x4 | ||
| 94 | #define MGA_UPLOAD_PIPE 0x8 | ||
| 95 | #define MGA_UPLOAD_TEX0IMAGE 0x10 /* handled client-side */ | ||
| 96 | #define MGA_UPLOAD_TEX1IMAGE 0x20 /* handled client-side */ | ||
| 97 | #define MGA_UPLOAD_2D 0x40 | ||
| 98 | #define MGA_WAIT_AGE 0x80 /* handled client-side */ | ||
| 99 | #define MGA_UPLOAD_CLIPRECTS 0x100 /* handled client-side */ | ||
| 100 | #if 0 | ||
| 101 | #define MGA_DMA_FLUSH 0x200 /* set when someone gets the lock | ||
| 102 | quiescent */ | ||
| 103 | #endif | ||
| 104 | |||
| 105 | /* 32 buffers of 64k each, total 2 meg. | ||
| 106 | */ | ||
| 107 | #define MGA_BUFFER_SIZE (1 << 16) | ||
| 108 | #define MGA_NUM_BUFFERS 128 | ||
| 109 | |||
| 110 | /* Keep these small for testing. | ||
| 111 | */ | ||
| 112 | #define MGA_NR_SAREA_CLIPRECTS 8 | ||
| 113 | |||
| 114 | /* 2 heaps (1 for card, 1 for agp), each divided into up to 128 | ||
| 115 | * regions, subject to a minimum region size of (1<<16) == 64k. | ||
| 116 | * | ||
| 117 | * Clients may subdivide regions internally, but when sharing between | ||
| 118 | * clients, the region size is the minimum granularity. | ||
| 119 | */ | ||
| 120 | |||
| 121 | #define MGA_CARD_HEAP 0 | ||
| 122 | #define MGA_AGP_HEAP 1 | ||
| 123 | #define MGA_NR_TEX_HEAPS 2 | ||
| 124 | #define MGA_NR_TEX_REGIONS 16 | ||
| 125 | #define MGA_LOG_MIN_TEX_REGION_SIZE 16 | ||
| 126 | |||
| 127 | #define DRM_MGA_IDLE_RETRY 2048 | ||
| 128 | |||
| 129 | #endif /* __MGA_SAREA_DEFINES__ */ | ||
| 130 | |||
| 131 | /* Setup registers for 3D context | ||
| 132 | */ | ||
| 133 | typedef struct { | ||
| 134 | unsigned int dstorg; | ||
| 135 | unsigned int maccess; | ||
| 136 | unsigned int plnwt; | ||
| 137 | unsigned int dwgctl; | ||
| 138 | unsigned int alphactrl; | ||
| 139 | unsigned int fogcolor; | ||
| 140 | unsigned int wflag; | ||
| 141 | unsigned int tdualstage0; | ||
| 142 | unsigned int tdualstage1; | ||
| 143 | unsigned int fcol; | ||
| 144 | unsigned int stencil; | ||
| 145 | unsigned int stencilctl; | ||
| 146 | } drm_mga_context_regs_t; | ||
| 147 | |||
| 148 | /* Setup registers for 2D, X server | ||
| 149 | */ | ||
| 150 | typedef struct { | ||
| 151 | unsigned int pitch; | ||
| 152 | } drm_mga_server_regs_t; | ||
| 153 | |||
| 154 | /* Setup registers for each texture unit | ||
| 155 | */ | ||
| 156 | typedef struct { | ||
| 157 | unsigned int texctl; | ||
| 158 | unsigned int texctl2; | ||
| 159 | unsigned int texfilter; | ||
| 160 | unsigned int texbordercol; | ||
| 161 | unsigned int texorg; | ||
| 162 | unsigned int texwidth; | ||
| 163 | unsigned int texheight; | ||
| 164 | unsigned int texorg1; | ||
| 165 | unsigned int texorg2; | ||
| 166 | unsigned int texorg3; | ||
| 167 | unsigned int texorg4; | ||
| 168 | } drm_mga_texture_regs_t; | ||
| 169 | |||
| 170 | /* General aging mechanism | ||
| 171 | */ | ||
| 172 | typedef struct { | ||
| 173 | unsigned int head; /* Position of head pointer */ | ||
| 174 | unsigned int wrap; /* Primary DMA wrap count */ | ||
| 175 | } drm_mga_age_t; | ||
| 176 | |||
| 177 | typedef struct _drm_mga_sarea { | ||
| 178 | /* The channel for communication of state information to the kernel | ||
| 179 | * on firing a vertex dma buffer. | ||
| 180 | */ | ||
| 181 | drm_mga_context_regs_t context_state; | ||
| 182 | drm_mga_server_regs_t server_state; | ||
| 183 | drm_mga_texture_regs_t tex_state[2]; | ||
| 184 | unsigned int warp_pipe; | ||
| 185 | unsigned int dirty; | ||
| 186 | unsigned int vertsize; | ||
| 187 | |||
| 188 | /* The current cliprects, or a subset thereof. | ||
| 189 | */ | ||
| 190 | struct drm_clip_rect boxes[MGA_NR_SAREA_CLIPRECTS]; | ||
| 191 | unsigned int nbox; | ||
| 192 | |||
| 193 | /* Information about the most recently used 3d drawable. The | ||
| 194 | * client fills in the req_* fields, the server fills in the | ||
| 195 | * exported_ fields and puts the cliprects into boxes, above. | ||
| 196 | * | ||
| 197 | * The client clears the exported_drawable field before | ||
| 198 | * clobbering the boxes data. | ||
| 199 | */ | ||
| 200 | unsigned int req_drawable; /* the X drawable id */ | ||
| 201 | unsigned int req_draw_buffer; /* MGA_FRONT or MGA_BACK */ | ||
| 202 | |||
| 203 | unsigned int exported_drawable; | ||
| 204 | unsigned int exported_index; | ||
| 205 | unsigned int exported_stamp; | ||
| 206 | unsigned int exported_buffers; | ||
| 207 | unsigned int exported_nfront; | ||
| 208 | unsigned int exported_nback; | ||
| 209 | int exported_back_x, exported_front_x, exported_w; | ||
| 210 | int exported_back_y, exported_front_y, exported_h; | ||
| 211 | struct drm_clip_rect exported_boxes[MGA_NR_SAREA_CLIPRECTS]; | ||
| 212 | |||
| 213 | /* Counters for aging textures and for client-side throttling. | ||
| 214 | */ | ||
| 215 | unsigned int status[4]; | ||
| 216 | unsigned int last_wrap; | ||
| 217 | |||
| 218 | drm_mga_age_t last_frame; | ||
| 219 | unsigned int last_enqueue; /* last time a buffer was enqueued */ | ||
| 220 | unsigned int last_dispatch; /* age of the most recently dispatched buffer */ | ||
| 221 | unsigned int last_quiescent; /* */ | ||
| 222 | |||
| 223 | /* LRU lists for texture memory in agp space and on the card. | ||
| 224 | */ | ||
| 225 | struct drm_tex_region texList[MGA_NR_TEX_HEAPS][MGA_NR_TEX_REGIONS + 1]; | ||
| 226 | unsigned int texAge[MGA_NR_TEX_HEAPS]; | ||
| 227 | |||
| 228 | /* Mechanism to validate card state. | ||
| 229 | */ | ||
| 230 | int ctxOwner; | ||
| 231 | } drm_mga_sarea_t; | ||
| 232 | |||
| 233 | /* MGA specific ioctls | ||
| 234 | * The device specific ioctl range is 0x40 to 0x79. | ||
| 235 | */ | ||
| 236 | #define DRM_MGA_INIT 0x00 | ||
| 237 | #define DRM_MGA_FLUSH 0x01 | ||
| 238 | #define DRM_MGA_RESET 0x02 | ||
| 239 | #define DRM_MGA_SWAP 0x03 | ||
| 240 | #define DRM_MGA_CLEAR 0x04 | ||
| 241 | #define DRM_MGA_VERTEX 0x05 | ||
| 242 | #define DRM_MGA_INDICES 0x06 | ||
| 243 | #define DRM_MGA_ILOAD 0x07 | ||
| 244 | #define DRM_MGA_BLIT 0x08 | ||
| 245 | #define DRM_MGA_GETPARAM 0x09 | ||
| 246 | |||
| 247 | /* 3.2: | ||
| 248 | * ioctls for operating on fences. | ||
| 249 | */ | ||
| 250 | #define DRM_MGA_SET_FENCE 0x0a | ||
| 251 | #define DRM_MGA_WAIT_FENCE 0x0b | ||
| 252 | #define DRM_MGA_DMA_BOOTSTRAP 0x0c | ||
| 253 | |||
| 254 | #define DRM_IOCTL_MGA_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_INIT, drm_mga_init_t) | ||
| 255 | #define DRM_IOCTL_MGA_FLUSH DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_FLUSH, struct drm_lock) | ||
| 256 | #define DRM_IOCTL_MGA_RESET DRM_IO( DRM_COMMAND_BASE + DRM_MGA_RESET) | ||
| 257 | #define DRM_IOCTL_MGA_SWAP DRM_IO( DRM_COMMAND_BASE + DRM_MGA_SWAP) | ||
| 258 | #define DRM_IOCTL_MGA_CLEAR DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_CLEAR, drm_mga_clear_t) | ||
| 259 | #define DRM_IOCTL_MGA_VERTEX DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_VERTEX, drm_mga_vertex_t) | ||
| 260 | #define DRM_IOCTL_MGA_INDICES DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_INDICES, drm_mga_indices_t) | ||
| 261 | #define DRM_IOCTL_MGA_ILOAD DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_ILOAD, drm_mga_iload_t) | ||
| 262 | #define DRM_IOCTL_MGA_BLIT DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_BLIT, drm_mga_blit_t) | ||
| 263 | #define DRM_IOCTL_MGA_GETPARAM DRM_IOWR(DRM_COMMAND_BASE + DRM_MGA_GETPARAM, drm_mga_getparam_t) | ||
| 264 | #define DRM_IOCTL_MGA_SET_FENCE DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_SET_FENCE, __u32) | ||
| 265 | #define DRM_IOCTL_MGA_WAIT_FENCE DRM_IOWR(DRM_COMMAND_BASE + DRM_MGA_WAIT_FENCE, __u32) | ||
| 266 | #define DRM_IOCTL_MGA_DMA_BOOTSTRAP DRM_IOWR(DRM_COMMAND_BASE + DRM_MGA_DMA_BOOTSTRAP, drm_mga_dma_bootstrap_t) | ||
| 267 | |||
| 268 | typedef struct _drm_mga_warp_index { | ||
| 269 | int installed; | ||
| 270 | unsigned long phys_addr; | ||
| 271 | int size; | ||
| 272 | } drm_mga_warp_index_t; | ||
| 273 | |||
| 274 | typedef struct drm_mga_init { | ||
| 275 | enum { | ||
| 276 | MGA_INIT_DMA = 0x01, | ||
| 277 | MGA_CLEANUP_DMA = 0x02 | ||
| 278 | } func; | ||
| 279 | |||
| 280 | unsigned long sarea_priv_offset; | ||
| 281 | |||
| 282 | __struct_group(/* no tag */, always32bit, /* no attrs */, | ||
| 283 | int chipset; | ||
| 284 | int sgram; | ||
| 285 | |||
| 286 | unsigned int maccess; | ||
| 287 | |||
| 288 | unsigned int fb_cpp; | ||
| 289 | unsigned int front_offset, front_pitch; | ||
| 290 | unsigned int back_offset, back_pitch; | ||
| 291 | |||
| 292 | unsigned int depth_cpp; | ||
| 293 | unsigned int depth_offset, depth_pitch; | ||
| 294 | |||
| 295 | unsigned int texture_offset[MGA_NR_TEX_HEAPS]; | ||
| 296 | unsigned int texture_size[MGA_NR_TEX_HEAPS]; | ||
| 297 | ); | ||
| 298 | |||
| 299 | unsigned long fb_offset; | ||
| 300 | unsigned long mmio_offset; | ||
| 301 | unsigned long status_offset; | ||
| 302 | unsigned long warp_offset; | ||
| 303 | unsigned long primary_offset; | ||
| 304 | unsigned long buffers_offset; | ||
| 305 | } drm_mga_init_t; | ||
| 306 | |||
| 307 | typedef struct drm_mga_dma_bootstrap { | ||
| 308 | /** | ||
| 309 | * \name AGP texture region | ||
| 310 | * | ||
| 311 | * On return from the DRM_MGA_DMA_BOOTSTRAP ioctl, these fields will | ||
| 312 | * be filled in with the actual AGP texture settings. | ||
| 313 | * | ||
| 314 | * \warning | ||
| 315 | * If these fields are non-zero, but dma_mga_dma_bootstrap::agp_mode | ||
| 316 | * is zero, it means that PCI memory (most likely through the use of | ||
| 317 | * an IOMMU) is being used for "AGP" textures. | ||
| 318 | */ | ||
| 319 | /*@{ */ | ||
| 320 | unsigned long texture_handle; /**< Handle used to map AGP textures. */ | ||
| 321 | __u32 texture_size; /**< Size of the AGP texture region. */ | ||
| 322 | /*@} */ | ||
| 323 | |||
| 324 | /** | ||
| 325 | * Requested size of the primary DMA region. | ||
| 326 | * | ||
| 327 | * On return from the DRM_MGA_DMA_BOOTSTRAP ioctl, this field will be | ||
| 328 | * filled in with the actual AGP mode. If AGP was not available | ||
| 329 | */ | ||
| 330 | __u32 primary_size; | ||
| 331 | |||
| 332 | /** | ||
| 333 | * Requested number of secondary DMA buffers. | ||
| 334 | * | ||
| 335 | * On return from the DRM_MGA_DMA_BOOTSTRAP ioctl, this field will be | ||
| 336 | * filled in with the actual number of secondary DMA buffers | ||
| 337 | * allocated. Particularly when PCI DMA is used, this may be | ||
| 338 | * (subtantially) less than the number requested. | ||
| 339 | */ | ||
| 340 | __u32 secondary_bin_count; | ||
| 341 | |||
| 342 | /** | ||
| 343 | * Requested size of each secondary DMA buffer. | ||
| 344 | * | ||
| 345 | * While the kernel \b is free to reduce | ||
| 346 | * dma_mga_dma_bootstrap::secondary_bin_count, it is \b not allowed | ||
| 347 | * to reduce dma_mga_dma_bootstrap::secondary_bin_size. | ||
| 348 | */ | ||
| 349 | __u32 secondary_bin_size; | ||
| 350 | |||
| 351 | /** | ||
| 352 | * Bit-wise mask of AGPSTAT2_* values. Currently only \c AGPSTAT2_1X, | ||
| 353 | * \c AGPSTAT2_2X, and \c AGPSTAT2_4X are supported. If this value is | ||
| 354 | * zero, it means that PCI DMA should be used, even if AGP is | ||
| 355 | * possible. | ||
| 356 | * | ||
| 357 | * On return from the DRM_MGA_DMA_BOOTSTRAP ioctl, this field will be | ||
| 358 | * filled in with the actual AGP mode. If AGP was not available | ||
| 359 | * (i.e., PCI DMA was used), this value will be zero. | ||
| 360 | */ | ||
| 361 | __u32 agp_mode; | ||
| 362 | |||
| 363 | /** | ||
| 364 | * Desired AGP GART size, measured in megabytes. | ||
| 365 | */ | ||
| 366 | __u8 agp_size; | ||
| 367 | } drm_mga_dma_bootstrap_t; | ||
| 368 | |||
| 369 | typedef struct drm_mga_clear { | ||
| 370 | unsigned int flags; | ||
| 371 | unsigned int clear_color; | ||
| 372 | unsigned int clear_depth; | ||
| 373 | unsigned int color_mask; | ||
| 374 | unsigned int depth_mask; | ||
| 375 | } drm_mga_clear_t; | ||
| 376 | |||
| 377 | typedef struct drm_mga_vertex { | ||
| 378 | int idx; /* buffer to queue */ | ||
| 379 | int used; /* bytes in use */ | ||
| 380 | int discard; /* client finished with buffer? */ | ||
| 381 | } drm_mga_vertex_t; | ||
| 382 | |||
| 383 | typedef struct drm_mga_indices { | ||
| 384 | int idx; /* buffer to queue */ | ||
| 385 | unsigned int start; | ||
| 386 | unsigned int end; | ||
| 387 | int discard; /* client finished with buffer? */ | ||
| 388 | } drm_mga_indices_t; | ||
| 389 | |||
| 390 | typedef struct drm_mga_iload { | ||
| 391 | int idx; | ||
| 392 | unsigned int dstorg; | ||
| 393 | unsigned int length; | ||
| 394 | } drm_mga_iload_t; | ||
| 395 | |||
| 396 | typedef struct _drm_mga_blit { | ||
| 397 | unsigned int planemask; | ||
| 398 | unsigned int srcorg; | ||
| 399 | unsigned int dstorg; | ||
| 400 | int src_pitch, dst_pitch; | ||
| 401 | int delta_sx, delta_sy; | ||
| 402 | int delta_dx, delta_dy; | ||
| 403 | int height, ydir; /* flip image vertically */ | ||
| 404 | int source_pitch, dest_pitch; | ||
| 405 | } drm_mga_blit_t; | ||
| 406 | |||
| 407 | /* 3.1: An ioctl to get parameters that aren't available to the 3d | ||
| 408 | * client any other way. | ||
| 409 | */ | ||
| 410 | #define MGA_PARAM_IRQ_NR 1 | ||
| 411 | |||
| 412 | /* 3.2: Query the actual card type. The DDX only distinguishes between | ||
| 413 | * G200 chips and non-G200 chips, which it calls G400. It turns out that | ||
| 414 | * there are some very sublte differences between the G4x0 chips and the G550 | ||
| 415 | * chips. Using this parameter query, a client-side driver can detect the | ||
| 416 | * difference between a G4x0 and a G550. | ||
| 417 | */ | ||
| 418 | #define MGA_PARAM_CARD_TYPE 2 | ||
| 419 | |||
| 420 | typedef struct drm_mga_getparam { | ||
| 421 | int param; | ||
| 422 | void __user *value; | ||
| 423 | } drm_mga_getparam_t; | ||
| 424 | |||
| 425 | #if defined(__cplusplus) | ||
| 426 | } | ||
| 427 | #endif | ||
| 428 | |||
| 429 | #endif | ||