1 1.6 riastrad /* $NetBSD: via_dma.c,v 1.6 2021/12/18 23:45:44 riastradh Exp $ */ 2 1.3 riastrad 3 1.1 riastrad /* via_dma.c -- DMA support for the VIA Unichrome/Pro 4 1.1 riastrad * 5 1.1 riastrad * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. 6 1.1 riastrad * All Rights Reserved. 7 1.1 riastrad * 8 1.1 riastrad * Copyright 2004 Digeo, Inc., Palo Alto, CA, U.S.A. 9 1.1 riastrad * All Rights Reserved. 10 1.1 riastrad * 11 1.1 riastrad * Copyright 2004 The Unichrome project. 12 1.1 riastrad * All Rights Reserved. 13 1.1 riastrad * 14 1.1 riastrad * Permission is hereby granted, free of charge, to any person obtaining a 15 1.1 riastrad * copy of this software and associated documentation files (the "Software"), 16 1.1 riastrad * to deal in the Software without restriction, including without limitation 17 1.1 riastrad * the rights to use, copy, modify, merge, publish, distribute, sub license, 18 1.1 riastrad * and/or sell copies of the Software, and to permit persons to whom the 19 1.1 riastrad * Software is furnished to do so, subject to the following conditions: 20 1.1 riastrad * 21 1.1 riastrad * The above copyright notice and this permission notice (including the 22 1.1 riastrad * next paragraph) shall be included in all copies or substantial portions 23 1.1 riastrad * of the Software. 24 1.1 riastrad * 25 1.1 riastrad * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 26 1.1 riastrad * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 27 1.1 riastrad * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 28 1.1 riastrad * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, 29 1.1 riastrad * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 30 1.1 riastrad * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 31 1.1 riastrad * USE OR OTHER DEALINGS IN THE SOFTWARE. 32 1.1 riastrad * 33 1.1 riastrad * Authors: 34 1.1 riastrad * Tungsten Graphics, 35 1.1 riastrad * Erdi Chen, 36 1.1 riastrad * Thomas Hellstrom. 37 1.1 riastrad */ 38 1.1 riastrad 39 1.3 riastrad #include <sys/cdefs.h> 40 1.6 riastrad __KERNEL_RCSID(0, "$NetBSD: via_dma.c,v 1.6 2021/12/18 23:45:44 riastradh Exp $"); 41 1.3 riastrad 42 1.6 riastrad #include <linux/delay.h> 43 1.6 riastrad #include <linux/uaccess.h> 44 1.6 riastrad 45 1.6 riastrad #include <drm/drm.h> 46 1.6 riastrad #include <drm/drm_agpsupport.h> 47 1.6 riastrad #include <drm/drm_device.h> 48 1.6 riastrad #include <drm/drm_file.h> 49 1.1 riastrad #include <drm/via_drm.h> 50 1.6 riastrad 51 1.1 riastrad #include "via_drv.h" 52 1.1 riastrad #include "via_3d_reg.h" 53 1.1 riastrad 54 1.1 riastrad #define CMDBUF_ALIGNMENT_SIZE (0x100) 55 1.1 riastrad #define CMDBUF_ALIGNMENT_MASK (0x0ff) 56 1.1 riastrad 57 1.1 riastrad /* defines for VIA 3D registers */ 58 1.1 riastrad #define VIA_REG_STATUS 0x400 59 1.1 riastrad #define VIA_REG_TRANSET 0x43C 60 1.1 riastrad #define VIA_REG_TRANSPACE 0x440 61 1.1 riastrad 62 1.1 riastrad /* VIA_REG_STATUS(0x400): Engine Status */ 63 1.1 riastrad #define VIA_CMD_RGTR_BUSY 0x00000080 /* Command Regulator is busy */ 64 1.1 riastrad #define VIA_2D_ENG_BUSY 0x00000001 /* 2D Engine is busy */ 65 1.1 riastrad #define VIA_3D_ENG_BUSY 0x00000002 /* 3D Engine is busy */ 66 1.1 riastrad #define VIA_VR_QUEUE_BUSY 0x00020000 /* Virtual Queue is busy */ 67 1.1 riastrad 68 1.1 riastrad #define SetReg2DAGP(nReg, nData) { \ 69 1.1 riastrad *((uint32_t *)(vb)) = ((nReg) >> 2) | HALCYON_HEADER1; \ 70 1.1 riastrad *((uint32_t *)(vb) + 1) = (nData); \ 71 1.1 riastrad vb = ((uint32_t *)vb) + 2; \ 72 1.1 riastrad dev_priv->dma_low += 8; \ 73 1.1 riastrad } 74 1.1 riastrad 75 1.2 riastrad #define via_flush_write_combine() mb() 76 1.1 riastrad 77 1.1 riastrad #define VIA_OUT_RING_QW(w1, w2) do { \ 78 1.1 riastrad *vb++ = (w1); \ 79 1.1 riastrad *vb++ = (w2); \ 80 1.1 riastrad dev_priv->dma_low += 8; \ 81 1.1 riastrad } while (0) 82 1.1 riastrad 83 1.1 riastrad static void via_cmdbuf_start(drm_via_private_t *dev_priv); 84 1.1 riastrad static void via_cmdbuf_pause(drm_via_private_t *dev_priv); 85 1.1 riastrad static void via_cmdbuf_reset(drm_via_private_t *dev_priv); 86 1.1 riastrad static void via_cmdbuf_rewind(drm_via_private_t *dev_priv); 87 1.1 riastrad static int via_wait_idle(drm_via_private_t *dev_priv); 88 1.1 riastrad static void via_pad_cache(drm_via_private_t *dev_priv, int qwords); 89 1.1 riastrad 90 1.1 riastrad /* 91 1.1 riastrad * Free space in command buffer. 92 1.1 riastrad */ 93 1.1 riastrad 94 1.1 riastrad static uint32_t via_cmdbuf_space(drm_via_private_t *dev_priv) 95 1.1 riastrad { 96 1.1 riastrad uint32_t agp_base = dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr; 97 1.1 riastrad uint32_t hw_addr = *(dev_priv->hw_addr_ptr) - agp_base; 98 1.1 riastrad 99 1.1 riastrad return ((hw_addr <= dev_priv->dma_low) ? 100 1.1 riastrad (dev_priv->dma_high + hw_addr - dev_priv->dma_low) : 101 1.1 riastrad (hw_addr - dev_priv->dma_low)); 102 1.1 riastrad } 103 1.1 riastrad 104 1.1 riastrad /* 105 1.1 riastrad * How much does the command regulator lag behind? 106 1.1 riastrad */ 107 1.1 riastrad 108 1.1 riastrad static uint32_t via_cmdbuf_lag(drm_via_private_t *dev_priv) 109 1.1 riastrad { 110 1.1 riastrad uint32_t agp_base = dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr; 111 1.1 riastrad uint32_t hw_addr = *(dev_priv->hw_addr_ptr) - agp_base; 112 1.1 riastrad 113 1.1 riastrad return ((hw_addr <= dev_priv->dma_low) ? 114 1.1 riastrad (dev_priv->dma_low - hw_addr) : 115 1.1 riastrad (dev_priv->dma_wrap + dev_priv->dma_low - hw_addr)); 116 1.1 riastrad } 117 1.1 riastrad 118 1.1 riastrad /* 119 1.1 riastrad * Check that the given size fits in the buffer, otherwise wait. 120 1.1 riastrad */ 121 1.1 riastrad 122 1.1 riastrad static inline int 123 1.1 riastrad via_cmdbuf_wait(drm_via_private_t *dev_priv, unsigned int size) 124 1.1 riastrad { 125 1.1 riastrad uint32_t agp_base = dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr; 126 1.1 riastrad uint32_t cur_addr, hw_addr, next_addr; 127 1.1 riastrad volatile uint32_t *hw_addr_ptr; 128 1.1 riastrad uint32_t count; 129 1.1 riastrad hw_addr_ptr = dev_priv->hw_addr_ptr; 130 1.1 riastrad cur_addr = dev_priv->dma_low; 131 1.1 riastrad next_addr = cur_addr + size + 512 * 1024; 132 1.1 riastrad count = 1000000; 133 1.1 riastrad do { 134 1.1 riastrad hw_addr = *hw_addr_ptr - agp_base; 135 1.1 riastrad if (count-- == 0) { 136 1.1 riastrad DRM_ERROR 137 1.1 riastrad ("via_cmdbuf_wait timed out hw %x cur_addr %x next_addr %x\n", 138 1.1 riastrad hw_addr, cur_addr, next_addr); 139 1.1 riastrad return -1; 140 1.1 riastrad } 141 1.1 riastrad if ((cur_addr < hw_addr) && (next_addr >= hw_addr)) 142 1.1 riastrad msleep(1); 143 1.1 riastrad } while ((cur_addr < hw_addr) && (next_addr >= hw_addr)); 144 1.1 riastrad return 0; 145 1.1 riastrad } 146 1.1 riastrad 147 1.1 riastrad /* 148 1.1 riastrad * Checks whether buffer head has reach the end. Rewind the ring buffer 149 1.1 riastrad * when necessary. 150 1.1 riastrad * 151 1.1 riastrad * Returns virtual pointer to ring buffer. 152 1.1 riastrad */ 153 1.1 riastrad 154 1.1 riastrad static inline uint32_t *via_check_dma(drm_via_private_t * dev_priv, 155 1.1 riastrad unsigned int size) 156 1.1 riastrad { 157 1.1 riastrad if ((dev_priv->dma_low + size + 4 * CMDBUF_ALIGNMENT_SIZE) > 158 1.1 riastrad dev_priv->dma_high) { 159 1.1 riastrad via_cmdbuf_rewind(dev_priv); 160 1.1 riastrad } 161 1.1 riastrad if (via_cmdbuf_wait(dev_priv, size) != 0) 162 1.1 riastrad return NULL; 163 1.1 riastrad 164 1.1 riastrad return (uint32_t *) (dev_priv->dma_ptr + dev_priv->dma_low); 165 1.1 riastrad } 166 1.1 riastrad 167 1.1 riastrad int via_dma_cleanup(struct drm_device *dev) 168 1.1 riastrad { 169 1.1 riastrad if (dev->dev_private) { 170 1.1 riastrad drm_via_private_t *dev_priv = 171 1.1 riastrad (drm_via_private_t *) dev->dev_private; 172 1.1 riastrad 173 1.1 riastrad if (dev_priv->ring.virtual_start) { 174 1.1 riastrad via_cmdbuf_reset(dev_priv); 175 1.1 riastrad 176 1.3 riastrad drm_legacy_ioremapfree(&dev_priv->ring.map, dev); 177 1.1 riastrad dev_priv->ring.virtual_start = NULL; 178 1.1 riastrad } 179 1.1 riastrad 180 1.1 riastrad } 181 1.1 riastrad 182 1.1 riastrad return 0; 183 1.1 riastrad } 184 1.1 riastrad 185 1.1 riastrad static int via_initialize(struct drm_device *dev, 186 1.1 riastrad drm_via_private_t *dev_priv, 187 1.1 riastrad drm_via_dma_init_t *init) 188 1.1 riastrad { 189 1.1 riastrad if (!dev_priv || !dev_priv->mmio) { 190 1.1 riastrad DRM_ERROR("via_dma_init called before via_map_init\n"); 191 1.1 riastrad return -EFAULT; 192 1.1 riastrad } 193 1.1 riastrad 194 1.1 riastrad if (dev_priv->ring.virtual_start != NULL) { 195 1.1 riastrad DRM_ERROR("called again without calling cleanup\n"); 196 1.1 riastrad return -EFAULT; 197 1.1 riastrad } 198 1.1 riastrad 199 1.1 riastrad if (!dev->agp || !dev->agp->base) { 200 1.1 riastrad DRM_ERROR("called with no agp memory available\n"); 201 1.1 riastrad return -EFAULT; 202 1.1 riastrad } 203 1.1 riastrad 204 1.1 riastrad if (dev_priv->chipset == VIA_DX9_0) { 205 1.1 riastrad DRM_ERROR("AGP DMA is not supported on this chip\n"); 206 1.1 riastrad return -EINVAL; 207 1.1 riastrad } 208 1.1 riastrad 209 1.1 riastrad dev_priv->ring.map.offset = dev->agp->base + init->offset; 210 1.1 riastrad dev_priv->ring.map.size = init->size; 211 1.1 riastrad dev_priv->ring.map.type = 0; 212 1.1 riastrad dev_priv->ring.map.flags = 0; 213 1.1 riastrad dev_priv->ring.map.mtrr = 0; 214 1.1 riastrad 215 1.3 riastrad drm_legacy_ioremap(&dev_priv->ring.map, dev); 216 1.1 riastrad 217 1.1 riastrad if (dev_priv->ring.map.handle == NULL) { 218 1.1 riastrad via_dma_cleanup(dev); 219 1.1 riastrad DRM_ERROR("can not ioremap virtual address for" 220 1.1 riastrad " ring buffer\n"); 221 1.1 riastrad return -ENOMEM; 222 1.1 riastrad } 223 1.1 riastrad 224 1.1 riastrad dev_priv->ring.virtual_start = dev_priv->ring.map.handle; 225 1.1 riastrad 226 1.1 riastrad dev_priv->dma_ptr = dev_priv->ring.virtual_start; 227 1.1 riastrad dev_priv->dma_low = 0; 228 1.1 riastrad dev_priv->dma_high = init->size; 229 1.1 riastrad dev_priv->dma_wrap = init->size; 230 1.1 riastrad dev_priv->dma_offset = init->offset; 231 1.1 riastrad dev_priv->last_pause_ptr = NULL; 232 1.1 riastrad dev_priv->hw_addr_ptr = 233 1.1 riastrad (volatile uint32_t *)((char *)dev_priv->mmio->handle + 234 1.1 riastrad init->reg_pause_addr); 235 1.1 riastrad 236 1.1 riastrad via_cmdbuf_start(dev_priv); 237 1.1 riastrad 238 1.1 riastrad return 0; 239 1.1 riastrad } 240 1.1 riastrad 241 1.1 riastrad static int via_dma_init(struct drm_device *dev, void *data, struct drm_file *file_priv) 242 1.1 riastrad { 243 1.1 riastrad drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private; 244 1.1 riastrad drm_via_dma_init_t *init = data; 245 1.1 riastrad int retcode = 0; 246 1.1 riastrad 247 1.1 riastrad switch (init->func) { 248 1.1 riastrad case VIA_INIT_DMA: 249 1.2 riastrad if (!capable(CAP_SYS_ADMIN)) 250 1.1 riastrad retcode = -EPERM; 251 1.1 riastrad else 252 1.1 riastrad retcode = via_initialize(dev, dev_priv, init); 253 1.1 riastrad break; 254 1.1 riastrad case VIA_CLEANUP_DMA: 255 1.2 riastrad if (!capable(CAP_SYS_ADMIN)) 256 1.1 riastrad retcode = -EPERM; 257 1.1 riastrad else 258 1.1 riastrad retcode = via_dma_cleanup(dev); 259 1.1 riastrad break; 260 1.1 riastrad case VIA_DMA_INITIALIZED: 261 1.1 riastrad retcode = (dev_priv->ring.virtual_start != NULL) ? 262 1.1 riastrad 0 : -EFAULT; 263 1.1 riastrad break; 264 1.1 riastrad default: 265 1.1 riastrad retcode = -EINVAL; 266 1.1 riastrad break; 267 1.1 riastrad } 268 1.1 riastrad 269 1.1 riastrad return retcode; 270 1.1 riastrad } 271 1.1 riastrad 272 1.1 riastrad static int via_dispatch_cmdbuffer(struct drm_device *dev, drm_via_cmdbuffer_t *cmd) 273 1.1 riastrad { 274 1.1 riastrad drm_via_private_t *dev_priv; 275 1.1 riastrad uint32_t *vb; 276 1.1 riastrad int ret; 277 1.1 riastrad 278 1.1 riastrad dev_priv = (drm_via_private_t *) dev->dev_private; 279 1.1 riastrad 280 1.1 riastrad if (dev_priv->ring.virtual_start == NULL) { 281 1.1 riastrad DRM_ERROR("called without initializing AGP ring buffer.\n"); 282 1.1 riastrad return -EFAULT; 283 1.1 riastrad } 284 1.1 riastrad 285 1.1 riastrad if (cmd->size > VIA_PCI_BUF_SIZE) 286 1.1 riastrad return -ENOMEM; 287 1.1 riastrad 288 1.2 riastrad if (copy_from_user(dev_priv->pci_buf, cmd->buf, cmd->size)) 289 1.1 riastrad return -EFAULT; 290 1.1 riastrad 291 1.1 riastrad /* 292 1.1 riastrad * Running this function on AGP memory is dead slow. Therefore 293 1.1 riastrad * we run it on a temporary cacheable system memory buffer and 294 1.1 riastrad * copy it to AGP memory when ready. 295 1.1 riastrad */ 296 1.1 riastrad 297 1.1 riastrad if ((ret = 298 1.1 riastrad via_verify_command_stream((uint32_t *) dev_priv->pci_buf, 299 1.1 riastrad cmd->size, dev, 1))) { 300 1.1 riastrad return ret; 301 1.1 riastrad } 302 1.1 riastrad 303 1.1 riastrad vb = via_check_dma(dev_priv, (cmd->size < 0x100) ? 0x102 : cmd->size); 304 1.1 riastrad if (vb == NULL) 305 1.1 riastrad return -EAGAIN; 306 1.1 riastrad 307 1.1 riastrad memcpy(vb, dev_priv->pci_buf, cmd->size); 308 1.1 riastrad 309 1.1 riastrad dev_priv->dma_low += cmd->size; 310 1.1 riastrad 311 1.1 riastrad /* 312 1.1 riastrad * Small submissions somehow stalls the CPU. (AGP cache effects?) 313 1.1 riastrad * pad to greater size. 314 1.1 riastrad */ 315 1.1 riastrad 316 1.1 riastrad if (cmd->size < 0x100) 317 1.1 riastrad via_pad_cache(dev_priv, (0x100 - cmd->size) >> 3); 318 1.1 riastrad via_cmdbuf_pause(dev_priv); 319 1.1 riastrad 320 1.1 riastrad return 0; 321 1.1 riastrad } 322 1.1 riastrad 323 1.1 riastrad int via_driver_dma_quiescent(struct drm_device *dev) 324 1.1 riastrad { 325 1.1 riastrad drm_via_private_t *dev_priv = dev->dev_private; 326 1.1 riastrad 327 1.1 riastrad if (!via_wait_idle(dev_priv)) 328 1.1 riastrad return -EBUSY; 329 1.1 riastrad return 0; 330 1.1 riastrad } 331 1.1 riastrad 332 1.1 riastrad static int via_flush_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) 333 1.1 riastrad { 334 1.1 riastrad 335 1.1 riastrad LOCK_TEST_WITH_RETURN(dev, file_priv); 336 1.1 riastrad 337 1.1 riastrad return via_driver_dma_quiescent(dev); 338 1.1 riastrad } 339 1.1 riastrad 340 1.1 riastrad static int via_cmdbuffer(struct drm_device *dev, void *data, struct drm_file *file_priv) 341 1.1 riastrad { 342 1.1 riastrad drm_via_cmdbuffer_t *cmdbuf = data; 343 1.1 riastrad int ret; 344 1.1 riastrad 345 1.1 riastrad LOCK_TEST_WITH_RETURN(dev, file_priv); 346 1.1 riastrad 347 1.1 riastrad DRM_DEBUG("buf %p size %lu\n", cmdbuf->buf, cmdbuf->size); 348 1.1 riastrad 349 1.1 riastrad ret = via_dispatch_cmdbuffer(dev, cmdbuf); 350 1.1 riastrad return ret; 351 1.1 riastrad } 352 1.1 riastrad 353 1.1 riastrad static int via_dispatch_pci_cmdbuffer(struct drm_device *dev, 354 1.1 riastrad drm_via_cmdbuffer_t *cmd) 355 1.1 riastrad { 356 1.1 riastrad drm_via_private_t *dev_priv = dev->dev_private; 357 1.1 riastrad int ret; 358 1.1 riastrad 359 1.1 riastrad if (cmd->size > VIA_PCI_BUF_SIZE) 360 1.1 riastrad return -ENOMEM; 361 1.2 riastrad if (copy_from_user(dev_priv->pci_buf, cmd->buf, cmd->size)) 362 1.1 riastrad return -EFAULT; 363 1.1 riastrad 364 1.1 riastrad if ((ret = 365 1.1 riastrad via_verify_command_stream((uint32_t *) dev_priv->pci_buf, 366 1.1 riastrad cmd->size, dev, 0))) { 367 1.1 riastrad return ret; 368 1.1 riastrad } 369 1.1 riastrad 370 1.1 riastrad ret = 371 1.1 riastrad via_parse_command_stream(dev, (const uint32_t *)dev_priv->pci_buf, 372 1.1 riastrad cmd->size); 373 1.1 riastrad return ret; 374 1.1 riastrad } 375 1.1 riastrad 376 1.1 riastrad static int via_pci_cmdbuffer(struct drm_device *dev, void *data, struct drm_file *file_priv) 377 1.1 riastrad { 378 1.1 riastrad drm_via_cmdbuffer_t *cmdbuf = data; 379 1.1 riastrad int ret; 380 1.1 riastrad 381 1.1 riastrad LOCK_TEST_WITH_RETURN(dev, file_priv); 382 1.1 riastrad 383 1.1 riastrad DRM_DEBUG("buf %p size %lu\n", cmdbuf->buf, cmdbuf->size); 384 1.1 riastrad 385 1.1 riastrad ret = via_dispatch_pci_cmdbuffer(dev, cmdbuf); 386 1.1 riastrad return ret; 387 1.1 riastrad } 388 1.1 riastrad 389 1.1 riastrad static inline uint32_t *via_align_buffer(drm_via_private_t *dev_priv, 390 1.1 riastrad uint32_t * vb, int qw_count) 391 1.1 riastrad { 392 1.1 riastrad for (; qw_count > 0; --qw_count) 393 1.1 riastrad VIA_OUT_RING_QW(HC_DUMMY, HC_DUMMY); 394 1.1 riastrad return vb; 395 1.1 riastrad } 396 1.1 riastrad 397 1.1 riastrad /* 398 1.1 riastrad * This function is used internally by ring buffer management code. 399 1.1 riastrad * 400 1.1 riastrad * Returns virtual pointer to ring buffer. 401 1.1 riastrad */ 402 1.1 riastrad static inline uint32_t *via_get_dma(drm_via_private_t *dev_priv) 403 1.1 riastrad { 404 1.1 riastrad return (uint32_t *) (dev_priv->dma_ptr + dev_priv->dma_low); 405 1.1 riastrad } 406 1.1 riastrad 407 1.1 riastrad /* 408 1.1 riastrad * Hooks a segment of data into the tail of the ring-buffer by 409 1.1 riastrad * modifying the pause address stored in the buffer itself. If 410 1.1 riastrad * the regulator has already paused, restart it. 411 1.1 riastrad */ 412 1.1 riastrad static int via_hook_segment(drm_via_private_t *dev_priv, 413 1.1 riastrad uint32_t pause_addr_hi, uint32_t pause_addr_lo, 414 1.1 riastrad int no_pci_fire) 415 1.1 riastrad { 416 1.1 riastrad int paused, count; 417 1.1 riastrad volatile uint32_t *paused_at = dev_priv->last_pause_ptr; 418 1.1 riastrad uint32_t reader, ptr; 419 1.1 riastrad uint32_t diff; 420 1.1 riastrad 421 1.1 riastrad paused = 0; 422 1.1 riastrad via_flush_write_combine(); 423 1.1 riastrad (void) *(volatile uint32_t *)(via_get_dma(dev_priv) - 1); 424 1.1 riastrad 425 1.1 riastrad *paused_at = pause_addr_lo; 426 1.1 riastrad via_flush_write_combine(); 427 1.1 riastrad (void) *paused_at; 428 1.1 riastrad 429 1.1 riastrad reader = *(dev_priv->hw_addr_ptr); 430 1.1 riastrad ptr = ((volatile char *)paused_at - dev_priv->dma_ptr) + 431 1.1 riastrad dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr + 4; 432 1.1 riastrad 433 1.1 riastrad dev_priv->last_pause_ptr = via_get_dma(dev_priv) - 1; 434 1.1 riastrad 435 1.1 riastrad /* 436 1.1 riastrad * If there is a possibility that the command reader will 437 1.1 riastrad * miss the new pause address and pause on the old one, 438 1.1 riastrad * In that case we need to program the new start address 439 1.1 riastrad * using PCI. 440 1.1 riastrad */ 441 1.1 riastrad 442 1.1 riastrad diff = (uint32_t) (ptr - reader) - dev_priv->dma_diff; 443 1.1 riastrad count = 10000000; 444 1.1 riastrad while (diff == 0 && count--) { 445 1.6 riastrad paused = (via_read(dev_priv, 0x41c) & 0x80000000); 446 1.1 riastrad if (paused) 447 1.1 riastrad break; 448 1.1 riastrad reader = *(dev_priv->hw_addr_ptr); 449 1.1 riastrad diff = (uint32_t) (ptr - reader) - dev_priv->dma_diff; 450 1.1 riastrad } 451 1.1 riastrad 452 1.6 riastrad paused = via_read(dev_priv, 0x41c) & 0x80000000; 453 1.1 riastrad 454 1.1 riastrad if (paused && !no_pci_fire) { 455 1.1 riastrad reader = *(dev_priv->hw_addr_ptr); 456 1.1 riastrad diff = (uint32_t) (ptr - reader) - dev_priv->dma_diff; 457 1.1 riastrad diff &= (dev_priv->dma_high - 1); 458 1.1 riastrad if (diff != 0 && diff < (dev_priv->dma_high >> 1)) { 459 1.1 riastrad DRM_ERROR("Paused at incorrect address. " 460 1.1 riastrad "0x%08x, 0x%08x 0x%08x\n", 461 1.1 riastrad ptr, reader, dev_priv->dma_diff); 462 1.1 riastrad } else if (diff == 0) { 463 1.1 riastrad /* 464 1.1 riastrad * There is a concern that these writes may stall the PCI bus 465 1.1 riastrad * if the GPU is not idle. However, idling the GPU first 466 1.1 riastrad * doesn't make a difference. 467 1.1 riastrad */ 468 1.1 riastrad 469 1.6 riastrad via_write(dev_priv, VIA_REG_TRANSET, (HC_ParaType_PreCR << 16)); 470 1.6 riastrad via_write(dev_priv, VIA_REG_TRANSPACE, pause_addr_hi); 471 1.6 riastrad via_write(dev_priv, VIA_REG_TRANSPACE, pause_addr_lo); 472 1.6 riastrad via_read(dev_priv, VIA_REG_TRANSPACE); 473 1.1 riastrad } 474 1.1 riastrad } 475 1.1 riastrad return paused; 476 1.1 riastrad } 477 1.1 riastrad 478 1.1 riastrad static int via_wait_idle(drm_via_private_t *dev_priv) 479 1.1 riastrad { 480 1.1 riastrad int count = 10000000; 481 1.1 riastrad 482 1.6 riastrad while (!(via_read(dev_priv, VIA_REG_STATUS) & VIA_VR_QUEUE_BUSY) && --count) 483 1.1 riastrad ; 484 1.1 riastrad 485 1.6 riastrad while (count && (via_read(dev_priv, VIA_REG_STATUS) & 486 1.1 riastrad (VIA_CMD_RGTR_BUSY | VIA_2D_ENG_BUSY | 487 1.1 riastrad VIA_3D_ENG_BUSY))) 488 1.1 riastrad --count; 489 1.1 riastrad return count; 490 1.1 riastrad } 491 1.1 riastrad 492 1.1 riastrad static uint32_t *via_align_cmd(drm_via_private_t *dev_priv, uint32_t cmd_type, 493 1.1 riastrad uint32_t addr, uint32_t *cmd_addr_hi, 494 1.1 riastrad uint32_t *cmd_addr_lo, int skip_wait) 495 1.1 riastrad { 496 1.1 riastrad uint32_t agp_base; 497 1.1 riastrad uint32_t cmd_addr, addr_lo, addr_hi; 498 1.1 riastrad uint32_t *vb; 499 1.1 riastrad uint32_t qw_pad_count; 500 1.1 riastrad 501 1.1 riastrad if (!skip_wait) 502 1.1 riastrad via_cmdbuf_wait(dev_priv, 2 * CMDBUF_ALIGNMENT_SIZE); 503 1.1 riastrad 504 1.1 riastrad vb = via_get_dma(dev_priv); 505 1.1 riastrad VIA_OUT_RING_QW(HC_HEADER2 | ((VIA_REG_TRANSET >> 2) << 12) | 506 1.1 riastrad (VIA_REG_TRANSPACE >> 2), HC_ParaType_PreCR << 16); 507 1.1 riastrad agp_base = dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr; 508 1.1 riastrad qw_pad_count = (CMDBUF_ALIGNMENT_SIZE >> 3) - 509 1.1 riastrad ((dev_priv->dma_low & CMDBUF_ALIGNMENT_MASK) >> 3); 510 1.1 riastrad 511 1.1 riastrad cmd_addr = (addr) ? addr : 512 1.1 riastrad agp_base + dev_priv->dma_low - 8 + (qw_pad_count << 3); 513 1.1 riastrad addr_lo = ((HC_SubA_HAGPBpL << 24) | (cmd_type & HC_HAGPBpID_MASK) | 514 1.1 riastrad (cmd_addr & HC_HAGPBpL_MASK)); 515 1.1 riastrad addr_hi = ((HC_SubA_HAGPBpH << 24) | (cmd_addr >> 24)); 516 1.1 riastrad 517 1.1 riastrad vb = via_align_buffer(dev_priv, vb, qw_pad_count - 1); 518 1.1 riastrad VIA_OUT_RING_QW(*cmd_addr_hi = addr_hi, *cmd_addr_lo = addr_lo); 519 1.1 riastrad return vb; 520 1.1 riastrad } 521 1.1 riastrad 522 1.1 riastrad static void via_cmdbuf_start(drm_via_private_t *dev_priv) 523 1.1 riastrad { 524 1.1 riastrad uint32_t pause_addr_lo, pause_addr_hi; 525 1.1 riastrad uint32_t start_addr, start_addr_lo; 526 1.1 riastrad uint32_t end_addr, end_addr_lo; 527 1.1 riastrad uint32_t command; 528 1.1 riastrad uint32_t agp_base; 529 1.1 riastrad uint32_t ptr; 530 1.1 riastrad uint32_t reader; 531 1.1 riastrad int count; 532 1.1 riastrad 533 1.1 riastrad dev_priv->dma_low = 0; 534 1.1 riastrad 535 1.1 riastrad agp_base = dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr; 536 1.1 riastrad start_addr = agp_base; 537 1.1 riastrad end_addr = agp_base + dev_priv->dma_high; 538 1.1 riastrad 539 1.1 riastrad start_addr_lo = ((HC_SubA_HAGPBstL << 24) | (start_addr & 0xFFFFFF)); 540 1.1 riastrad end_addr_lo = ((HC_SubA_HAGPBendL << 24) | (end_addr & 0xFFFFFF)); 541 1.1 riastrad command = ((HC_SubA_HAGPCMNT << 24) | (start_addr >> 24) | 542 1.1 riastrad ((end_addr & 0xff000000) >> 16)); 543 1.1 riastrad 544 1.1 riastrad dev_priv->last_pause_ptr = 545 1.1 riastrad via_align_cmd(dev_priv, HC_HAGPBpID_PAUSE, 0, 546 1.1 riastrad &pause_addr_hi, &pause_addr_lo, 1) - 1; 547 1.1 riastrad 548 1.1 riastrad via_flush_write_combine(); 549 1.1 riastrad (void) *(volatile uint32_t *)dev_priv->last_pause_ptr; 550 1.1 riastrad 551 1.6 riastrad via_write(dev_priv, VIA_REG_TRANSET, (HC_ParaType_PreCR << 16)); 552 1.6 riastrad via_write(dev_priv, VIA_REG_TRANSPACE, command); 553 1.6 riastrad via_write(dev_priv, VIA_REG_TRANSPACE, start_addr_lo); 554 1.6 riastrad via_write(dev_priv, VIA_REG_TRANSPACE, end_addr_lo); 555 1.1 riastrad 556 1.6 riastrad via_write(dev_priv, VIA_REG_TRANSPACE, pause_addr_hi); 557 1.6 riastrad via_write(dev_priv, VIA_REG_TRANSPACE, pause_addr_lo); 558 1.2 riastrad wmb(); 559 1.6 riastrad via_write(dev_priv, VIA_REG_TRANSPACE, command | HC_HAGPCMNT_MASK); 560 1.6 riastrad via_read(dev_priv, VIA_REG_TRANSPACE); 561 1.1 riastrad 562 1.1 riastrad dev_priv->dma_diff = 0; 563 1.1 riastrad 564 1.1 riastrad count = 10000000; 565 1.6 riastrad while (!(via_read(dev_priv, 0x41c) & 0x80000000) && count--); 566 1.1 riastrad 567 1.1 riastrad reader = *(dev_priv->hw_addr_ptr); 568 1.1 riastrad ptr = ((volatile char *)dev_priv->last_pause_ptr - dev_priv->dma_ptr) + 569 1.1 riastrad dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr + 4; 570 1.1 riastrad 571 1.1 riastrad /* 572 1.1 riastrad * This is the difference between where we tell the 573 1.1 riastrad * command reader to pause and where it actually pauses. 574 1.1 riastrad * This differs between hw implementation so we need to 575 1.1 riastrad * detect it. 576 1.1 riastrad */ 577 1.1 riastrad 578 1.1 riastrad dev_priv->dma_diff = ptr - reader; 579 1.1 riastrad } 580 1.1 riastrad 581 1.1 riastrad static void via_pad_cache(drm_via_private_t *dev_priv, int qwords) 582 1.1 riastrad { 583 1.1 riastrad uint32_t *vb; 584 1.1 riastrad 585 1.1 riastrad via_cmdbuf_wait(dev_priv, qwords + 2); 586 1.1 riastrad vb = via_get_dma(dev_priv); 587 1.1 riastrad VIA_OUT_RING_QW(HC_HEADER2, HC_ParaType_NotTex << 16); 588 1.1 riastrad via_align_buffer(dev_priv, vb, qwords); 589 1.1 riastrad } 590 1.1 riastrad 591 1.1 riastrad static inline void via_dummy_bitblt(drm_via_private_t *dev_priv) 592 1.1 riastrad { 593 1.1 riastrad uint32_t *vb = via_get_dma(dev_priv); 594 1.1 riastrad SetReg2DAGP(0x0C, (0 | (0 << 16))); 595 1.1 riastrad SetReg2DAGP(0x10, 0 | (0 << 16)); 596 1.1 riastrad SetReg2DAGP(0x0, 0x1 | 0x2000 | 0xAA000000); 597 1.1 riastrad } 598 1.1 riastrad 599 1.1 riastrad static void via_cmdbuf_jump(drm_via_private_t *dev_priv) 600 1.1 riastrad { 601 1.1 riastrad uint32_t pause_addr_lo, pause_addr_hi; 602 1.1 riastrad uint32_t jump_addr_lo, jump_addr_hi; 603 1.1 riastrad volatile uint32_t *last_pause_ptr; 604 1.1 riastrad uint32_t dma_low_save1, dma_low_save2; 605 1.1 riastrad 606 1.1 riastrad via_align_cmd(dev_priv, HC_HAGPBpID_JUMP, 0, &jump_addr_hi, 607 1.1 riastrad &jump_addr_lo, 0); 608 1.1 riastrad 609 1.1 riastrad dev_priv->dma_wrap = dev_priv->dma_low; 610 1.1 riastrad 611 1.1 riastrad /* 612 1.1 riastrad * Wrap command buffer to the beginning. 613 1.1 riastrad */ 614 1.1 riastrad 615 1.1 riastrad dev_priv->dma_low = 0; 616 1.1 riastrad if (via_cmdbuf_wait(dev_priv, CMDBUF_ALIGNMENT_SIZE) != 0) 617 1.1 riastrad DRM_ERROR("via_cmdbuf_jump failed\n"); 618 1.1 riastrad 619 1.1 riastrad via_dummy_bitblt(dev_priv); 620 1.1 riastrad via_dummy_bitblt(dev_priv); 621 1.1 riastrad 622 1.1 riastrad last_pause_ptr = 623 1.1 riastrad via_align_cmd(dev_priv, HC_HAGPBpID_PAUSE, 0, &pause_addr_hi, 624 1.1 riastrad &pause_addr_lo, 0) - 1; 625 1.1 riastrad via_align_cmd(dev_priv, HC_HAGPBpID_PAUSE, 0, &pause_addr_hi, 626 1.1 riastrad &pause_addr_lo, 0); 627 1.1 riastrad 628 1.1 riastrad *last_pause_ptr = pause_addr_lo; 629 1.1 riastrad dma_low_save1 = dev_priv->dma_low; 630 1.1 riastrad 631 1.1 riastrad /* 632 1.1 riastrad * Now, set a trap that will pause the regulator if it tries to rerun the old 633 1.1 riastrad * command buffer. (Which may happen if via_hook_segment detecs a command regulator pause 634 1.1 riastrad * and reissues the jump command over PCI, while the regulator has already taken the jump 635 1.1 riastrad * and actually paused at the current buffer end). 636 1.1 riastrad * There appears to be no other way to detect this condition, since the hw_addr_pointer 637 1.1 riastrad * does not seem to get updated immediately when a jump occurs. 638 1.1 riastrad */ 639 1.1 riastrad 640 1.1 riastrad last_pause_ptr = 641 1.1 riastrad via_align_cmd(dev_priv, HC_HAGPBpID_PAUSE, 0, &pause_addr_hi, 642 1.1 riastrad &pause_addr_lo, 0) - 1; 643 1.1 riastrad via_align_cmd(dev_priv, HC_HAGPBpID_PAUSE, 0, &pause_addr_hi, 644 1.1 riastrad &pause_addr_lo, 0); 645 1.1 riastrad *last_pause_ptr = pause_addr_lo; 646 1.1 riastrad 647 1.1 riastrad dma_low_save2 = dev_priv->dma_low; 648 1.1 riastrad dev_priv->dma_low = dma_low_save1; 649 1.1 riastrad via_hook_segment(dev_priv, jump_addr_hi, jump_addr_lo, 0); 650 1.1 riastrad dev_priv->dma_low = dma_low_save2; 651 1.1 riastrad via_hook_segment(dev_priv, pause_addr_hi, pause_addr_lo, 0); 652 1.1 riastrad } 653 1.1 riastrad 654 1.1 riastrad 655 1.1 riastrad static void via_cmdbuf_rewind(drm_via_private_t *dev_priv) 656 1.1 riastrad { 657 1.1 riastrad via_cmdbuf_jump(dev_priv); 658 1.1 riastrad } 659 1.1 riastrad 660 1.1 riastrad static void via_cmdbuf_flush(drm_via_private_t *dev_priv, uint32_t cmd_type) 661 1.1 riastrad { 662 1.1 riastrad uint32_t pause_addr_lo, pause_addr_hi; 663 1.1 riastrad 664 1.1 riastrad via_align_cmd(dev_priv, cmd_type, 0, &pause_addr_hi, &pause_addr_lo, 0); 665 1.1 riastrad via_hook_segment(dev_priv, pause_addr_hi, pause_addr_lo, 0); 666 1.1 riastrad } 667 1.1 riastrad 668 1.1 riastrad static void via_cmdbuf_pause(drm_via_private_t *dev_priv) 669 1.1 riastrad { 670 1.1 riastrad via_cmdbuf_flush(dev_priv, HC_HAGPBpID_PAUSE); 671 1.1 riastrad } 672 1.1 riastrad 673 1.1 riastrad static void via_cmdbuf_reset(drm_via_private_t *dev_priv) 674 1.1 riastrad { 675 1.1 riastrad via_cmdbuf_flush(dev_priv, HC_HAGPBpID_STOP); 676 1.1 riastrad via_wait_idle(dev_priv); 677 1.1 riastrad } 678 1.1 riastrad 679 1.1 riastrad /* 680 1.1 riastrad * User interface to the space and lag functions. 681 1.1 riastrad */ 682 1.1 riastrad 683 1.1 riastrad static int via_cmdbuf_size(struct drm_device *dev, void *data, struct drm_file *file_priv) 684 1.1 riastrad { 685 1.1 riastrad drm_via_cmdbuf_size_t *d_siz = data; 686 1.1 riastrad int ret = 0; 687 1.1 riastrad uint32_t tmp_size, count; 688 1.1 riastrad drm_via_private_t *dev_priv; 689 1.1 riastrad 690 1.1 riastrad DRM_DEBUG("\n"); 691 1.1 riastrad LOCK_TEST_WITH_RETURN(dev, file_priv); 692 1.1 riastrad 693 1.1 riastrad dev_priv = (drm_via_private_t *) dev->dev_private; 694 1.1 riastrad 695 1.1 riastrad if (dev_priv->ring.virtual_start == NULL) { 696 1.1 riastrad DRM_ERROR("called without initializing AGP ring buffer.\n"); 697 1.1 riastrad return -EFAULT; 698 1.1 riastrad } 699 1.1 riastrad 700 1.1 riastrad count = 1000000; 701 1.1 riastrad tmp_size = d_siz->size; 702 1.1 riastrad switch (d_siz->func) { 703 1.1 riastrad case VIA_CMDBUF_SPACE: 704 1.1 riastrad while (((tmp_size = via_cmdbuf_space(dev_priv)) < d_siz->size) 705 1.1 riastrad && --count) { 706 1.1 riastrad if (!d_siz->wait) 707 1.1 riastrad break; 708 1.1 riastrad } 709 1.1 riastrad if (!count) { 710 1.1 riastrad DRM_ERROR("VIA_CMDBUF_SPACE timed out.\n"); 711 1.1 riastrad ret = -EAGAIN; 712 1.1 riastrad } 713 1.1 riastrad break; 714 1.1 riastrad case VIA_CMDBUF_LAG: 715 1.1 riastrad while (((tmp_size = via_cmdbuf_lag(dev_priv)) > d_siz->size) 716 1.1 riastrad && --count) { 717 1.1 riastrad if (!d_siz->wait) 718 1.1 riastrad break; 719 1.1 riastrad } 720 1.1 riastrad if (!count) { 721 1.1 riastrad DRM_ERROR("VIA_CMDBUF_LAG timed out.\n"); 722 1.1 riastrad ret = -EAGAIN; 723 1.1 riastrad } 724 1.1 riastrad break; 725 1.1 riastrad default: 726 1.1 riastrad ret = -EFAULT; 727 1.1 riastrad } 728 1.1 riastrad d_siz->size = tmp_size; 729 1.1 riastrad 730 1.1 riastrad return ret; 731 1.1 riastrad } 732 1.1 riastrad 733 1.2 riastrad const struct drm_ioctl_desc via_ioctls[] = { 734 1.1 riastrad DRM_IOCTL_DEF_DRV(VIA_ALLOCMEM, via_mem_alloc, DRM_AUTH), 735 1.1 riastrad DRM_IOCTL_DEF_DRV(VIA_FREEMEM, via_mem_free, DRM_AUTH), 736 1.1 riastrad DRM_IOCTL_DEF_DRV(VIA_AGP_INIT, via_agp_init, DRM_AUTH|DRM_MASTER), 737 1.1 riastrad DRM_IOCTL_DEF_DRV(VIA_FB_INIT, via_fb_init, DRM_AUTH|DRM_MASTER), 738 1.1 riastrad DRM_IOCTL_DEF_DRV(VIA_MAP_INIT, via_map_init, DRM_AUTH|DRM_MASTER), 739 1.1 riastrad DRM_IOCTL_DEF_DRV(VIA_DEC_FUTEX, via_decoder_futex, DRM_AUTH), 740 1.1 riastrad DRM_IOCTL_DEF_DRV(VIA_DMA_INIT, via_dma_init, DRM_AUTH), 741 1.1 riastrad DRM_IOCTL_DEF_DRV(VIA_CMDBUFFER, via_cmdbuffer, DRM_AUTH), 742 1.1 riastrad DRM_IOCTL_DEF_DRV(VIA_FLUSH, via_flush_ioctl, DRM_AUTH), 743 1.1 riastrad DRM_IOCTL_DEF_DRV(VIA_PCICMD, via_pci_cmdbuffer, DRM_AUTH), 744 1.1 riastrad DRM_IOCTL_DEF_DRV(VIA_CMDBUF_SIZE, via_cmdbuf_size, DRM_AUTH), 745 1.1 riastrad DRM_IOCTL_DEF_DRV(VIA_WAIT_IRQ, via_wait_irq, DRM_AUTH), 746 1.1 riastrad DRM_IOCTL_DEF_DRV(VIA_DMA_BLIT, via_dma_blit, DRM_AUTH), 747 1.1 riastrad DRM_IOCTL_DEF_DRV(VIA_BLIT_SYNC, via_dma_blit_sync, DRM_AUTH) 748 1.1 riastrad }; 749 1.1 riastrad 750 1.3 riastrad int via_max_ioctl = ARRAY_SIZE(via_ioctls); 751