History

drm: Remove the obsolete driver-mga

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.

Cai Huoqing committed 3 years ago

Commit 96ed7db1 parent cab188611 files · +0 −4039Browse files

Unified · Split

11 files
  1. drivers/gpu/drm/Kconfig +0 −9
  2. drivers/gpu/drm/Makefile +0 −1
  3. drivers/gpu/drm/mga/Makefile +0 −11
  4. drivers/gpu/drm/mga/mga_dma.c +0 −1168
  5. drivers/gpu/drm/mga/mga_drv.c +0 −104
  6. drivers/gpu/drm/mga/mga_drv.h +0 −685
  7. drivers/gpu/drm/mga/mga_ioc32.c +0 −197
  8. drivers/gpu/drm/mga/mga_irq.c +0 −169
  9. drivers/gpu/drm/mga/mga_state.c +0 −1099
  10. drivers/gpu/drm/mga/mga_warp.c +0 −167
  11. include/uapi/drm/mga_drm.h +0 −429
drivers/gpu/drm/Kconfig+0−9
@@ -414,15 +414,6 @@ config DRM_R128 · 413 unmodified lines
414 is selected, the module will be called r128. AGP support for414 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
417config 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
426config DRM_SIS417config DRM_SIS
427 tristate "SiS video cards"418 tristate "SiS video cards"
428 depends on DRM && AGP419 depends on DRM && AGP
drivers/gpu/drm/Makefile+0−1
@@ -137,7 +137,6 @@ obj-$(CONFIG_DRM_TDFX) += tdfx/ · 136 unmodified lines
137obj-$(CONFIG_DRM_R128) += r128/137obj-$(CONFIG_DRM_R128) += r128/
138obj-$(CONFIG_DRM_RADEON)+= radeon/138obj-$(CONFIG_DRM_RADEON)+= radeon/
139obj-$(CONFIG_DRM_AMDGPU)+= amd/amdgpu/139obj-$(CONFIG_DRM_AMDGPU)+= amd/amdgpu/
140obj-$(CONFIG_DRM_MGA) += mga/
141obj-$(CONFIG_DRM_I915) += i915/140obj-$(CONFIG_DRM_I915) += i915/
142obj-$(CONFIG_DRM_KMB_DISPLAY) += kmb/141obj-$(CONFIG_DRM_KMB_DISPLAY) += kmb/
143obj-$(CONFIG_DRM_MGAG200) += mgag200/142obj-$(CONFIG_DRM_MGAG200) += mgag200/
drivers/gpu/drm/mga/Makefile+0−11
@@ -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
6mga-y := mga_drv.o mga_dma.o mga_state.o mga_warp.o mga_irq.o
7
8mga-$(CONFIG_COMPAT) += mga_ioc32.o
9
10obj-$(CONFIG_DRM_MGA) += mga.o
11
drivers/gpu/drm/mga/mga_dma.c+0−1168
@@ -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
47static int mga_do_cleanup_dma(struct drm_device *dev, int full_cleanup);
48
49/* ================================================================
50 * Engine control
51 */
52
53int 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
75static 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
103void 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
158void 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
198void 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
223static 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
244static 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
287static 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 */
307static 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
322static 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
355int 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
390int 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 */
454static 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
607static 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 */
628static 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
717static 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
775int 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
803static 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
942static 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
1014int 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
1039int 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
1071int 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
1085static 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
1110int 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 */
1150void 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 */
1159void mga_driver_lastclose(struct drm_device *dev)
1160{
1161 mga_do_cleanup_dma(dev, FULL_CLEANUP);
1162}
1163
1164int 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}
drivers/gpu/drm/mga/mga_drv.c+0−104
@@ -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
39static struct pci_device_id pciidlist[] = {
40 mga_PCI_IDS
41};
42
43static 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
56static 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
83static struct pci_driver mga_pci_driver = {
84 .name = DRIVER_NAME,
85 .id_table = pciidlist,
86};
87
88static 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
94static void __exit mga_exit(void)
95{
96 drm_legacy_pci_exit(&driver, &mga_pci_driver);
97}
98
99module_init(mga_init);
100module_exit(mga_exit);
101
102MODULE_AUTHOR(DRIVER_AUTHOR);
103MODULE_DESCRIPTION(DRIVER_DESC);
104MODULE_LICENSE("GPL and additional rights");
drivers/gpu/drm/mga/mga_drv.h+0−685
@@ -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
60typedef 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
77typedef 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
84typedef struct {
85 drm_mga_freelist_t *list_entry;
86 int discard;
87 int dispatched;
88} drm_mga_buf_priv_t;
89
90typedef 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
165extern const struct drm_ioctl_desc mga_ioctls[];
166extern int mga_max_ioctl;
167
168 /* mga_dma.c */
169extern int mga_dma_bootstrap(struct drm_device *dev, void *data,
170 struct drm_file *file_priv);
171extern int mga_dma_init(struct drm_device *dev, void *data,
172 struct drm_file *file_priv);
173extern int mga_getparam(struct drm_device *dev, void *data,
174 struct drm_file *file_priv);
175extern int mga_dma_flush(struct drm_device *dev, void *data,
176 struct drm_file *file_priv);
177extern int mga_dma_reset(struct drm_device *dev, void *data,
178 struct drm_file *file_priv);
179extern int mga_dma_buffers(struct drm_device *dev, void *data,
180 struct drm_file *file_priv);
181extern int mga_driver_load(struct drm_device *dev, unsigned long flags);
182extern void mga_driver_unload(struct drm_device *dev);
183extern void mga_driver_lastclose(struct drm_device *dev);
184extern int mga_driver_dma_quiescent(struct drm_device *dev);
185
186extern int mga_do_wait_for_idle(drm_mga_private_t *dev_priv);
187
188extern void mga_do_dma_flush(drm_mga_private_t *dev_priv);
189extern void mga_do_dma_wrap_start(drm_mga_private_t *dev_priv);
190extern void mga_do_dma_wrap_end(drm_mga_private_t *dev_priv);
191
192extern int mga_freelist_put(struct drm_device *dev, struct drm_buf *buf);
193
194 /* mga_warp.c */
195extern int mga_warp_install_microcode(drm_mga_private_t *dev_priv);
196extern int mga_warp_init(drm_mga_private_t *dev_priv);
197
198 /* mga_irq.c */
199extern int mga_enable_vblank(struct drm_device *dev, unsigned int pipe);
200extern void mga_disable_vblank(struct drm_device *dev, unsigned int pipe);
201extern u32 mga_get_vblank_counter(struct drm_device *dev, unsigned int pipe);
202extern void mga_driver_fence_wait(struct drm_device *dev, unsigned int *sequence);
203extern int mga_driver_vblank_wait(struct drm_device *dev, unsigned int *sequence);
204extern irqreturn_t mga_driver_irq_handler(int irq, void *arg);
205extern void mga_driver_irq_preinstall(struct drm_device *dev);
206extern int mga_driver_irq_postinstall(struct drm_device *dev);
207extern void mga_driver_irq_uninstall(struct drm_device *dev);
208extern 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) \
237do { \
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) \
247do { \
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) \
261do { \
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) \
283do { \
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() \
294do { \
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() \
304do { \
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() \
312do { \
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) \
331do { \
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) \
339do { \
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) \
355do { \
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) \
365do { \
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 */
679static __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
drivers/gpu/drm/mga/mga_ioc32.c+0−197
@@ -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
38typedef 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
61static 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
85typedef struct drm_mga_getparam32 {
86 int param;
87 u32 value;
88} drm_mga_getparam32_t;
89
90static 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
104typedef 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
114static 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
152static 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 */
171long 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}
drivers/gpu/drm/mga/mga_irq.c+0−169
@@ -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
36u32 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
48irqreturn_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
89int 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
104void 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
119void 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
136void 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
146int 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
159void 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}
drivers/gpu/drm/mga/mga_state.c+0−1099
@@ -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
41static 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
66static __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
89static __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
116static __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
144static __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
184static __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
223static __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
250static __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
327static 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
348static 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 */
381static 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 */
400static 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
417static 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
446static 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
465static 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
480static 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
568static 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
622static 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
669static 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 */
718static 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
766static 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
827static 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
849static 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
870static 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
905static 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
940static 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
978static 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
1004int 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
1037static 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
1066static int mga_wait_fence(struct drm_device *dev, void *data, struct drm_file *
1067file_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
1083const 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
1099int mga_max_ioctl = ARRAY_SIZE(mga_ioctls);
drivers/gpu/drm/mga/mga_warp.c+0−167
@@ -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
40MODULE_FIRMWARE(FIRMWARE_G200);
41MODULE_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
47int 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
127out:
128 release_firmware(fw);
129 return rc;
130}
131
132#define WMISC_EXPECTED (MGA_WUCODECACHE_ENABLE | MGA_WMASTER_ENABLE)
133
134int 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}
include/uapi/drm/mga_drm.h+0−429
@@ -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)
41extern "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 */
133typedef 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 */
150typedef struct {
151 unsigned int pitch;
152} drm_mga_server_regs_t;
153
154/* Setup registers for each texture unit
155 */
156typedef 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 */
172typedef struct {
173 unsigned int head; /* Position of head pointer */
174 unsigned int wrap; /* Primary DMA wrap count */
175} drm_mga_age_t;
176
177typedef 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
268typedef struct _drm_mga_warp_index {
269 int installed;
270 unsigned long phys_addr;
271 int size;
272} drm_mga_warp_index_t;
273
274typedef 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
307typedef 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
369typedef 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
377typedef 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
383typedef 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
390typedef struct drm_mga_iload {
391 int idx;
392 unsigned int dstorg;
393 unsigned int length;
394} drm_mga_iload_t;
395
396typedef 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
420typedef 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

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t