1/* i810_dma.c -- DMA support for the i810 -*- 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 * Authors: Rickard E. (Rik) Faith <faith@valinux.com>
28 *	    Jeff Hartmann <jhartmann@valinux.com>
29 *          Keith Whitwell <keith@tungstengraphics.com>
30 *
31 */
32
33#include "drmP.h"
34#include "drm.h"
35#include "i810_drm.h"
36#include "i810_drv.h"
37#include <linux/interrupt.h>	/* For task queue support */
38#include <linux/delay.h>
39#include <linux/slab.h>
40#include <linux/pagemap.h>
41
42#define I810_BUF_FREE		2
43#define I810_BUF_CLIENT		1
44#define I810_BUF_HARDWARE	0
45
46#define I810_BUF_UNMAPPED 0
47#define I810_BUF_MAPPED   1
48
49static struct drm_buf *i810_freelist_get(struct drm_device * dev)
50{
51	struct drm_device_dma *dma = dev->dma;
52	int i;
53	int used;
54
55	/* Linear search might not be the best solution */
56
57	for (i = 0; i < dma->buf_count; i++) {
58		struct drm_buf *buf = dma->buflist[i];
59		drm_i810_buf_priv_t *buf_priv = buf->dev_private;
60		/* In use is already a pointer */
61		used = cmpxchg(buf_priv->in_use, I810_BUF_FREE,
62			       I810_BUF_CLIENT);
63		if (used == I810_BUF_FREE)
64			return buf;
65	}
66	return NULL;
67}
68
69/* This should only be called if the buffer is not sent to the hardware
70 * yet, the hardware updates in use for us once its on the ring buffer.
71 */
72
73static int i810_freelist_put(struct drm_device *dev, struct drm_buf *buf)
74{
75	drm_i810_buf_priv_t *buf_priv = buf->dev_private;
76	int used;
77
78	/* In use is already a pointer */
79	used = cmpxchg(buf_priv->in_use, I810_BUF_CLIENT, I810_BUF_FREE);
80	if (used != I810_BUF_CLIENT) {
81		DRM_ERROR("Freeing buffer thats not in use : %d\n", buf->idx);
82		return -EINVAL;
83	}
84
85	return 0;
86}
87
88static int i810_mmap_buffers(struct file *filp, struct vm_area_struct *vma)
89{
90	struct drm_file *priv = filp->private_data;
91	struct drm_device *dev;
92	drm_i810_private_t *dev_priv;
93	struct drm_buf *buf;
94	drm_i810_buf_priv_t *buf_priv;
95
96	dev = priv->minor->dev;
97	dev_priv = dev->dev_private;
98	buf = dev_priv->mmap_buffer;
99	buf_priv = buf->dev_private;
100
101	vma->vm_flags |= (VM_IO | VM_DONTCOPY);
102	vma->vm_file = filp;
103
104	buf_priv->currently_mapped = I810_BUF_MAPPED;
105
106	if (io_remap_pfn_range(vma, vma->vm_start,
107			       vma->vm_pgoff,
108			       vma->vm_end - vma->vm_start, vma->vm_page_prot))
109		return -EAGAIN;
110	return 0;
111}
112
113static const struct file_operations i810_buffer_fops = {
114	.open = drm_open,
115	.release = drm_release,
116	.unlocked_ioctl = drm_ioctl,
117	.mmap = i810_mmap_buffers,
118	.fasync = drm_fasync,
119	.llseek = noop_llseek,
120};
121
122static int i810_map_buffer(struct drm_buf *buf, struct drm_file *file_priv)
123{
124	struct drm_device *dev = file_priv->minor->dev;
125	drm_i810_buf_priv_t *buf_priv = buf->dev_private;
126	drm_i810_private_t *dev_priv = dev->dev_private;
127	const struct file_operations *old_fops;
128	int retcode = 0;
129
130	if (buf_priv->currently_mapped == I810_BUF_MAPPED)
131		return -EINVAL;
132
133	down_write(&current->mm->mmap_sem);
134	old_fops = file_priv->filp->f_op;
135	file_priv->filp->f_op = &i810_buffer_fops;
136	dev_priv->mmap_buffer = buf;
137	buf_priv->virtual = (void *)do_mmap(file_priv->filp, 0, buf->total,
138					    PROT_READ | PROT_WRITE,
139					    MAP_SHARED, buf->bus_address);
140	dev_priv->mmap_buffer = NULL;
141	file_priv->filp->f_op = old_fops;
142	if (IS_ERR(buf_priv->virtual)) {
143		/* Real error */
144		DRM_ERROR("mmap error\n");
145		retcode = PTR_ERR(buf_priv->virtual);
146		buf_priv->virtual = NULL;
147	}
148	up_write(&current->mm->mmap_sem);
149
150	return retcode;
151}
152
153static int i810_unmap_buffer(struct drm_buf *buf)
154{
155	drm_i810_buf_priv_t *buf_priv = buf->dev_private;
156	int retcode = 0;
157
158	if (buf_priv->currently_mapped != I810_BUF_MAPPED)
159		return -EINVAL;
160
161	down_write(&current->mm->mmap_sem);
162	retcode = do_munmap(current->mm,
163			    (unsigned long)buf_priv->virtual,
164			    (size_t) buf->total);
165	up_write(&current->mm->mmap_sem);
166
167	buf_priv->currently_mapped = I810_BUF_UNMAPPED;
168	buf_priv->virtual = NULL;
169
170	return retcode;
171}
172
173static int i810_dma_get_buffer(struct drm_device *dev, drm_i810_dma_t *d,
174			       struct drm_file *file_priv)
175{
176	struct drm_buf *buf;
177	drm_i810_buf_priv_t *buf_priv;
178	int retcode = 0;
179
180	buf = i810_freelist_get(dev);
181	if (!buf) {
182		retcode = -ENOMEM;
183		DRM_DEBUG("retcode=%d\n", retcode);
184		return retcode;
185	}
186
187	retcode = i810_map_buffer(buf, file_priv);
188	if (retcode) {
189		i810_freelist_put(dev, buf);
190		DRM_ERROR("mapbuf failed, retcode %d\n", retcode);
191		return retcode;
192	}
193	buf->file_priv = file_priv;
194	buf_priv = buf->dev_private;
195	d->granted = 1;
196	d->request_idx = buf->idx;
197	d->request_size = buf->total;
198	d->virtual = buf_priv->virtual;
199
200	return retcode;
201}
202
203static int i810_dma_cleanup(struct drm_device *dev)
204{
205	struct drm_device_dma *dma = dev->dma;
206
207	/* Make sure interrupts are disabled here because the uninstall ioctl
208	 * may not have been called from userspace and after dev_private
209	 * is freed, it's too late.
210	 */
211	if (drm_core_check_feature(dev, DRIVER_HAVE_IRQ) && dev->irq_enabled)
212		drm_irq_uninstall(dev);
213
214	if (dev->dev_private) {
215		int i;
216		drm_i810_private_t *dev_priv =
217		    (drm_i810_private_t *) dev->dev_private;
218
219		if (dev_priv->ring.virtual_start)
220			drm_core_ioremapfree(&dev_priv->ring.map, dev);
221		if (dev_priv->hw_status_page) {
222			pci_free_consistent(dev->pdev, PAGE_SIZE,
223					    dev_priv->hw_status_page,
224					    dev_priv->dma_status_page);
225		}
226		kfree(dev->dev_private);
227		dev->dev_private = NULL;
228
229		for (i = 0; i < dma->buf_count; i++) {
230			struct drm_buf *buf = dma->buflist[i];
231			drm_i810_buf_priv_t *buf_priv = buf->dev_private;
232
233			if (buf_priv->kernel_virtual && buf->total)
234				drm_core_ioremapfree(&buf_priv->map, dev);
235		}
236	}
237	return 0;
238}
239
240static int i810_wait_ring(struct drm_device *dev, int n)
241{
242	drm_i810_private_t *dev_priv = dev->dev_private;
243	drm_i810_ring_buffer_t *ring = &(dev_priv->ring);
244	int iters = 0;
245	unsigned long end;
246	unsigned int last_head = I810_READ(LP_RING + RING_HEAD) & HEAD_ADDR;
247
248	end = jiffies + (HZ * 3);
249	while (ring->space < n) {
250		ring->head = I810_READ(LP_RING + RING_HEAD) & HEAD_ADDR;
251		ring->space = ring->head - (ring->tail + 8);
252		if (ring->space < 0)
253			ring->space += ring->Size;
254
255		if (ring->head != last_head) {
256			end = jiffies + (HZ * 3);
257			last_head = ring->head;
258		}
259
260		iters++;
261		if (time_before(end, jiffies)) {
262			DRM_ERROR("space: %d wanted %d\n", ring->space, n);
263			DRM_ERROR("lockup\n");
264			goto out_wait_ring;
265		}
266		udelay(1);
267	}
268
269out_wait_ring:
270	return iters;
271}
272
273static void i810_kernel_lost_context(struct drm_device *dev)
274{
275	drm_i810_private_t *dev_priv = dev->dev_private;
276	drm_i810_ring_buffer_t *ring = &(dev_priv->ring);
277
278	ring->head = I810_READ(LP_RING + RING_HEAD) & HEAD_ADDR;
279	ring->tail = I810_READ(LP_RING + RING_TAIL);
280	ring->space = ring->head - (ring->tail + 8);
281	if (ring->space < 0)
282		ring->space += ring->Size;
283}
284
285static int i810_freelist_init(struct drm_device *dev, drm_i810_private_t *dev_priv)
286{
287	struct drm_device_dma *dma = dev->dma;
288	int my_idx = 24;
289	u32 *hw_status = (u32 *) (dev_priv->hw_status_page + my_idx);
290	int i;
291
292	if (dma->buf_count > 1019) {
293		/* Not enough space in the status page for the freelist */
294		return -EINVAL;
295	}
296
297	for (i = 0; i < dma->buf_count; i++) {
298		struct drm_buf *buf = dma->buflist[i];
299		drm_i810_buf_priv_t *buf_priv = buf->dev_private;
300
301		buf_priv->in_use = hw_status++;
302		buf_priv->my_use_idx = my_idx;
303		my_idx += 4;
304
305		*buf_priv->in_use = I810_BUF_FREE;
306
307		buf_priv->map.offset = buf->bus_address;
308		buf_priv->map.size = buf->total;
309		buf_priv->map.type = _DRM_AGP;
310		buf_priv->map.flags = 0;
311		buf_priv->map.mtrr = 0;
312
313		drm_core_ioremap(&buf_priv->map, dev);
314		buf_priv->kernel_virtual = buf_priv->map.handle;
315
316	}
317	return 0;
318}
319
320static int i810_dma_initialize(struct drm_device *dev,
321			       drm_i810_private_t *dev_priv,
322			       drm_i810_init_t *init)
323{
324	struct drm_map_list *r_list;
325	memset(dev_priv, 0, sizeof(drm_i810_private_t));
326
327	list_for_each_entry(r_list, &dev->maplist, head) {
328		if (r_list->map &&
329		    r_list->map->type == _DRM_SHM &&
330		    r_list->map->flags & _DRM_CONTAINS_LOCK) {
331			dev_priv->sarea_map = r_list->map;
332			break;
333		}
334	}
335	if (!dev_priv->sarea_map) {
336		dev->dev_private = (void *)dev_priv;
337		i810_dma_cleanup(dev);
338		DRM_ERROR("can not find sarea!\n");
339		return -EINVAL;
340	}
341	dev_priv->mmio_map = drm_core_findmap(dev, init->mmio_offset);
342	if (!dev_priv->mmio_map) {
343		dev->dev_private = (void *)dev_priv;
344		i810_dma_cleanup(dev);
345		DRM_ERROR("can not find mmio map!\n");
346		return -EINVAL;
347	}
348	dev->agp_buffer_token = init->buffers_offset;
349	dev->agp_buffer_map = drm_core_findmap(dev, init->buffers_offset);
350	if (!dev->agp_buffer_map) {
351		dev->dev_private = (void *)dev_priv;
352		i810_dma_cleanup(dev);
353		DRM_ERROR("can not find dma buffer map!\n");
354		return -EINVAL;
355	}
356
357	dev_priv->sarea_priv = (drm_i810_sarea_t *)
358	    ((u8 *) dev_priv->sarea_map->handle + init->sarea_priv_offset);
359
360	dev_priv->ring.Start = init->ring_start;
361	dev_priv->ring.End = init->ring_end;
362	dev_priv->ring.Size = init->ring_size;
363
364	dev_priv->ring.map.offset = dev->agp->base + init->ring_start;
365	dev_priv->ring.map.size = init->ring_size;
366	dev_priv->ring.map.type = _DRM_AGP;
367	dev_priv->ring.map.flags = 0;
368	dev_priv->ring.map.mtrr = 0;
369
370	drm_core_ioremap(&dev_priv->ring.map, dev);
371
372	if (dev_priv->ring.map.handle == NULL) {
373		dev->dev_private = (void *)dev_priv;
374		i810_dma_cleanup(dev);
375		DRM_ERROR("can not ioremap virtual address for"
376			  " ring buffer\n");
377		return -ENOMEM;
378	}
379
380	dev_priv->ring.virtual_start = dev_priv->ring.map.handle;
381
382	dev_priv->ring.tail_mask = dev_priv->ring.Size - 1;
383
384	dev_priv->w = init->w;
385	dev_priv->h = init->h;
386	dev_priv->pitch = init->pitch;
387	dev_priv->back_offset = init->back_offset;
388	dev_priv->depth_offset = init->depth_offset;
389	dev_priv->front_offset = init->front_offset;
390
391	dev_priv->overlay_offset = init->overlay_offset;
392	dev_priv->overlay_physical = init->overlay_physical;
393
394	dev_priv->front_di1 = init->front_offset | init->pitch_bits;
395	dev_priv->back_di1 = init->back_offset | init->pitch_bits;
396	dev_priv->zi1 = init->depth_offset | init->pitch_bits;
397
398	/* Program Hardware Status Page */
399	dev_priv->hw_status_page =
400	    pci_alloc_consistent(dev->pdev, PAGE_SIZE,
401				 &dev_priv->dma_status_page);
402	if (!dev_priv->hw_status_page) {
403		dev->dev_private = (void *)dev_priv;
404		i810_dma_cleanup(dev);
405		DRM_ERROR("Can not allocate hardware status page\n");
406		return -ENOMEM;
407	}
408	memset(dev_priv->hw_status_page, 0, PAGE_SIZE);
409	DRM_DEBUG("hw status page @ %p\n", dev_priv->hw_status_page);
410
411	I810_WRITE(0x02080, dev_priv->dma_status_page);
412	DRM_DEBUG("Enabled hardware status page\n");
413
414	/* Now we need to init our freelist */
415	if (i810_freelist_init(dev, dev_priv) != 0) {
416		dev->dev_private = (void *)dev_priv;
417		i810_dma_cleanup(dev);
418		DRM_ERROR("Not enough space in the status page for"
419			  " the freelist\n");
420		return -ENOMEM;
421	}
422	dev->dev_private = (void *)dev_priv;
423
424	return 0;
425}
426
427static int i810_dma_init(struct drm_device *dev, void *data,
428			 struct drm_file *file_priv)
429{
430	drm_i810_private_t *dev_priv;
431	drm_i810_init_t *init = data;
432	int retcode = 0;
433
434	switch (init->func) {
435	case I810_INIT_DMA_1_4:
436		DRM_INFO("Using v1.4 init.\n");
437		dev_priv = kmalloc(sizeof(drm_i810_private_t), GFP_KERNEL);
438		if (dev_priv == NULL)
439			return -ENOMEM;
440		retcode = i810_dma_initialize(dev, dev_priv, init);
441		break;
442
443	case I810_CLEANUP_DMA:
444		DRM_INFO("DMA Cleanup\n");
445		retcode = i810_dma_cleanup(dev);
446		break;
447	default:
448		return -EINVAL;
449	}
450
451	return retcode;
452}
453
454/* Most efficient way to verify state for the i810 is as it is
455 * emitted.  Non-conformant state is silently dropped.
456 *
457 * Use 'volatile' & local var tmp to force the emitted values to be
458 * identical to the verified ones.
459 */
460static void i810EmitContextVerified(struct drm_device *dev,
461				    volatile unsigned int *code)
462{
463	drm_i810_private_t *dev_priv = dev->dev_private;
464	int i, j = 0;
465	unsigned int tmp;
466	RING_LOCALS;
467
468	BEGIN_LP_RING(I810_CTX_SETUP_SIZE);
469
470	OUT_RING(GFX_OP_COLOR_FACTOR);
471	OUT_RING(code[I810_CTXREG_CF1]);
472
473	OUT_RING(GFX_OP_STIPPLE);
474	OUT_RING(code[I810_CTXREG_ST1]);
475
476	for (i = 4; i < I810_CTX_SETUP_SIZE; i++) {
477		tmp = code[i];
478
479		if ((tmp & (7 << 29)) == (3 << 29) &&
480		    (tmp & (0x1f << 24)) < (0x1d << 24)) {
481			OUT_RING(tmp);
482			j++;
483		} else
484			printk("constext state dropped!!!\n");
485	}
486
487	if (j & 1)
488		OUT_RING(0);
489
490	ADVANCE_LP_RING();
491}
492
493static void i810EmitTexVerified(struct drm_device *dev, volatile unsigned int *code)
494{
495	drm_i810_private_t *dev_priv = dev->dev_private;
496	int i, j = 0;
497	unsigned int tmp;
498	RING_LOCALS;
499
500	BEGIN_LP_RING(I810_TEX_SETUP_SIZE);
501
502	OUT_RING(GFX_OP_MAP_INFO);
503	OUT_RING(code[I810_TEXREG_MI1]);
504	OUT_RING(code[I810_TEXREG_MI2]);
505	OUT_RING(code[I810_TEXREG_MI3]);
506
507	for (i = 4; i < I810_TEX_SETUP_SIZE; i++) {
508		tmp = code[i];
509
510		if ((tmp & (7 << 29)) == (3 << 29) &&
511		    (tmp & (0x1f << 24)) < (0x1d << 24)) {
512			OUT_RING(tmp);
513			j++;
514		} else
515			printk("texture state dropped!!!\n");
516	}
517
518	if (j & 1)
519		OUT_RING(0);
520
521	ADVANCE_LP_RING();
522}
523
524/* Need to do some additional checking when setting the dest buffer.
525 */
526static void i810EmitDestVerified(struct drm_device *dev,
527				 volatile unsigned int *code)
528{
529	drm_i810_private_t *dev_priv = dev->dev_private;
530	unsigned int tmp;
531	RING_LOCALS;
532
533	BEGIN_LP_RING(I810_DEST_SETUP_SIZE + 2);
534
535	tmp = code[I810_DESTREG_DI1];
536	if (tmp == dev_priv->front_di1 || tmp == dev_priv->back_di1) {
537		OUT_RING(CMD_OP_DESTBUFFER_INFO);
538		OUT_RING(tmp);
539	} else
540		DRM_DEBUG("bad di1 %x (allow %x or %x)\n",
541			  tmp, dev_priv->front_di1, dev_priv->back_di1);
542
543	/* invarient:
544	 */
545	OUT_RING(CMD_OP_Z_BUFFER_INFO);
546	OUT_RING(dev_priv->zi1);
547
548	OUT_RING(GFX_OP_DESTBUFFER_VARS);
549	OUT_RING(code[I810_DESTREG_DV1]);
550
551	OUT_RING(GFX_OP_DRAWRECT_INFO);
552	OUT_RING(code[I810_DESTREG_DR1]);
553	OUT_RING(code[I810_DESTREG_DR2]);
554	OUT_RING(code[I810_DESTREG_DR3]);
555	OUT_RING(code[I810_DESTREG_DR4]);
556	OUT_RING(0);
557
558	ADVANCE_LP_RING();
559}
560
561static void i810EmitState(struct drm_device *dev)
562{
563	drm_i810_private_t *dev_priv = dev->dev_private;
564	drm_i810_sarea_t *sarea_priv = dev_priv->sarea_priv;
565	unsigned int dirty = sarea_priv->dirty;
566
567	DRM_DEBUG("%x\n", dirty);
568
569	if (dirty & I810_UPLOAD_BUFFERS) {
570		i810EmitDestVerified(dev, sarea_priv->BufferState);
571		sarea_priv->dirty &= ~I810_UPLOAD_BUFFERS;
572	}
573
574	if (dirty & I810_UPLOAD_CTX) {
575		i810EmitContextVerified(dev, sarea_priv->ContextState);
576		sarea_priv->dirty &= ~I810_UPLOAD_CTX;
577	}
578
579	if (dirty & I810_UPLOAD_TEX0) {
580		i810EmitTexVerified(dev, sarea_priv->TexState[0]);
581		sarea_priv->dirty &= ~I810_UPLOAD_TEX0;
582	}
583
584	if (dirty & I810_UPLOAD_TEX1) {
585		i810EmitTexVerified(dev, sarea_priv->TexState[1]);
586		sarea_priv->dirty &= ~I810_UPLOAD_TEX1;
587	}
588}
589
590/* need to verify
591 */
592static void i810_dma_dispatch_clear(struct drm_device *dev, int flags,
593				    unsigned int clear_color,
594				    unsigned int clear_zval)
595{
596	drm_i810_private_t *dev_priv = dev->dev_private;
597	drm_i810_sarea_t *sarea_priv = dev_priv->sarea_priv;
598	int nbox = sarea_priv->nbox;
599	struct drm_clip_rect *pbox = sarea_priv->boxes;
600	int pitch = dev_priv->pitch;
601	int cpp = 2;
602	int i;
603	RING_LOCALS;
604
605	if (dev_priv->current_page == 1) {
606		unsigned int tmp = flags;
607
608		flags &= ~(I810_FRONT | I810_BACK);
609		if (tmp & I810_FRONT)
610			flags |= I810_BACK;
611		if (tmp & I810_BACK)
612			flags |= I810_FRONT;
613	}
614
615	i810_kernel_lost_context(dev);
616
617	if (nbox > I810_NR_SAREA_CLIPRECTS)
618		nbox = I810_NR_SAREA_CLIPRECTS;
619
620	for (i = 0; i < nbox; i++, pbox++) {
621		unsigned int x = pbox->x1;
622		unsigned int y = pbox->y1;
623		unsigned int width = (pbox->x2 - x) * cpp;
624		unsigned int height = pbox->y2 - y;
625		unsigned int start = y * pitch + x * cpp;
626
627		if (pbox->x1 > pbox->x2 ||
628		    pbox->y1 > pbox->y2 ||
629		    pbox->x2 > dev_priv->w || pbox->y2 > dev_priv->h)
630			continue;
631
632		if (flags & I810_FRONT) {
633			BEGIN_LP_RING(6);
634			OUT_RING(BR00_BITBLT_CLIENT | BR00_OP_COLOR_BLT | 0x3);
635			OUT_RING(BR13_SOLID_PATTERN | (0xF0 << 16) | pitch);
636			OUT_RING((height << 16) | width);
637			OUT_RING(start);
638			OUT_RING(clear_color);
639			OUT_RING(0);
640			ADVANCE_LP_RING();
641		}
642
643		if (flags & I810_BACK) {
644			BEGIN_LP_RING(6);
645			OUT_RING(BR00_BITBLT_CLIENT | BR00_OP_COLOR_BLT | 0x3);
646			OUT_RING(BR13_SOLID_PATTERN | (0xF0 << 16) | pitch);
647			OUT_RING((height << 16) | width);
648			OUT_RING(dev_priv->back_offset + start);
649			OUT_RING(clear_color);
650			OUT_RING(0);
651			ADVANCE_LP_RING();
652		}
653
654		if (flags & I810_DEPTH) {
655			BEGIN_LP_RING(6);
656			OUT_RING(BR00_BITBLT_CLIENT | BR00_OP_COLOR_BLT | 0x3);
657			OUT_RING(BR13_SOLID_PATTERN | (0xF0 << 16) | pitch);
658			OUT_RING((height << 16) | width);
659			OUT_RING(dev_priv->depth_offset + start);
660			OUT_RING(clear_zval);
661			OUT_RING(0);
662			ADVANCE_LP_RING();
663		}
664	}
665}
666
667static void i810_dma_dispatch_swap(struct drm_device *dev)
668{
669	drm_i810_private_t *dev_priv = dev->dev_private;
670	drm_i810_sarea_t *sarea_priv = dev_priv->sarea_priv;
671	int nbox = sarea_priv->nbox;
672	struct drm_clip_rect *pbox = sarea_priv->boxes;
673	int pitch = dev_priv->pitch;
674	int cpp = 2;
675	int i;
676	RING_LOCALS;
677
678	DRM_DEBUG("swapbuffers\n");
679
680	i810_kernel_lost_context(dev);
681
682	if (nbox > I810_NR_SAREA_CLIPRECTS)
683		nbox = I810_NR_SAREA_CLIPRECTS;
684
685	for (i = 0; i < nbox; i++, pbox++) {
686		unsigned int w = pbox->x2 - pbox->x1;
687		unsigned int h = pbox->y2 - pbox->y1;
688		unsigned int dst = pbox->x1 * cpp + pbox->y1 * pitch;
689		unsigned int start = dst;
690
691		if (pbox->x1 > pbox->x2 ||
692		    pbox->y1 > pbox->y2 ||
693		    pbox->x2 > dev_priv->w || pbox->y2 > dev_priv->h)
694			continue;
695
696		BEGIN_LP_RING(6);
697		OUT_RING(BR00_BITBLT_CLIENT | BR00_OP_SRC_COPY_BLT | 0x4);
698		OUT_RING(pitch | (0xCC << 16));
699		OUT_RING((h << 16) | (w * cpp));
700		if (dev_priv->current_page == 0)
701			OUT_RING(dev_priv->front_offset + start);
702		else
703			OUT_RING(dev_priv->back_offset + start);
704		OUT_RING(pitch);
705		if (dev_priv->current_page == 0)
706			OUT_RING(dev_priv->back_offset + start);
707		else
708			OUT_RING(dev_priv->front_offset + start);
709		ADVANCE_LP_RING();
710	}
711}
712
713static void i810_dma_dispatch_vertex(struct drm_device *dev,
714				     struct drm_buf *buf, int discard, int used)
715{
716	drm_i810_private_t *dev_priv = dev->dev_private;
717	drm_i810_buf_priv_t *buf_priv = buf->dev_private;
718	drm_i810_sarea_t *sarea_priv = dev_priv->sarea_priv;
719	struct drm_clip_rect *box = sarea_priv->boxes;
720	int nbox = sarea_priv->nbox;
721	unsigned long address = (unsigned long)buf->bus_address;
722	unsigned long start = address - dev->agp->base;
723	int i = 0;
724	RING_LOCALS;
725
726	i810_kernel_lost_context(dev);
727
728	if (nbox > I810_NR_SAREA_CLIPRECTS)
729		nbox = I810_NR_SAREA_CLIPRECTS;
730
731	if (used > 4 * 1024)
732		used = 0;
733
734	if (sarea_priv->dirty)
735		i810EmitState(dev);
736
737	if (buf_priv->currently_mapped == I810_BUF_MAPPED) {
738		unsigned int prim = (sarea_priv->vertex_prim & PR_MASK);
739
740		*(u32 *) buf_priv->kernel_virtual =
741		    ((GFX_OP_PRIMITIVE | prim | ((used / 4) - 2)));
742
743		if (used & 4) {
744			*(u32 *) ((char *) buf_priv->kernel_virtual + used) = 0;
745			used += 4;
746		}
747
748		i810_unmap_buffer(buf);
749	}
750
751	if (used) {
752		do {
753			if (i < nbox) {
754				BEGIN_LP_RING(4);
755				OUT_RING(GFX_OP_SCISSOR | SC_UPDATE_SCISSOR |
756					 SC_ENABLE);
757				OUT_RING(GFX_OP_SCISSOR_INFO);
758				OUT_RING(box[i].x1 | (box[i].y1 << 16));
759				OUT_RING((box[i].x2 -
760					  1) | ((box[i].y2 - 1) << 16));
761				ADVANCE_LP_RING();
762			}
763
764			BEGIN_LP_RING(4);
765			OUT_RING(CMD_OP_BATCH_BUFFER);
766			OUT_RING(start | BB1_PROTECTED);
767			OUT_RING(start + used - 4);
768			OUT_RING(0);
769			ADVANCE_LP_RING();
770
771		} while (++i < nbox);
772	}
773
774	if (discard) {
775		dev_priv->counter++;
776
777		(void)cmpxchg(buf_priv->in_use, I810_BUF_CLIENT,
778			      I810_BUF_HARDWARE);
779
780		BEGIN_LP_RING(8);
781		OUT_RING(CMD_STORE_DWORD_IDX);
782		OUT_RING(20);
783		OUT_RING(dev_priv->counter);
784		OUT_RING(CMD_STORE_DWORD_IDX);
785		OUT_RING(buf_priv->my_use_idx);
786		OUT_RING(I810_BUF_FREE);
787		OUT_RING(CMD_REPORT_HEAD);
788		OUT_RING(0);
789		ADVANCE_LP_RING();
790	}
791}
792
793static void i810_dma_dispatch_flip(struct drm_device *dev)
794{
795	drm_i810_private_t *dev_priv = dev->dev_private;
796	int pitch = dev_priv->pitch;
797	RING_LOCALS;
798
799	DRM_DEBUG("page=%d pfCurrentPage=%d\n",
800		  dev_priv->current_page,
801		  dev_priv->sarea_priv->pf_current_page);
802
803	i810_kernel_lost_context(dev);
804
805	BEGIN_LP_RING(2);
806	OUT_RING(INST_PARSER_CLIENT | INST_OP_FLUSH | INST_FLUSH_MAP_CACHE);
807	OUT_RING(0);
808	ADVANCE_LP_RING();
809
810	BEGIN_LP_RING(I810_DEST_SETUP_SIZE + 2);
811	/* On i815 at least ASYNC is buggy */
812	/* pitch<<5 is from 11.2.8 p158,
813	   its the pitch / 8 then left shifted 8,
814	   so (pitch >> 3) << 8 */
815	OUT_RING(CMD_OP_FRONTBUFFER_INFO | (pitch << 5) /*| ASYNC_FLIP */ );
816	if (dev_priv->current_page == 0) {
817		OUT_RING(dev_priv->back_offset);
818		dev_priv->current_page = 1;
819	} else {
820		OUT_RING(dev_priv->front_offset);
821		dev_priv->current_page = 0;
822	}
823	OUT_RING(0);
824	ADVANCE_LP_RING();
825
826	BEGIN_LP_RING(2);
827	OUT_RING(CMD_OP_WAIT_FOR_EVENT | WAIT_FOR_PLANE_A_FLIP);
828	OUT_RING(0);
829	ADVANCE_LP_RING();
830
831	/* Increment the frame counter.  The client-side 3D driver must
832	 * throttle the framerate by waiting for this value before
833	 * performing the swapbuffer ioctl.
834	 */
835	dev_priv->sarea_priv->pf_current_page = dev_priv->current_page;
836
837}
838
839static void i810_dma_quiescent(struct drm_device *dev)
840{
841	drm_i810_private_t *dev_priv = dev->dev_private;
842	RING_LOCALS;
843
844	i810_kernel_lost_context(dev);
845
846	BEGIN_LP_RING(4);
847	OUT_RING(INST_PARSER_CLIENT | INST_OP_FLUSH | INST_FLUSH_MAP_CACHE);
848	OUT_RING(CMD_REPORT_HEAD);
849	OUT_RING(0);
850	OUT_RING(0);
851	ADVANCE_LP_RING();
852
853	i810_wait_ring(dev, dev_priv->ring.Size - 8);
854}
855
856static int i810_flush_queue(struct drm_device *dev)
857{
858	drm_i810_private_t *dev_priv = dev->dev_private;
859	struct drm_device_dma *dma = dev->dma;
860	int i, ret = 0;
861	RING_LOCALS;
862
863	i810_kernel_lost_context(dev);
864
865	BEGIN_LP_RING(2);
866	OUT_RING(CMD_REPORT_HEAD);
867	OUT_RING(0);
868	ADVANCE_LP_RING();
869
870	i810_wait_ring(dev, dev_priv->ring.Size - 8);
871
872	for (i = 0; i < dma->buf_count; i++) {
873		struct drm_buf *buf = dma->buflist[i];
874		drm_i810_buf_priv_t *buf_priv = buf->dev_private;
875
876		int used = cmpxchg(buf_priv->in_use, I810_BUF_HARDWARE,
877				   I810_BUF_FREE);
878
879		if (used == I810_BUF_HARDWARE)
880			DRM_DEBUG("reclaimed from HARDWARE\n");
881		if (used == I810_BUF_CLIENT)
882			DRM_DEBUG("still on client\n");
883	}
884
885	return ret;
886}
887
888/* Must be called with the lock held */
889static void i810_reclaim_buffers(struct drm_device *dev,
890				 struct drm_file *file_priv)
891{
892	struct drm_device_dma *dma = dev->dma;
893	int i;
894
895	if (!dma)
896		return;
897	if (!dev->dev_private)
898		return;
899	if (!dma->buflist)
900		return;
901
902	i810_flush_queue(dev);
903
904	for (i = 0; i < dma->buf_count; i++) {
905		struct drm_buf *buf = dma->buflist[i];
906		drm_i810_buf_priv_t *buf_priv = buf->dev_private;
907
908		if (buf->file_priv == file_priv && buf_priv) {
909			int used = cmpxchg(buf_priv->in_use, I810_BUF_CLIENT,
910					   I810_BUF_FREE);
911
912			if (used == I810_BUF_CLIENT)
913				DRM_DEBUG("reclaimed from client\n");
914			if (buf_priv->currently_mapped == I810_BUF_MAPPED)
915				buf_priv->currently_mapped = I810_BUF_UNMAPPED;
916		}
917	}
918}
919
920static int i810_flush_ioctl(struct drm_device *dev, void *data,
921			    struct drm_file *file_priv)
922{
923	LOCK_TEST_WITH_RETURN(dev, file_priv);
924
925	i810_flush_queue(dev);
926	return 0;
927}
928
929static int i810_dma_vertex(struct drm_device *dev, void *data,
930			   struct drm_file *file_priv)
931{
932	struct drm_device_dma *dma = dev->dma;
933	drm_i810_private_t *dev_priv = (drm_i810_private_t *) dev->dev_private;
934	u32 *hw_status = dev_priv->hw_status_page;
935	drm_i810_sarea_t *sarea_priv = (drm_i810_sarea_t *)
936	    dev_priv->sarea_priv;
937	drm_i810_vertex_t *vertex = data;
938
939	LOCK_TEST_WITH_RETURN(dev, file_priv);
940
941	DRM_DEBUG("idx %d used %d discard %d\n",
942		  vertex->idx, vertex->used, vertex->discard);
943
944	if (vertex->idx < 0 || vertex->idx > dma->buf_count)
945		return -EINVAL;
946
947	i810_dma_dispatch_vertex(dev,
948				 dma->buflist[vertex->idx],
949				 vertex->discard, vertex->used);
950
951	atomic_add(vertex->used, &dev->counts[_DRM_STAT_SECONDARY]);
952	atomic_inc(&dev->counts[_DRM_STAT_DMA]);
953	sarea_priv->last_enqueue = dev_priv->counter - 1;
954	sarea_priv->last_dispatch = (int)hw_status[5];
955
956	return 0;
957}
958
959static int i810_clear_bufs(struct drm_device *dev, void *data,
960			   struct drm_file *file_priv)
961{
962	drm_i810_clear_t *clear = data;
963
964	LOCK_TEST_WITH_RETURN(dev, file_priv);
965
966	/* GH: Someone's doing nasty things... */
967	if (!dev->dev_private)
968		return -EINVAL;
969
970	i810_dma_dispatch_clear(dev, clear->flags,
971				clear->clear_color, clear->clear_depth);
972	return 0;
973}
974
975static int i810_swap_bufs(struct drm_device *dev, void *data,
976			  struct drm_file *file_priv)
977{
978	DRM_DEBUG("\n");
979
980	LOCK_TEST_WITH_RETURN(dev, file_priv);
981
982	i810_dma_dispatch_swap(dev);
983	return 0;
984}
985
986static int i810_getage(struct drm_device *dev, void *data,
987		       struct drm_file *file_priv)
988{
989	drm_i810_private_t *dev_priv = (drm_i810_private_t *) dev->dev_private;
990	u32 *hw_status = dev_priv->hw_status_page;
991	drm_i810_sarea_t *sarea_priv = (drm_i810_sarea_t *)
992	    dev_priv->sarea_priv;
993
994	sarea_priv->last_dispatch = (int)hw_status[5];
995	return 0;
996}
997
998static int i810_getbuf(struct drm_device *dev, void *data,
999		       struct drm_file *file_priv)
1000{
1001	int retcode = 0;
1002	drm_i810_dma_t *d = data;
1003	drm_i810_private_t *dev_priv = (drm_i810_private_t *) dev->dev_private;
1004	u32 *hw_status = dev_priv->hw_status_page;
1005	drm_i810_sarea_t *sarea_priv = (drm_i810_sarea_t *)
1006	    dev_priv->sarea_priv;
1007
1008	LOCK_TEST_WITH_RETURN(dev, file_priv);
1009
1010	d->granted = 0;
1011
1012	retcode = i810_dma_get_buffer(dev, d, file_priv);
1013
1014	DRM_DEBUG("i810_dma: %d returning %d, granted = %d\n",
1015		  task_pid_nr(current), retcode, d->granted);
1016
1017	sarea_priv->last_dispatch = (int)hw_status[5];
1018
1019	return retcode;
1020}
1021
1022static int i810_copybuf(struct drm_device *dev, void *data,
1023			struct drm_file *file_priv)
1024{
1025	/* Never copy - 2.4.x doesn't need it */
1026	return 0;
1027}
1028
1029static int i810_docopy(struct drm_device *dev, void *data,
1030			struct drm_file *file_priv)
1031{
1032	/* Never copy - 2.4.x doesn't need it */
1033	return 0;
1034}
1035
1036static void i810_dma_dispatch_mc(struct drm_device *dev, struct drm_buf *buf, int used,
1037				 unsigned int last_render)
1038{
1039	drm_i810_private_t *dev_priv = dev->dev_private;
1040	drm_i810_buf_priv_t *buf_priv = buf->dev_private;
1041	drm_i810_sarea_t *sarea_priv = dev_priv->sarea_priv;
1042	unsigned long address = (unsigned long)buf->bus_address;
1043	unsigned long start = address - dev->agp->base;
1044	int u;
1045	RING_LOCALS;
1046
1047	i810_kernel_lost_context(dev);
1048
1049	u = cmpxchg(buf_priv->in_use, I810_BUF_CLIENT, I810_BUF_HARDWARE);
1050	if (u != I810_BUF_CLIENT)
1051		DRM_DEBUG("MC found buffer that isn't mine!\n");
1052
1053	if (used > 4 * 1024)
1054		used = 0;
1055
1056	sarea_priv->dirty = 0x7f;
1057
1058	DRM_DEBUG("addr 0x%lx, used 0x%x\n", address, used);
1059
1060	dev_priv->counter++;
1061	DRM_DEBUG("dispatch counter : %ld\n", dev_priv->counter);
1062	DRM_DEBUG("start : %lx\n", start);
1063	DRM_DEBUG("used : %d\n", used);
1064	DRM_DEBUG("start + used - 4 : %ld\n", start + used - 4);
1065
1066	if (buf_priv->currently_mapped == I810_BUF_MAPPED) {
1067		if (used & 4) {
1068			*(u32 *) ((char *) buf_priv->virtual + used) = 0;
1069			used += 4;
1070		}
1071
1072		i810_unmap_buffer(buf);
1073	}
1074	BEGIN_LP_RING(4);
1075	OUT_RING(CMD_OP_BATCH_BUFFER);
1076	OUT_RING(start | BB1_PROTECTED);
1077	OUT_RING(start + used - 4);
1078	OUT_RING(0);
1079	ADVANCE_LP_RING();
1080
1081	BEGIN_LP_RING(8);
1082	OUT_RING(CMD_STORE_DWORD_IDX);
1083	OUT_RING(buf_priv->my_use_idx);
1084	OUT_RING(I810_BUF_FREE);
1085	OUT_RING(0);
1086
1087	OUT_RING(CMD_STORE_DWORD_IDX);
1088	OUT_RING(16);
1089	OUT_RING(last_render);
1090	OUT_RING(0);
1091	ADVANCE_LP_RING();
1092}
1093
1094static int i810_dma_mc(struct drm_device *dev, void *data,
1095		       struct drm_file *file_priv)
1096{
1097	struct drm_device_dma *dma = dev->dma;
1098	drm_i810_private_t *dev_priv = (drm_i810_private_t *) dev->dev_private;
1099	u32 *hw_status = dev_priv->hw_status_page;
1100	drm_i810_sarea_t *sarea_priv = (drm_i810_sarea_t *)
1101	    dev_priv->sarea_priv;
1102	drm_i810_mc_t *mc = data;
1103
1104	LOCK_TEST_WITH_RETURN(dev, file_priv);
1105
1106	if (mc->idx >= dma->buf_count || mc->idx < 0)
1107		return -EINVAL;
1108
1109	i810_dma_dispatch_mc(dev, dma->buflist[mc->idx], mc->used,
1110			     mc->last_render);
1111
1112	atomic_add(mc->used, &dev->counts[_DRM_STAT_SECONDARY]);
1113	atomic_inc(&dev->counts[_DRM_STAT_DMA]);
1114	sarea_priv->last_enqueue = dev_priv->counter - 1;
1115	sarea_priv->last_dispatch = (int)hw_status[5];
1116
1117	return 0;
1118}
1119
1120static int i810_rstatus(struct drm_device *dev, void *data,
1121			struct drm_file *file_priv)
1122{
1123	drm_i810_private_t *dev_priv = (drm_i810_private_t *) dev->dev_private;
1124
1125	return (int)(((u32 *) (dev_priv->hw_status_page))[4]);
1126}
1127
1128static int i810_ov0_info(struct drm_device *dev, void *data,
1129			 struct drm_file *file_priv)
1130{
1131	drm_i810_private_t *dev_priv = (drm_i810_private_t *) dev->dev_private;
1132	drm_i810_overlay_t *ov = data;
1133
1134	ov->offset = dev_priv->overlay_offset;
1135	ov->physical = dev_priv->overlay_physical;
1136
1137	return 0;
1138}
1139
1140static int i810_fstatus(struct drm_device *dev, void *data,
1141			struct drm_file *file_priv)
1142{
1143	drm_i810_private_t *dev_priv = (drm_i810_private_t *) dev->dev_private;
1144
1145	LOCK_TEST_WITH_RETURN(dev, file_priv);
1146	return I810_READ(0x30008);
1147}
1148
1149static int i810_ov0_flip(struct drm_device *dev, void *data,
1150			 struct drm_file *file_priv)
1151{
1152	drm_i810_private_t *dev_priv = (drm_i810_private_t *) dev->dev_private;
1153
1154	LOCK_TEST_WITH_RETURN(dev, file_priv);
1155
1156	/* Tell the overlay to update */
1157	I810_WRITE(0x30000, dev_priv->overlay_physical | 0x80000000);
1158
1159	return 0;
1160}
1161
1162/* Not sure why this isn't set all the time:
1163 */
1164static void i810_do_init_pageflip(struct drm_device *dev)
1165{
1166	drm_i810_private_t *dev_priv = dev->dev_private;
1167
1168	DRM_DEBUG("\n");
1169	dev_priv->page_flipping = 1;
1170	dev_priv->current_page = 0;
1171	dev_priv->sarea_priv->pf_current_page = dev_priv->current_page;
1172}
1173
1174static int i810_do_cleanup_pageflip(struct drm_device *dev)
1175{
1176	drm_i810_private_t *dev_priv = dev->dev_private;
1177
1178	DRM_DEBUG("\n");
1179	if (dev_priv->current_page != 0)
1180		i810_dma_dispatch_flip(dev);
1181
1182	dev_priv->page_flipping = 0;
1183	return 0;
1184}
1185
1186static int i810_flip_bufs(struct drm_device *dev, void *data,
1187			  struct drm_file *file_priv)
1188{
1189	drm_i810_private_t *dev_priv = dev->dev_private;
1190
1191	DRM_DEBUG("\n");
1192
1193	LOCK_TEST_WITH_RETURN(dev, file_priv);
1194
1195	if (!dev_priv->page_flipping)
1196		i810_do_init_pageflip(dev);
1197
1198	i810_dma_dispatch_flip(dev);
1199	return 0;
1200}
1201
1202int i810_driver_load(struct drm_device *dev, unsigned long flags)
1203{
1204	/* i810 has 4 more counters */
1205	dev->counters += 4;
1206	dev->types[6] = _DRM_STAT_IRQ;
1207	dev->types[7] = _DRM_STAT_PRIMARY;
1208	dev->types[8] = _DRM_STAT_SECONDARY;
1209	dev->types[9] = _DRM_STAT_DMA;
1210
1211	return 0;
1212}
1213
1214void i810_driver_lastclose(struct drm_device *dev)
1215{
1216	i810_dma_cleanup(dev);
1217}
1218
1219void i810_driver_preclose(struct drm_device *dev, struct drm_file *file_priv)
1220{
1221	if (dev->dev_private) {
1222		drm_i810_private_t *dev_priv = dev->dev_private;
1223		if (dev_priv->page_flipping)
1224			i810_do_cleanup_pageflip(dev);
1225	}
1226}
1227
1228void i810_driver_reclaim_buffers_locked(struct drm_device *dev,
1229					struct drm_file *file_priv)
1230{
1231	i810_reclaim_buffers(dev, file_priv);
1232}
1233
1234int i810_driver_dma_quiescent(struct drm_device *dev)
1235{
1236	i810_dma_quiescent(dev);
1237	return 0;
1238}
1239
1240struct drm_ioctl_desc i810_ioctls[] = {
1241	DRM_IOCTL_DEF_DRV(I810_INIT, i810_dma_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY|DRM_UNLOCKED),
1242	DRM_IOCTL_DEF_DRV(I810_VERTEX, i810_dma_vertex, DRM_AUTH|DRM_UNLOCKED),
1243	DRM_IOCTL_DEF_DRV(I810_CLEAR, i810_clear_bufs, DRM_AUTH|DRM_UNLOCKED),
1244	DRM_IOCTL_DEF_DRV(I810_FLUSH, i810_flush_ioctl, DRM_AUTH|DRM_UNLOCKED),
1245	DRM_IOCTL_DEF_DRV(I810_GETAGE, i810_getage, DRM_AUTH|DRM_UNLOCKED),
1246	DRM_IOCTL_DEF_DRV(I810_GETBUF, i810_getbuf, DRM_AUTH|DRM_UNLOCKED),
1247	DRM_IOCTL_DEF_DRV(I810_SWAP, i810_swap_bufs, DRM_AUTH|DRM_UNLOCKED),
1248	DRM_IOCTL_DEF_DRV(I810_COPY, i810_copybuf, DRM_AUTH|DRM_UNLOCKED),
1249	DRM_IOCTL_DEF_DRV(I810_DOCOPY, i810_docopy, DRM_AUTH|DRM_UNLOCKED),
1250	DRM_IOCTL_DEF_DRV(I810_OV0INFO, i810_ov0_info, DRM_AUTH|DRM_UNLOCKED),
1251	DRM_IOCTL_DEF_DRV(I810_FSTATUS, i810_fstatus, DRM_AUTH|DRM_UNLOCKED),
1252	DRM_IOCTL_DEF_DRV(I810_OV0FLIP, i810_ov0_flip, DRM_AUTH|DRM_UNLOCKED),
1253	DRM_IOCTL_DEF_DRV(I810_MC, i810_dma_mc, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY|DRM_UNLOCKED),
1254	DRM_IOCTL_DEF_DRV(I810_RSTATUS, i810_rstatus, DRM_AUTH|DRM_UNLOCKED),
1255	DRM_IOCTL_DEF_DRV(I810_FLIP, i810_flip_bufs, DRM_AUTH|DRM_UNLOCKED),
1256};
1257
1258int i810_max_ioctl = DRM_ARRAY_SIZE(i810_ioctls);
1259
1260/**
1261 * Determine if the device really is AGP or not.
1262 *
1263 * All Intel graphics chipsets are treated as AGP, even if they are really
1264 * PCI-e.
1265 *
1266 * \param dev   The device to be tested.
1267 *
1268 * \returns
1269 * A value of 1 is always retured to indictate every i810 is AGP.
1270 */
1271int i810_driver_device_is_agp(struct drm_device *dev)
1272{
1273	return 1;
1274}
1275