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