aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char/drm/i915_dma.c
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2008-05-28 20:09:59 -0400
committerDave Airlie <airlied@redhat.com>2008-07-13 20:45:01 -0400
commitc0e09200dc0813972442e550a5905a132768e56c (patch)
treed38e635a30ff8b0a2b98b9d7f97cab1501f8209e /drivers/char/drm/i915_dma.c
parentbce7f793daec3e65ec5c5705d2457b81fe7b5725 (diff)
drm: reorganise drm tree to be more future proof.
With the coming of kernel based modesetting and the memory manager stuff, the everything in one directory approach was getting very ugly and starting to be unmanageable. This restructures the drm along the lines of other kernel components. It creates a drivers/gpu/drm directory and moves the hw drivers into subdirectores. It moves the includes into an include/drm, and sets up the unifdef for the userspace headers we should be exporting. Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers/char/drm/i915_dma.c')
-rw-r--r--drivers/char/drm/i915_dma.c858
1 files changed, 0 insertions, 858 deletions
diff --git a/drivers/char/drm/i915_dma.c b/drivers/char/drm/i915_dma.c
deleted file mode 100644
index 88974342933c..000000000000
--- a/drivers/char/drm/i915_dma.c
+++ /dev/null
@@ -1,858 +0,0 @@
1/* i915_dma.c -- DMA support for the I915 -*- linux-c -*-
2 */
3/*
4 * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
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
9 * "Software"), to deal in the Software without restriction, including
10 * without limitation the rights to use, copy, modify, merge, publish,
11 * distribute, sub license, and/or sell copies of the Software, and to
12 * permit persons to whom the Software is furnished to do so, subject to
13 * the following conditions:
14 *
15 * The above copyright notice and this permission notice (including the
16 * next paragraph) shall be included in all copies or substantial portions
17 * of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
22 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
23 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
24 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
25 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 *
27 */
28
29#include "drmP.h"
30#include "drm.h"
31#include "i915_drm.h"
32#include "i915_drv.h"
33
34/* Really want an OS-independent resettable timer. Would like to have
35 * this loop run for (eg) 3 sec, but have the timer reset every time
36 * the head pointer changes, so that EBUSY only happens if the ring
37 * actually stalls for (eg) 3 seconds.
38 */
39int i915_wait_ring(struct drm_device * dev, int n, const char *caller)
40{
41 drm_i915_private_t *dev_priv = dev->dev_private;
42 drm_i915_ring_buffer_t *ring = &(dev_priv->ring);
43 u32 last_head = I915_READ(LP_RING + RING_HEAD) & HEAD_ADDR;
44 int i;
45
46 for (i = 0; i < 10000; i++) {
47 ring->head = I915_READ(LP_RING + RING_HEAD) & HEAD_ADDR;
48 ring->space = ring->head - (ring->tail + 8);
49 if (ring->space < 0)
50 ring->space += ring->Size;
51 if (ring->space >= n)
52 return 0;
53
54 dev_priv->sarea_priv->perf_boxes |= I915_BOX_WAIT;
55
56 if (ring->head != last_head)
57 i = 0;
58
59 last_head = ring->head;
60 }
61
62 return -EBUSY;
63}
64
65void i915_kernel_lost_context(struct drm_device * dev)
66{
67 drm_i915_private_t *dev_priv = dev->dev_private;
68 drm_i915_ring_buffer_t *ring = &(dev_priv->ring);
69
70 ring->head = I915_READ(LP_RING + RING_HEAD) & HEAD_ADDR;
71 ring->tail = I915_READ(LP_RING + RING_TAIL) & TAIL_ADDR;
72 ring->space = ring->head - (ring->tail + 8);
73 if (ring->space < 0)
74 ring->space += ring->Size;
75
76 if (ring->head == ring->tail)
77 dev_priv->sarea_priv->perf_boxes |= I915_BOX_RING_EMPTY;
78}
79
80static int i915_dma_cleanup(struct drm_device * dev)
81{
82 drm_i915_private_t *dev_priv = dev->dev_private;
83 /* Make sure interrupts are disabled here because the uninstall ioctl
84 * may not have been called from userspace and after dev_private
85 * is freed, it's too late.
86 */
87 if (dev->irq)
88 drm_irq_uninstall(dev);
89
90 if (dev_priv->ring.virtual_start) {
91 drm_core_ioremapfree(&dev_priv->ring.map, dev);
92 dev_priv->ring.virtual_start = 0;
93 dev_priv->ring.map.handle = 0;
94 dev_priv->ring.map.size = 0;
95 }
96
97 if (dev_priv->status_page_dmah) {
98 drm_pci_free(dev, dev_priv->status_page_dmah);
99 dev_priv->status_page_dmah = NULL;
100 /* Need to rewrite hardware status page */
101 I915_WRITE(0x02080, 0x1ffff000);
102 }
103
104 if (dev_priv->status_gfx_addr) {
105 dev_priv->status_gfx_addr = 0;
106 drm_core_ioremapfree(&dev_priv->hws_map, dev);
107 I915_WRITE(0x2080, 0x1ffff000);
108 }
109
110 return 0;
111}
112
113static int i915_initialize(struct drm_device * dev, drm_i915_init_t * init)
114{
115 drm_i915_private_t *dev_priv = dev->dev_private;
116
117 dev_priv->sarea = drm_getsarea(dev);
118 if (!dev_priv->sarea) {
119 DRM_ERROR("can not find sarea!\n");
120 i915_dma_cleanup(dev);
121 return -EINVAL;
122 }
123
124 dev_priv->mmio_map = drm_core_findmap(dev, init->mmio_offset);
125 if (!dev_priv->mmio_map) {
126 i915_dma_cleanup(dev);
127 DRM_ERROR("can not find mmio map!\n");
128 return -EINVAL;
129 }
130
131 dev_priv->sarea_priv = (drm_i915_sarea_t *)
132 ((u8 *) dev_priv->sarea->handle + init->sarea_priv_offset);
133
134 dev_priv->ring.Start = init->ring_start;
135 dev_priv->ring.End = init->ring_end;
136 dev_priv->ring.Size = init->ring_size;
137 dev_priv->ring.tail_mask = dev_priv->ring.Size - 1;
138
139 dev_priv->ring.map.offset = init->ring_start;
140 dev_priv->ring.map.size = init->ring_size;
141 dev_priv->ring.map.type = 0;
142 dev_priv->ring.map.flags = 0;
143 dev_priv->ring.map.mtrr = 0;
144
145 drm_core_ioremap(&dev_priv->ring.map, dev);
146
147 if (dev_priv->ring.map.handle == NULL) {
148 i915_dma_cleanup(dev);
149 DRM_ERROR("can not ioremap virtual address for"
150 " ring buffer\n");
151 return -ENOMEM;
152 }
153
154 dev_priv->ring.virtual_start = dev_priv->ring.map.handle;
155
156 dev_priv->cpp = init->cpp;
157 dev_priv->back_offset = init->back_offset;
158 dev_priv->front_offset = init->front_offset;
159 dev_priv->current_page = 0;
160 dev_priv->sarea_priv->pf_current_page = dev_priv->current_page;
161
162 /* We are using separate values as placeholders for mechanisms for
163 * private backbuffer/depthbuffer usage.
164 */
165 dev_priv->use_mi_batchbuffer_start = 0;
166 if (IS_I965G(dev)) /* 965 doesn't support older method */
167 dev_priv->use_mi_batchbuffer_start = 1;
168
169 /* Allow hardware batchbuffers unless told otherwise.
170 */
171 dev_priv->allow_batchbuffer = 1;
172
173 /* Program Hardware Status Page */
174 if (!I915_NEED_GFX_HWS(dev)) {
175 dev_priv->status_page_dmah =
176 drm_pci_alloc(dev, PAGE_SIZE, PAGE_SIZE, 0xffffffff);
177
178 if (!dev_priv->status_page_dmah) {
179 i915_dma_cleanup(dev);
180 DRM_ERROR("Can not allocate hardware status page\n");
181 return -ENOMEM;
182 }
183 dev_priv->hw_status_page = dev_priv->status_page_dmah->vaddr;
184 dev_priv->dma_status_page = dev_priv->status_page_dmah->busaddr;
185
186 memset(dev_priv->hw_status_page, 0, PAGE_SIZE);
187 I915_WRITE(0x02080, dev_priv->dma_status_page);
188 }
189 DRM_DEBUG("Enabled hardware status page\n");
190 return 0;
191}
192
193static int i915_dma_resume(struct drm_device * dev)
194{
195 drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
196
197 DRM_DEBUG("%s\n", __func__);
198
199 if (!dev_priv->sarea) {
200 DRM_ERROR("can not find sarea!\n");
201 return -EINVAL;
202 }
203
204 if (!dev_priv->mmio_map) {
205 DRM_ERROR("can not find mmio map!\n");
206 return -EINVAL;
207 }
208
209 if (dev_priv->ring.map.handle == NULL) {
210 DRM_ERROR("can not ioremap virtual address for"
211 " ring buffer\n");
212 return -ENOMEM;
213 }
214
215 /* Program Hardware Status Page */
216 if (!dev_priv->hw_status_page) {
217 DRM_ERROR("Can not find hardware status page\n");
218 return -EINVAL;
219 }
220 DRM_DEBUG("hw status page @ %p\n", dev_priv->hw_status_page);
221
222 if (dev_priv->status_gfx_addr != 0)
223 I915_WRITE(0x02080, dev_priv->status_gfx_addr);
224 else
225 I915_WRITE(0x02080, dev_priv->dma_status_page);
226 DRM_DEBUG("Enabled hardware status page\n");
227
228 return 0;
229}
230
231static int i915_dma_init(struct drm_device *dev, void *data,
232 struct drm_file *file_priv)
233{
234 drm_i915_init_t *init = data;
235 int retcode = 0;
236
237 switch (init->func) {
238 case I915_INIT_DMA:
239 retcode = i915_initialize(dev, init);
240 break;
241 case I915_CLEANUP_DMA:
242 retcode = i915_dma_cleanup(dev);
243 break;
244 case I915_RESUME_DMA:
245 retcode = i915_dma_resume(dev);
246 break;
247 default:
248 retcode = -EINVAL;
249 break;
250 }
251
252 return retcode;
253}
254
255/* Implement basically the same security restrictions as hardware does
256 * for MI_BATCH_NON_SECURE. These can be made stricter at any time.
257 *
258 * Most of the calculations below involve calculating the size of a
259 * particular instruction. It's important to get the size right as
260 * that tells us where the next instruction to check is. Any illegal
261 * instruction detected will be given a size of zero, which is a
262 * signal to abort the rest of the buffer.
263 */
264static int do_validate_cmd(int cmd)
265{
266 switch (((cmd >> 29) & 0x7)) {
267 case 0x0:
268 switch ((cmd >> 23) & 0x3f) {
269 case 0x0:
270 return 1; /* MI_NOOP */
271 case 0x4:
272 return 1; /* MI_FLUSH */
273 default:
274 return 0; /* disallow everything else */
275 }
276 break;
277 case 0x1:
278 return 0; /* reserved */
279 case 0x2:
280 return (cmd & 0xff) + 2; /* 2d commands */
281 case 0x3:
282 if (((cmd >> 24) & 0x1f) <= 0x18)
283 return 1;
284
285 switch ((cmd >> 24) & 0x1f) {
286 case 0x1c:
287 return 1;
288 case 0x1d:
289 switch ((cmd >> 16) & 0xff) {
290 case 0x3:
291 return (cmd & 0x1f) + 2;
292 case 0x4:
293 return (cmd & 0xf) + 2;
294 default:
295 return (cmd & 0xffff) + 2;
296 }
297 case 0x1e:
298 if (cmd & (1 << 23))
299 return (cmd & 0xffff) + 1;
300 else
301 return 1;
302 case 0x1f:
303 if ((cmd & (1 << 23)) == 0) /* inline vertices */
304 return (cmd & 0x1ffff) + 2;
305 else if (cmd & (1 << 17)) /* indirect random */
306 if ((cmd & 0xffff) == 0)
307 return 0; /* unknown length, too hard */
308 else
309 return (((cmd & 0xffff) + 1) / 2) + 1;
310 else
311 return 2; /* indirect sequential */
312 default:
313 return 0;
314 }
315 default:
316 return 0;
317 }
318
319 return 0;
320}
321
322static int validate_cmd(int cmd)
323{
324 int ret = do_validate_cmd(cmd);
325
326/* printk("validate_cmd( %x ): %d\n", cmd, ret); */
327
328 return ret;
329}
330
331static int i915_emit_cmds(struct drm_device * dev, int __user * buffer, int dwords)
332{
333 drm_i915_private_t *dev_priv = dev->dev_private;
334 int i;
335 RING_LOCALS;
336
337 if ((dwords+1) * sizeof(int) >= dev_priv->ring.Size - 8)
338 return -EINVAL;
339
340 BEGIN_LP_RING((dwords+1)&~1);
341
342 for (i = 0; i < dwords;) {
343 int cmd, sz;
344
345 if (DRM_COPY_FROM_USER_UNCHECKED(&cmd, &buffer[i], sizeof(cmd)))
346 return -EINVAL;
347
348 if ((sz = validate_cmd(cmd)) == 0 || i + sz > dwords)
349 return -EINVAL;
350
351 OUT_RING(cmd);
352
353 while (++i, --sz) {
354 if (DRM_COPY_FROM_USER_UNCHECKED(&cmd, &buffer[i],
355 sizeof(cmd))) {
356 return -EINVAL;
357 }
358 OUT_RING(cmd);
359 }
360 }
361
362 if (dwords & 1)
363 OUT_RING(0);
364
365 ADVANCE_LP_RING();
366
367 return 0;
368}
369
370static int i915_emit_box(struct drm_device * dev,
371 struct drm_clip_rect __user * boxes,
372 int i, int DR1, int DR4)
373{
374 drm_i915_private_t *dev_priv = dev->dev_private;
375 struct drm_clip_rect box;
376 RING_LOCALS;
377
378 if (DRM_COPY_FROM_USER_UNCHECKED(&box, &boxes[i], sizeof(box))) {
379 return -EFAULT;
380 }
381
382 if (box.y2 <= box.y1 || box.x2 <= box.x1 || box.y2 <= 0 || box.x2 <= 0) {
383 DRM_ERROR("Bad box %d,%d..%d,%d\n",
384 box.x1, box.y1, box.x2, box.y2);
385 return -EINVAL;
386 }
387
388 if (IS_I965G(dev)) {
389 BEGIN_LP_RING(4);
390 OUT_RING(GFX_OP_DRAWRECT_INFO_I965);
391 OUT_RING((box.x1 & 0xffff) | (box.y1 << 16));
392 OUT_RING(((box.x2 - 1) & 0xffff) | ((box.y2 - 1) << 16));
393 OUT_RING(DR4);
394 ADVANCE_LP_RING();
395 } else {
396 BEGIN_LP_RING(6);
397 OUT_RING(GFX_OP_DRAWRECT_INFO);
398 OUT_RING(DR1);
399 OUT_RING((box.x1 & 0xffff) | (box.y1 << 16));
400 OUT_RING(((box.x2 - 1) & 0xffff) | ((box.y2 - 1) << 16));
401 OUT_RING(DR4);
402 OUT_RING(0);
403 ADVANCE_LP_RING();
404 }
405
406 return 0;
407}
408
409/* XXX: Emitting the counter should really be moved to part of the IRQ
410 * emit. For now, do it in both places:
411 */
412
413static void i915_emit_breadcrumb(struct drm_device *dev)
414{
415 drm_i915_private_t *dev_priv = dev->dev_private;
416 RING_LOCALS;
417
418 dev_priv->sarea_priv->last_enqueue = ++dev_priv->counter;
419
420 if (dev_priv->counter > 0x7FFFFFFFUL)
421 dev_priv->sarea_priv->last_enqueue = dev_priv->counter = 1;
422
423 BEGIN_LP_RING(4);
424 OUT_RING(CMD_STORE_DWORD_IDX);
425 OUT_RING(20);
426 OUT_RING(dev_priv->counter);
427 OUT_RING(0);
428 ADVANCE_LP_RING();
429}
430
431static int i915_dispatch_cmdbuffer(struct drm_device * dev,
432 drm_i915_cmdbuffer_t * cmd)
433{
434 int nbox = cmd->num_cliprects;
435 int i = 0, count, ret;
436
437 if (cmd->sz & 0x3) {
438 DRM_ERROR("alignment");
439 return -EINVAL;
440 }
441
442 i915_kernel_lost_context(dev);
443
444 count = nbox ? nbox : 1;
445
446 for (i = 0; i < count; i++) {
447 if (i < nbox) {
448 ret = i915_emit_box(dev, cmd->cliprects, i,
449 cmd->DR1, cmd->DR4);
450 if (ret)
451 return ret;
452 }
453
454 ret = i915_emit_cmds(dev, (int __user *)cmd->buf, cmd->sz / 4);
455 if (ret)
456 return ret;
457 }
458
459 i915_emit_breadcrumb(dev);
460 return 0;
461}
462
463static int i915_dispatch_batchbuffer(struct drm_device * dev,
464 drm_i915_batchbuffer_t * batch)
465{
466 drm_i915_private_t *dev_priv = dev->dev_private;
467 struct drm_clip_rect __user *boxes = batch->cliprects;
468 int nbox = batch->num_cliprects;
469 int i = 0, count;
470 RING_LOCALS;
471
472 if ((batch->start | batch->used) & 0x7) {
473 DRM_ERROR("alignment");
474 return -EINVAL;
475 }
476
477 i915_kernel_lost_context(dev);
478
479 count = nbox ? nbox : 1;
480
481 for (i = 0; i < count; i++) {
482 if (i < nbox) {
483 int ret = i915_emit_box(dev, boxes, i,
484 batch->DR1, batch->DR4);
485 if (ret)
486 return ret;
487 }
488
489 if (dev_priv->use_mi_batchbuffer_start) {
490 BEGIN_LP_RING(2);
491 if (IS_I965G(dev)) {
492 OUT_RING(MI_BATCH_BUFFER_START | (2 << 6) | MI_BATCH_NON_SECURE_I965);
493 OUT_RING(batch->start);
494 } else {
495 OUT_RING(MI_BATCH_BUFFER_START | (2 << 6));
496 OUT_RING(batch->start | MI_BATCH_NON_SECURE);
497 }
498 ADVANCE_LP_RING();
499 } else {
500 BEGIN_LP_RING(4);
501 OUT_RING(MI_BATCH_BUFFER);
502 OUT_RING(batch->start | MI_BATCH_NON_SECURE);
503 OUT_RING(batch->start + batch->used - 4);
504 OUT_RING(0);
505 ADVANCE_LP_RING();
506 }
507 }
508
509 i915_emit_breadcrumb(dev);
510
511 return 0;
512}
513
514static int i915_dispatch_flip(struct drm_device * dev)
515{
516 drm_i915_private_t *dev_priv = dev->dev_private;
517 RING_LOCALS;
518
519 DRM_DEBUG("%s: page=%d pfCurrentPage=%d\n",
520 __FUNCTION__,
521 dev_priv->current_page,
522 dev_priv->sarea_priv->pf_current_page);
523
524 i915_kernel_lost_context(dev);
525
526 BEGIN_LP_RING(2);
527 OUT_RING(INST_PARSER_CLIENT | INST_OP_FLUSH | INST_FLUSH_MAP_CACHE);
528 OUT_RING(0);
529 ADVANCE_LP_RING();
530
531 BEGIN_LP_RING(6);
532 OUT_RING(CMD_OP_DISPLAYBUFFER_INFO | ASYNC_FLIP);
533 OUT_RING(0);
534 if (dev_priv->current_page == 0) {
535 OUT_RING(dev_priv->back_offset);
536 dev_priv->current_page = 1;
537 } else {
538 OUT_RING(dev_priv->front_offset);
539 dev_priv->current_page = 0;
540 }
541 OUT_RING(0);
542 ADVANCE_LP_RING();
543
544 BEGIN_LP_RING(2);
545 OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_PLANE_A_FLIP);
546 OUT_RING(0);
547 ADVANCE_LP_RING();
548
549 dev_priv->sarea_priv->last_enqueue = dev_priv->counter++;
550
551 BEGIN_LP_RING(4);
552 OUT_RING(CMD_STORE_DWORD_IDX);
553 OUT_RING(20);
554 OUT_RING(dev_priv->counter);
555 OUT_RING(0);
556 ADVANCE_LP_RING();
557
558 dev_priv->sarea_priv->pf_current_page = dev_priv->current_page;
559 return 0;
560}
561
562static int i915_quiescent(struct drm_device * dev)
563{
564 drm_i915_private_t *dev_priv = dev->dev_private;
565
566 i915_kernel_lost_context(dev);
567 return i915_wait_ring(dev, dev_priv->ring.Size - 8, __func__);
568}
569
570static int i915_flush_ioctl(struct drm_device *dev, void *data,
571 struct drm_file *file_priv)
572{
573 LOCK_TEST_WITH_RETURN(dev, file_priv);
574
575 return i915_quiescent(dev);
576}
577
578static int i915_batchbuffer(struct drm_device *dev, void *data,
579 struct drm_file *file_priv)
580{
581 drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
582 u32 *hw_status = dev_priv->hw_status_page;
583 drm_i915_sarea_t *sarea_priv = (drm_i915_sarea_t *)
584 dev_priv->sarea_priv;
585 drm_i915_batchbuffer_t *batch = data;
586 int ret;
587
588 if (!dev_priv->allow_batchbuffer) {
589 DRM_ERROR("Batchbuffer ioctl disabled\n");
590 return -EINVAL;
591 }
592
593 DRM_DEBUG("i915 batchbuffer, start %x used %d cliprects %d\n",
594 batch->start, batch->used, batch->num_cliprects);
595
596 LOCK_TEST_WITH_RETURN(dev, file_priv);
597
598 if (batch->num_cliprects && DRM_VERIFYAREA_READ(batch->cliprects,
599 batch->num_cliprects *
600 sizeof(struct drm_clip_rect)))
601 return -EFAULT;
602
603 ret = i915_dispatch_batchbuffer(dev, batch);
604
605 sarea_priv->last_dispatch = (int)hw_status[5];
606 return ret;
607}
608
609static int i915_cmdbuffer(struct drm_device *dev, void *data,
610 struct drm_file *file_priv)
611{
612 drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
613 u32 *hw_status = dev_priv->hw_status_page;
614 drm_i915_sarea_t *sarea_priv = (drm_i915_sarea_t *)
615 dev_priv->sarea_priv;
616 drm_i915_cmdbuffer_t *cmdbuf = data;
617 int ret;
618
619 DRM_DEBUG("i915 cmdbuffer, buf %p sz %d cliprects %d\n",
620 cmdbuf->buf, cmdbuf->sz, cmdbuf->num_cliprects);
621
622 LOCK_TEST_WITH_RETURN(dev, file_priv);
623
624 if (cmdbuf->num_cliprects &&
625 DRM_VERIFYAREA_READ(cmdbuf->cliprects,
626 cmdbuf->num_cliprects *
627 sizeof(struct drm_clip_rect))) {
628 DRM_ERROR("Fault accessing cliprects\n");
629 return -EFAULT;
630 }
631
632 ret = i915_dispatch_cmdbuffer(dev, cmdbuf);
633 if (ret) {
634 DRM_ERROR("i915_dispatch_cmdbuffer failed\n");
635 return ret;
636 }
637
638 sarea_priv->last_dispatch = (int)hw_status[5];
639 return 0;
640}
641
642static int i915_flip_bufs(struct drm_device *dev, void *data,
643 struct drm_file *file_priv)
644{
645 DRM_DEBUG("%s\n", __FUNCTION__);
646
647 LOCK_TEST_WITH_RETURN(dev, file_priv);
648
649 return i915_dispatch_flip(dev);
650}
651
652static int i915_getparam(struct drm_device *dev, void *data,
653 struct drm_file *file_priv)
654{
655 drm_i915_private_t *dev_priv = dev->dev_private;
656 drm_i915_getparam_t *param = data;
657 int value;
658
659 if (!dev_priv) {
660 DRM_ERROR("called with no initialization\n");
661 return -EINVAL;
662 }
663
664 switch (param->param) {
665 case I915_PARAM_IRQ_ACTIVE:
666 value = dev->irq ? 1 : 0;
667 break;
668 case I915_PARAM_ALLOW_BATCHBUFFER:
669 value = dev_priv->allow_batchbuffer ? 1 : 0;
670 break;
671 case I915_PARAM_LAST_DISPATCH:
672 value = READ_BREADCRUMB(dev_priv);
673 break;
674 default:
675 DRM_ERROR("Unknown parameter %d\n", param->param);
676 return -EINVAL;
677 }
678
679 if (DRM_COPY_TO_USER(param->value, &value, sizeof(int))) {
680 DRM_ERROR("DRM_COPY_TO_USER failed\n");
681 return -EFAULT;
682 }
683
684 return 0;
685}
686
687static int i915_setparam(struct drm_device *dev, void *data,
688 struct drm_file *file_priv)
689{
690 drm_i915_private_t *dev_priv = dev->dev_private;
691 drm_i915_setparam_t *param = data;
692
693 if (!dev_priv) {
694 DRM_ERROR("called with no initialization\n");
695 return -EINVAL;
696 }
697
698 switch (param->param) {
699 case I915_SETPARAM_USE_MI_BATCHBUFFER_START:
700 if (!IS_I965G(dev))
701 dev_priv->use_mi_batchbuffer_start = param->value;
702 break;
703 case I915_SETPARAM_TEX_LRU_LOG_GRANULARITY:
704 dev_priv->tex_lru_log_granularity = param->value;
705 break;
706 case I915_SETPARAM_ALLOW_BATCHBUFFER:
707 dev_priv->allow_batchbuffer = param->value;
708 break;
709 default:
710 DRM_ERROR("unknown parameter %d\n", param->param);
711 return -EINVAL;
712 }
713
714 return 0;
715}
716
717static int i915_set_status_page(struct drm_device *dev, void *data,
718 struct drm_file *file_priv)
719{
720 drm_i915_private_t *dev_priv = dev->dev_private;
721 drm_i915_hws_addr_t *hws = data;
722
723 if (!I915_NEED_GFX_HWS(dev))
724 return -EINVAL;
725
726 if (!dev_priv) {
727 DRM_ERROR("called with no initialization\n");
728 return -EINVAL;
729 }
730
731 printk(KERN_DEBUG "set status page addr 0x%08x\n", (u32)hws->addr);
732
733 dev_priv->status_gfx_addr = hws->addr & (0x1ffff<<12);
734
735 dev_priv->hws_map.offset = dev->agp->base + hws->addr;
736 dev_priv->hws_map.size = 4*1024;
737 dev_priv->hws_map.type = 0;
738 dev_priv->hws_map.flags = 0;
739 dev_priv->hws_map.mtrr = 0;
740
741 drm_core_ioremap(&dev_priv->hws_map, dev);
742 if (dev_priv->hws_map.handle == NULL) {
743 i915_dma_cleanup(dev);
744 dev_priv->status_gfx_addr = 0;
745 DRM_ERROR("can not ioremap virtual address for"
746 " G33 hw status page\n");
747 return -ENOMEM;
748 }
749 dev_priv->hw_status_page = dev_priv->hws_map.handle;
750
751 memset(dev_priv->hw_status_page, 0, PAGE_SIZE);
752 I915_WRITE(0x02080, dev_priv->status_gfx_addr);
753 DRM_DEBUG("load hws 0x2080 with gfx mem 0x%x\n",
754 dev_priv->status_gfx_addr);
755 DRM_DEBUG("load hws at %p\n", dev_priv->hw_status_page);
756 return 0;
757}
758
759int i915_driver_load(struct drm_device *dev, unsigned long flags)
760{
761 struct drm_i915_private *dev_priv = dev->dev_private;
762 unsigned long base, size;
763 int ret = 0, mmio_bar = IS_I9XX(dev) ? 0 : 1;
764
765 /* i915 has 4 more counters */
766 dev->counters += 4;
767 dev->types[6] = _DRM_STAT_IRQ;
768 dev->types[7] = _DRM_STAT_PRIMARY;
769 dev->types[8] = _DRM_STAT_SECONDARY;
770 dev->types[9] = _DRM_STAT_DMA;
771
772 dev_priv = drm_alloc(sizeof(drm_i915_private_t), DRM_MEM_DRIVER);
773 if (dev_priv == NULL)
774 return -ENOMEM;
775
776 memset(dev_priv, 0, sizeof(drm_i915_private_t));
777
778 dev->dev_private = (void *)dev_priv;
779
780 /* Add register map (needed for suspend/resume) */
781 base = drm_get_resource_start(dev, mmio_bar);
782 size = drm_get_resource_len(dev, mmio_bar);
783
784 ret = drm_addmap(dev, base, size, _DRM_REGISTERS,
785 _DRM_KERNEL | _DRM_DRIVER,
786 &dev_priv->mmio_map);
787 return ret;
788}
789
790int i915_driver_unload(struct drm_device *dev)
791{
792 struct drm_i915_private *dev_priv = dev->dev_private;
793
794 if (dev_priv->mmio_map)
795 drm_rmmap(dev, dev_priv->mmio_map);
796
797 drm_free(dev->dev_private, sizeof(drm_i915_private_t),
798 DRM_MEM_DRIVER);
799
800 return 0;
801}
802
803void i915_driver_lastclose(struct drm_device * dev)
804{
805 drm_i915_private_t *dev_priv = dev->dev_private;
806
807 if (!dev_priv)
808 return;
809
810 if (dev_priv->agp_heap)
811 i915_mem_takedown(&(dev_priv->agp_heap));
812
813 i915_dma_cleanup(dev);
814}
815
816void i915_driver_preclose(struct drm_device * dev, struct drm_file *file_priv)
817{
818 drm_i915_private_t *dev_priv = dev->dev_private;
819 i915_mem_release(dev, file_priv, dev_priv->agp_heap);
820}
821
822struct drm_ioctl_desc i915_ioctls[] = {
823 DRM_IOCTL_DEF(DRM_I915_INIT, i915_dma_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
824 DRM_IOCTL_DEF(DRM_I915_FLUSH, i915_flush_ioctl, DRM_AUTH),
825 DRM_IOCTL_DEF(DRM_I915_FLIP, i915_flip_bufs, DRM_AUTH),
826 DRM_IOCTL_DEF(DRM_I915_BATCHBUFFER, i915_batchbuffer, DRM_AUTH),
827 DRM_IOCTL_DEF(DRM_I915_IRQ_EMIT, i915_irq_emit, DRM_AUTH),
828 DRM_IOCTL_DEF(DRM_I915_IRQ_WAIT, i915_irq_wait, DRM_AUTH),
829 DRM_IOCTL_DEF(DRM_I915_GETPARAM, i915_getparam, DRM_AUTH),
830 DRM_IOCTL_DEF(DRM_I915_SETPARAM, i915_setparam, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
831 DRM_IOCTL_DEF(DRM_I915_ALLOC, i915_mem_alloc, DRM_AUTH),
832 DRM_IOCTL_DEF(DRM_I915_FREE, i915_mem_free, DRM_AUTH),
833 DRM_IOCTL_DEF(DRM_I915_INIT_HEAP, i915_mem_init_heap, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
834 DRM_IOCTL_DEF(DRM_I915_CMDBUFFER, i915_cmdbuffer, DRM_AUTH),
835 DRM_IOCTL_DEF(DRM_I915_DESTROY_HEAP, i915_mem_destroy_heap, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY ),
836 DRM_IOCTL_DEF(DRM_I915_SET_VBLANK_PIPE, i915_vblank_pipe_set, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY ),
837 DRM_IOCTL_DEF(DRM_I915_GET_VBLANK_PIPE, i915_vblank_pipe_get, DRM_AUTH ),
838 DRM_IOCTL_DEF(DRM_I915_VBLANK_SWAP, i915_vblank_swap, DRM_AUTH),
839 DRM_IOCTL_DEF(DRM_I915_HWS_ADDR, i915_set_status_page, DRM_AUTH),
840};
841
842int i915_max_ioctl = DRM_ARRAY_SIZE(i915_ioctls);
843
844/**
845 * Determine if the device really is AGP or not.
846 *
847 * All Intel graphics chipsets are treated as AGP, even if they are really
848 * PCI-e.
849 *
850 * \param dev The device to be tested.
851 *
852 * \returns
853 * A value of 1 is always retured to indictate every i9x5 is AGP.
854 */
855int i915_driver_device_is_agp(struct drm_device * dev)
856{
857 return 1;
858}