1/* mga_dma.c -- DMA support for mga g200/g400 -*- linux-c -*- 2 * Created: Mon Dec 13 01:50:01 1999 by jhartmann@precisioninsight.com 3 * 4 * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. 5 * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. 6 * All Rights Reserved. 7 * 8 * Permission is hereby granted, free of charge, to any person obtaining a 9 * copy of this software and associated documentation files (the "Software"), 10 * to deal in the Software without restriction, including without limitation 11 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 12 * and/or sell copies of the Software, and to permit persons to whom the 13 * Software is furnished to do so, subject to the following conditions: 14 * 15 * The above copyright notice and this permission notice (including the next 16 * paragraph) shall be included in all copies or substantial portions of the 17 * Software. 18 * 19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 22 * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 23 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 24 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25 * DEALINGS IN THE SOFTWARE. 26 * 27 * Authors: Rickard E. (Rik) Faith <faith@valinux.com> 28 * Jeff Hartmann <jhartmann@valinux.com> 29 * Keith Whitwell <keithw@valinux.com> 30 * 31 */ 32 33#define __NO_VERSION__ 34#include "drmP.h" 35#include "mga_drv.h" 36 37#include <linux/interrupt.h> /* For task queue support */ 38 39#define MGA_REG(reg) 2 40#define MGA_BASE(reg) ((unsigned long) \ 41 ((drm_device_t *)dev)->maplist[MGA_REG(reg)]->handle) 42#define MGA_ADDR(reg) (MGA_BASE(reg) + reg) 43#define MGA_DEREF(reg) *(__volatile__ int *)MGA_ADDR(reg) 44#define MGA_READ(reg) MGA_DEREF(reg) 45#define MGA_WRITE(reg,val) do { MGA_DEREF(reg) = val; } while (0) 46 47#define PDEA_pagpxfer_enable 0x2 48 49static int mga_flush_queue(drm_device_t *dev); 50 51static unsigned long mga_alloc_page(drm_device_t *dev) 52{ 53 unsigned long address; 54 55 address = __get_free_page(GFP_KERNEL); 56 if(address == 0UL) { 57 return 0; 58 } 59 atomic_inc(&virt_to_page(address)->count); 60 set_bit(PG_reserved, &virt_to_page(address)->flags); 61 62 return address; 63} 64 65static void mga_free_page(drm_device_t *dev, unsigned long page) 66{ 67 if(!page) return; 68 atomic_dec(&virt_to_page(page)->count); 69 clear_bit(PG_reserved, &virt_to_page(page)->flags); 70 free_page(page); 71 return; 72} 73 74static void mga_delay(void) 75{ 76 return; 77} 78 79/* These are two age tags that will never be sent to 80 * the hardware */ 81#define MGA_BUF_USED 0xffffffff 82#define MGA_BUF_FREE 0 83 84static int mga_freelist_init(drm_device_t *dev) 85{ 86 drm_device_dma_t *dma = dev->dma; 87 drm_buf_t *buf; 88 drm_mga_buf_priv_t *buf_priv; 89 drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private; 90 drm_mga_freelist_t *item; 91 int i; 92 93 dev_priv->head = drm_alloc(sizeof(drm_mga_freelist_t), DRM_MEM_DRIVER); 94 if(dev_priv->head == NULL) return -ENOMEM; 95 memset(dev_priv->head, 0, sizeof(drm_mga_freelist_t)); 96 dev_priv->head->age = MGA_BUF_USED; 97 98 for (i = 0; i < dma->buf_count; i++) { 99 buf = dma->buflist[ i ]; 100 buf_priv = buf->dev_private; 101 item = drm_alloc(sizeof(drm_mga_freelist_t), 102 DRM_MEM_DRIVER); 103 if(item == NULL) return -ENOMEM; 104 memset(item, 0, sizeof(drm_mga_freelist_t)); 105 item->age = MGA_BUF_FREE; 106 item->prev = dev_priv->head; 107 item->next = dev_priv->head->next; 108 if(dev_priv->head->next != NULL) 109 dev_priv->head->next->prev = item; 110 if(item->next == NULL) dev_priv->tail = item; 111 item->buf = buf; 112 buf_priv->my_freelist = item; 113 buf_priv->discard = 0; 114 buf_priv->dispatched = 0; 115 dev_priv->head->next = item; 116 } 117 118 return 0; 119} 120 121static void mga_freelist_cleanup(drm_device_t *dev) 122{ 123 drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private; 124 drm_mga_freelist_t *item; 125 drm_mga_freelist_t *prev; 126 127 item = dev_priv->head; 128 while(item) { 129 prev = item; 130 item = item->next; 131 drm_free(prev, sizeof(drm_mga_freelist_t), DRM_MEM_DRIVER); 132 } 133 134 dev_priv->head = dev_priv->tail = NULL; 135} 136 137/* Frees dispatch lock */ 138static inline void mga_dma_quiescent(drm_device_t *dev) 139{ 140 drm_device_dma_t *dma = dev->dma; 141 drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private; 142 drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; 143 unsigned long end; 144 int i; 145 146 DRM_DEBUG("dispatch_status = 0x%02lx\n", dev_priv->dispatch_status); 147 end = jiffies + (HZ*3); 148 while(1) { 149 if(!test_and_set_bit(MGA_IN_DISPATCH, 150 &dev_priv->dispatch_status)) { 151 break; 152 } 153 if((signed)(end - jiffies) <= 0) { 154 DRM_ERROR("irqs: %d wanted %d\n", 155 atomic_read(&dev->total_irq), 156 atomic_read(&dma->total_lost)); 157 DRM_ERROR("lockup: dispatch_status = 0x%02lx," 158 " jiffies = %lu, end = %lu\n", 159 dev_priv->dispatch_status, jiffies, end); 160 return; 161 } 162 for (i = 0 ; i < 2000 ; i++) mga_delay(); 163 } 164 end = jiffies + (HZ*3); 165 DRM_DEBUG("quiescent status : %x\n", MGA_READ(MGAREG_STATUS)); 166 while((MGA_READ(MGAREG_STATUS) & 0x00030001) != 0x00020000) { 167 if((signed)(end - jiffies) <= 0) { 168 DRM_ERROR("irqs: %d wanted %d\n", 169 atomic_read(&dev->total_irq), 170 atomic_read(&dma->total_lost)); 171 DRM_ERROR("lockup\n"); 172 clear_bit(MGA_IN_DISPATCH, &dev_priv->dispatch_status); 173 return; 174 } 175 for (i = 0 ; i < 2000 ; i++) mga_delay(); 176 } 177 sarea_priv->dirty |= MGA_DMA_FLUSH; 178 179 clear_bit(MGA_IN_DISPATCH, &dev_priv->dispatch_status); 180 DRM_DEBUG("exit, dispatch_status = 0x%02lx\n", 181 dev_priv->dispatch_status); 182} 183 184static void mga_reset_freelist(drm_device_t *dev) 185{ 186 drm_device_dma_t *dma = dev->dma; 187 drm_buf_t *buf; 188 drm_mga_buf_priv_t *buf_priv; 189 int i; 190 191 for (i = 0; i < dma->buf_count; i++) { 192 buf = dma->buflist[ i ]; 193 buf_priv = buf->dev_private; 194 buf_priv->my_freelist->age = MGA_BUF_FREE; 195 } 196} 197 198/* Least recently used : 199 * These operations are not atomic b/c they are protected by the 200 * hardware lock */ 201 202drm_buf_t *mga_freelist_get(drm_device_t *dev) 203{ 204 DECLARE_WAITQUEUE(entry, current); 205 drm_mga_private_t *dev_priv = 206 (drm_mga_private_t *) dev->dev_private; 207 drm_mga_freelist_t *prev; 208 drm_mga_freelist_t *next; 209 static int failed = 0; 210 int return_null = 0; 211 212 if(failed >= 1000 && dev_priv->tail->age >= dev_priv->last_prim_age) { 213 DRM_DEBUG("Waiting on freelist," 214 " tail->age = %d, last_prim_age= %d\n", 215 dev_priv->tail->age, 216 dev_priv->last_prim_age); 217 add_wait_queue(&dev_priv->buf_queue, &entry); 218 set_bit(MGA_IN_GETBUF, &dev_priv->dispatch_status); 219 for (;;) { 220 current->state = TASK_INTERRUPTIBLE; 221 mga_dma_schedule(dev, 0); 222 if(dev_priv->tail->age < dev_priv->last_prim_age) 223 break; 224 atomic_inc(&dev->total_sleeps); 225 schedule(); 226 if (signal_pending(current)) { 227 ++return_null; 228 break; 229 } 230 } 231 clear_bit(MGA_IN_GETBUF, &dev_priv->dispatch_status); 232 current->state = TASK_RUNNING; 233 remove_wait_queue(&dev_priv->buf_queue, &entry); 234 if (return_null) return NULL; 235 } 236 237 if(dev_priv->tail->age < dev_priv->last_prim_age) { 238 prev = dev_priv->tail->prev; 239 next = dev_priv->tail; 240 prev->next = NULL; 241 next->prev = next->next = NULL; 242 dev_priv->tail = prev; 243 next->age = MGA_BUF_USED; 244 failed = 0; 245 return next->buf; 246 } 247 248 failed++; 249 return NULL; 250} 251 252int mga_freelist_put(drm_device_t *dev, drm_buf_t *buf) 253{ 254 drm_mga_private_t *dev_priv = 255 (drm_mga_private_t *) dev->dev_private; 256 drm_mga_buf_priv_t *buf_priv = buf->dev_private; 257 drm_mga_freelist_t *prev; 258 drm_mga_freelist_t *head; 259 drm_mga_freelist_t *next; 260 261 if(buf_priv->my_freelist->age == MGA_BUF_USED) { 262 /* Discarded buffer, put it on the tail */ 263 next = buf_priv->my_freelist; 264 next->age = MGA_BUF_FREE; 265 prev = dev_priv->tail; 266 prev->next = next; 267 next->prev = prev; 268 next->next = NULL; 269 dev_priv->tail = next; 270 } else { 271 /* Normally aged buffer, put it on the head + 1, 272 * as the real head is a sentinal element 273 */ 274 next = buf_priv->my_freelist; 275 head = dev_priv->head; 276 prev = head->next; 277 head->next = next; 278 prev->prev = next; 279 next->prev = head; 280 next->next = prev; 281 } 282 283 return 0; 284} 285 286static int mga_init_primary_bufs(drm_device_t *dev, drm_mga_init_t *init) 287{ 288 drm_mga_private_t *dev_priv = dev->dev_private; 289 drm_mga_prim_buf_t *prim_buffer; 290 int i, temp, size_of_buf; 291 int offset = init->reserved_map_agpstart; 292 293 dev_priv->primary_size = ((init->primary_size + PAGE_SIZE - 1) / 294 PAGE_SIZE) * PAGE_SIZE; 295 size_of_buf = dev_priv->primary_size / MGA_NUM_PRIM_BUFS; 296 dev_priv->warp_ucode_size = init->warp_ucode_size; 297 dev_priv->prim_bufs = drm_alloc(sizeof(drm_mga_prim_buf_t *) * 298 (MGA_NUM_PRIM_BUFS + 1), 299 DRM_MEM_DRIVER); 300 if(dev_priv->prim_bufs == NULL) { 301 DRM_ERROR("Unable to allocate memory for prim_buf\n"); 302 return -ENOMEM; 303 } 304 memset(dev_priv->prim_bufs, 305 0, sizeof(drm_mga_prim_buf_t *) * (MGA_NUM_PRIM_BUFS + 1)); 306 307 temp = init->warp_ucode_size + dev_priv->primary_size; 308 temp = ((temp + PAGE_SIZE - 1) / PAGE_SIZE) * PAGE_SIZE; 309 310 dev_priv->ioremap = drm_ioremap(dev->agp->base + offset, 311 temp); 312 if(dev_priv->ioremap == NULL) { 313 DRM_ERROR("Ioremap failed\n"); 314 return -ENOMEM; 315 } 316 init_waitqueue_head(&dev_priv->wait_queue); 317 318 for(i = 0; i < MGA_NUM_PRIM_BUFS; i++) { 319 prim_buffer = drm_alloc(sizeof(drm_mga_prim_buf_t), 320 DRM_MEM_DRIVER); 321 if(prim_buffer == NULL) return -ENOMEM; 322 memset(prim_buffer, 0, sizeof(drm_mga_prim_buf_t)); 323 prim_buffer->phys_head = offset + dev->agp->base; 324 prim_buffer->current_dma_ptr = 325 prim_buffer->head = 326 (u32 *) (dev_priv->ioremap + 327 offset - 328 init->reserved_map_agpstart); 329 prim_buffer->num_dwords = 0; 330 prim_buffer->max_dwords = size_of_buf / sizeof(u32); 331 prim_buffer->max_dwords -= 5; /* Leave room for the softrap */ 332 prim_buffer->sec_used = 0; 333 prim_buffer->idx = i; 334 prim_buffer->prim_age = i + 1; 335 offset = offset + size_of_buf; 336 dev_priv->prim_bufs[i] = prim_buffer; 337 } 338 dev_priv->current_prim_idx = 0; 339 dev_priv->next_prim = 340 dev_priv->last_prim = 341 dev_priv->current_prim = 342 dev_priv->prim_bufs[0]; 343 dev_priv->next_prim_age = 2; 344 dev_priv->last_prim_age = 1; 345 set_bit(MGA_BUF_IN_USE, &dev_priv->current_prim->buffer_status); 346 return 0; 347} 348 349void mga_fire_primary(drm_device_t *dev, drm_mga_prim_buf_t *prim) 350{ 351 drm_mga_private_t *dev_priv = dev->dev_private; 352 drm_device_dma_t *dma = dev->dma; 353 drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; 354 int use_agp = PDEA_pagpxfer_enable; 355 unsigned long end; 356 int i; 357 int next_idx; 358 PRIMLOCALS; 359 360 dev_priv->last_prim = prim; 361 362 /* We never check for overflow, b/c there is always room */ 363 PRIMPTR(prim); 364 if(num_dwords <= 0) { 365 DRM_ERROR("num_dwords == 0 when dispatched\n"); 366 goto out_prim_wait; 367 } 368 PRIMOUTREG( MGAREG_DMAPAD, 0); 369 PRIMOUTREG( MGAREG_DMAPAD, 0); 370 PRIMOUTREG( MGAREG_DMAPAD, 0); 371 PRIMOUTREG( MGAREG_SOFTRAP, 0); 372 PRIMFINISH(prim); 373 374 end = jiffies + (HZ*3); 375 if(sarea_priv->dirty & MGA_DMA_FLUSH) { 376 while((MGA_READ(MGAREG_STATUS) & 0x00030001) != 0x00020000) { 377 if((signed)(end - jiffies) <= 0) { 378 DRM_ERROR("irqs: %d wanted %d\n", 379 atomic_read(&dev->total_irq), 380 atomic_read(&dma->total_lost)); 381 DRM_ERROR("lockup (flush)\n"); 382 goto out_prim_wait; 383 } 384 385 for (i = 0 ; i < 4096 ; i++) mga_delay(); 386 } 387 sarea_priv->dirty &= ~(MGA_DMA_FLUSH); 388 } else { 389 while((MGA_READ(MGAREG_STATUS) & 0x00020001) != 0x00020000) { 390 if((signed)(end - jiffies) <= 0) { 391 DRM_ERROR("irqs: %d wanted %d\n", 392 atomic_read(&dev->total_irq), 393 atomic_read(&dma->total_lost)); 394 DRM_ERROR("lockup (wait)\n"); 395 goto out_prim_wait; 396 } 397 398 for (i = 0 ; i < 4096 ; i++) mga_delay(); 399 } 400 } 401 402 mga_flush_write_combine(); 403 atomic_inc(&dev_priv->pending_bufs); 404 MGA_WRITE(MGAREG_PRIMADDRESS, phys_head | TT_GENERAL); 405 MGA_WRITE(MGAREG_PRIMEND, (phys_head + num_dwords * 4) | use_agp); 406 prim->num_dwords = 0; 407 sarea_priv->last_enqueue = prim->prim_age; 408 409 next_idx = prim->idx + 1; 410 if(next_idx >= MGA_NUM_PRIM_BUFS) 411 next_idx = 0; 412 413 dev_priv->next_prim = dev_priv->prim_bufs[next_idx]; 414 return; 415 416 out_prim_wait: 417 prim->num_dwords = 0; 418 prim->sec_used = 0; 419 clear_bit(MGA_BUF_IN_USE, &prim->buffer_status); 420 wake_up_interruptible(&dev_priv->wait_queue); 421 clear_bit(MGA_BUF_SWAP_PENDING, &prim->buffer_status); 422 clear_bit(MGA_IN_DISPATCH, &dev_priv->dispatch_status); 423} 424 425int mga_advance_primary(drm_device_t *dev) 426{ 427 DECLARE_WAITQUEUE(entry, current); 428 drm_mga_private_t *dev_priv = dev->dev_private; 429 drm_mga_prim_buf_t *prim_buffer; 430 drm_device_dma_t *dma = dev->dma; 431 int next_prim_idx; 432 int ret = 0; 433 434 /* This needs to reset the primary buffer if available, 435 * we should collect stats on how many times it bites 436 * it's tail */ 437 438 next_prim_idx = dev_priv->current_prim_idx + 1; 439 if(next_prim_idx >= MGA_NUM_PRIM_BUFS) 440 next_prim_idx = 0; 441 prim_buffer = dev_priv->prim_bufs[next_prim_idx]; 442 set_bit(MGA_IN_WAIT, &dev_priv->dispatch_status); 443 444 /* In use is cleared in interrupt handler */ 445 446 if(test_and_set_bit(MGA_BUF_IN_USE, &prim_buffer->buffer_status)) { 447 add_wait_queue(&dev_priv->wait_queue, &entry); 448 for (;;) { 449 current->state = TASK_INTERRUPTIBLE; 450 mga_dma_schedule(dev, 0); 451 if(!test_and_set_bit(MGA_BUF_IN_USE, 452 &prim_buffer->buffer_status)) 453 break; 454 atomic_inc(&dev->total_sleeps); 455 atomic_inc(&dma->total_missed_sched); 456 schedule(); 457 if (signal_pending(current)) { 458 ret = -ERESTARTSYS; 459 break; 460 } 461 } 462 current->state = TASK_RUNNING; 463 remove_wait_queue(&dev_priv->wait_queue, &entry); 464 if(ret) return ret; 465 } 466 clear_bit(MGA_IN_WAIT, &dev_priv->dispatch_status); 467 468 /* This primary buffer is now free to use */ 469 prim_buffer->current_dma_ptr = prim_buffer->head; 470 prim_buffer->num_dwords = 0; 471 prim_buffer->sec_used = 0; 472 prim_buffer->prim_age = dev_priv->next_prim_age++; 473 if(prim_buffer->prim_age == 0 || prim_buffer->prim_age == 0xffffffff) { 474 mga_flush_queue(dev); 475 mga_dma_quiescent(dev); 476 mga_reset_freelist(dev); 477 prim_buffer->prim_age = (dev_priv->next_prim_age += 2); 478 } 479 480 /* Reset all buffer status stuff */ 481 clear_bit(MGA_BUF_NEEDS_OVERFLOW, &prim_buffer->buffer_status); 482 clear_bit(MGA_BUF_FORCE_FIRE, &prim_buffer->buffer_status); 483 clear_bit(MGA_BUF_SWAP_PENDING, &prim_buffer->buffer_status); 484 485 dev_priv->current_prim = prim_buffer; 486 dev_priv->current_prim_idx = next_prim_idx; 487 return 0; 488} 489 490/* More dynamic performance decisions */ 491static inline int mga_decide_to_fire(drm_device_t *dev) 492{ 493 drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private; 494 495 if(test_bit(MGA_BUF_FORCE_FIRE, &dev_priv->next_prim->buffer_status)) { 496 return 1; 497 } 498 499 if (test_bit(MGA_IN_GETBUF, &dev_priv->dispatch_status) && 500 dev_priv->next_prim->num_dwords) { 501 return 1; 502 } 503 504 if (test_bit(MGA_IN_FLUSH, &dev_priv->dispatch_status) && 505 dev_priv->next_prim->num_dwords) { 506 return 1; 507 } 508 509 if(atomic_read(&dev_priv->pending_bufs) <= MGA_NUM_PRIM_BUFS - 1) { 510 if(test_bit(MGA_BUF_SWAP_PENDING, 511 &dev_priv->next_prim->buffer_status)) { 512 return 1; 513 } 514 } 515 516 if(atomic_read(&dev_priv->pending_bufs) <= MGA_NUM_PRIM_BUFS / 2) { 517 if(dev_priv->next_prim->sec_used >= MGA_DMA_BUF_NR / 8) { 518 return 1; 519 } 520 } 521 522 if(atomic_read(&dev_priv->pending_bufs) >= MGA_NUM_PRIM_BUFS / 2) { 523 if(dev_priv->next_prim->sec_used >= MGA_DMA_BUF_NR / 4) { 524 return 1; 525 } 526 } 527 528 return 0; 529} 530 531int mga_dma_schedule(drm_device_t *dev, int locked) 532{ 533 drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private; 534 int retval = 0; 535 536 if (!dev_priv) return -EBUSY; 537 538 if (test_and_set_bit(0, &dev->dma_flag)) { 539 retval = -EBUSY; 540 goto sch_out_wakeup; 541 } 542 543 if(test_bit(MGA_IN_FLUSH, &dev_priv->dispatch_status) || 544 test_bit(MGA_IN_WAIT, &dev_priv->dispatch_status) || 545 test_bit(MGA_IN_GETBUF, &dev_priv->dispatch_status)) { 546 locked = 1; 547 } 548 549 if (!locked && 550 !drm_lock_take(&dev->lock.hw_lock->lock, DRM_KERNEL_CONTEXT)) { 551 clear_bit(0, &dev->dma_flag); 552 retval = -EBUSY; 553 goto sch_out_wakeup; 554 } 555 556 if(!test_and_set_bit(MGA_IN_DISPATCH, &dev_priv->dispatch_status)) { 557 /* Fire dma buffer */ 558 if(mga_decide_to_fire(dev)) { 559 clear_bit(MGA_BUF_FORCE_FIRE, 560 &dev_priv->next_prim->buffer_status); 561 if(dev_priv->current_prim == dev_priv->next_prim) { 562 /* Schedule overflow for a later time */ 563 set_bit(MGA_BUF_NEEDS_OVERFLOW, 564 &dev_priv->next_prim->buffer_status); 565 } 566 mga_fire_primary(dev, dev_priv->next_prim); 567 } else { 568 clear_bit(MGA_IN_DISPATCH, &dev_priv->dispatch_status); 569 } 570 } 571 572 if (!locked) { 573 if (drm_lock_free(dev, &dev->lock.hw_lock->lock, 574 DRM_KERNEL_CONTEXT)) { 575 DRM_ERROR("\n"); 576 } 577 } 578 579 clear_bit(0, &dev->dma_flag); 580 581sch_out_wakeup: 582 if(test_bit(MGA_IN_FLUSH, &dev_priv->dispatch_status) && 583 atomic_read(&dev_priv->pending_bufs) == 0) { 584 /* Everything has been processed by the hardware */ 585 clear_bit(MGA_IN_FLUSH, &dev_priv->dispatch_status); 586 wake_up_interruptible(&dev_priv->flush_queue); 587 } 588 589 if(test_bit(MGA_IN_GETBUF, &dev_priv->dispatch_status) 590 && dev_priv->tail->age < dev_priv->last_prim_age) 591 wake_up_interruptible(&dev_priv->buf_queue); 592 593 return retval; 594} 595 596static void mga_dma_service(int irq, void *device, struct pt_regs *regs) 597{ 598 drm_device_t *dev = (drm_device_t *)device; 599 drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private; 600 drm_mga_prim_buf_t *last_prim_buffer; 601 602 atomic_inc(&dev->total_irq); 603 if((MGA_READ(MGAREG_STATUS) & 0x00000001) != 0x00000001) return; 604 MGA_WRITE(MGAREG_ICLEAR, 0x00000001); 605 last_prim_buffer = dev_priv->last_prim; 606 last_prim_buffer->num_dwords = 0; 607 last_prim_buffer->sec_used = 0; 608 dev_priv->sarea_priv->last_dispatch = 609 dev_priv->last_prim_age = last_prim_buffer->prim_age; 610 clear_bit(MGA_BUF_IN_USE, &last_prim_buffer->buffer_status); 611 clear_bit(MGA_BUF_SWAP_PENDING, &last_prim_buffer->buffer_status); 612 clear_bit(MGA_IN_DISPATCH, &dev_priv->dispatch_status); 613 atomic_dec(&dev_priv->pending_bufs); 614 queue_task(&dev->tq, &tq_immediate); 615 mark_bh(IMMEDIATE_BH); 616 wake_up_interruptible(&dev_priv->wait_queue); 617} 618 619static void mga_dma_task_queue(void *device) 620{ 621 mga_dma_schedule((drm_device_t *)device, 0); 622} 623 624int mga_dma_cleanup(drm_device_t *dev) 625{ 626 if(dev->dev_private) { 627 drm_mga_private_t *dev_priv = 628 (drm_mga_private_t *) dev->dev_private; 629 630 if (dev->irq) mga_flush_queue(dev); 631 mga_dma_quiescent(dev); 632 633 if(dev_priv->ioremap) { 634 int temp = (dev_priv->warp_ucode_size + 635 dev_priv->primary_size + 636 PAGE_SIZE - 1) / PAGE_SIZE * PAGE_SIZE; 637 638 drm_ioremapfree((void *) dev_priv->ioremap, temp); 639 } 640 if(dev_priv->status_page != NULL) { 641 iounmap(dev_priv->status_page); 642 } 643 if(dev_priv->real_status_page != 0UL) { 644 mga_free_page(dev, dev_priv->real_status_page); 645 } 646 if(dev_priv->prim_bufs != NULL) { 647 int i; 648 for(i = 0; i < MGA_NUM_PRIM_BUFS; i++) { 649 if(dev_priv->prim_bufs[i] != NULL) { 650 drm_free(dev_priv->prim_bufs[i], 651 sizeof(drm_mga_prim_buf_t), 652 DRM_MEM_DRIVER); 653 } 654 } 655 drm_free(dev_priv->prim_bufs, sizeof(void *) * 656 (MGA_NUM_PRIM_BUFS + 1), 657 DRM_MEM_DRIVER); 658 } 659 if(dev_priv->head != NULL) { 660 mga_freelist_cleanup(dev); 661 } 662 663 664 drm_free(dev->dev_private, sizeof(drm_mga_private_t), 665 DRM_MEM_DRIVER); 666 dev->dev_private = NULL; 667 } 668 669 return 0; 670} 671 672static int mga_dma_initialize(drm_device_t *dev, drm_mga_init_t *init) { 673 drm_mga_private_t *dev_priv; 674 drm_map_t *sarea_map = NULL; 675 676 dev_priv = drm_alloc(sizeof(drm_mga_private_t), DRM_MEM_DRIVER); 677 if(dev_priv == NULL) return -ENOMEM; 678 dev->dev_private = (void *) dev_priv; 679 680 memset(dev_priv, 0, sizeof(drm_mga_private_t)); 681 682 if((init->reserved_map_idx >= dev->map_count) || 683 (init->buffer_map_idx >= dev->map_count)) { 684 mga_dma_cleanup(dev); 685 return -EINVAL; 686 } 687 688 dev_priv->reserved_map_idx = init->reserved_map_idx; 689 dev_priv->buffer_map_idx = init->buffer_map_idx; 690 sarea_map = dev->maplist[0]; 691 dev_priv->sarea_priv = (drm_mga_sarea_t *) 692 ((u8 *)sarea_map->handle + 693 init->sarea_priv_offset); 694 695 /* Scale primary size to the next page */ 696 dev_priv->chipset = init->chipset; 697 dev_priv->frontOffset = init->frontOffset; 698 dev_priv->backOffset = init->backOffset; 699 dev_priv->depthOffset = init->depthOffset; 700 dev_priv->textureOffset = init->textureOffset; 701 dev_priv->textureSize = init->textureSize; 702 dev_priv->cpp = init->cpp; 703 dev_priv->sgram = init->sgram; 704 dev_priv->stride = init->stride; 705 706 dev_priv->mAccess = init->mAccess; 707 init_waitqueue_head(&dev_priv->flush_queue); 708 init_waitqueue_head(&dev_priv->buf_queue); 709 dev_priv->WarpPipe = 0xff000000; 710 dev_priv->vertexsize = 0; 711 712 DRM_DEBUG("chipset=%d ucode_size=%d backOffset=%x depthOffset=%x\n", 713 dev_priv->chipset, dev_priv->warp_ucode_size, 714 dev_priv->backOffset, dev_priv->depthOffset); 715 DRM_DEBUG("cpp: %d sgram: %d stride: %d maccess: %x\n", 716 dev_priv->cpp, dev_priv->sgram, dev_priv->stride, 717 dev_priv->mAccess); 718 719 memcpy(&dev_priv->WarpIndex, &init->WarpIndex, 720 sizeof(drm_mga_warp_index_t) * MGA_MAX_WARP_PIPES); 721 722 if(mga_init_primary_bufs(dev, init) != 0) { 723 DRM_ERROR("Can not initialize primary buffers\n"); 724 mga_dma_cleanup(dev); 725 return -ENOMEM; 726 } 727 dev_priv->real_status_page = mga_alloc_page(dev); 728 if(dev_priv->real_status_page == 0UL) { 729 mga_dma_cleanup(dev); 730 DRM_ERROR("Can not allocate status page\n"); 731 return -ENOMEM; 732 } 733 734 dev_priv->status_page = 735 ioremap_nocache(virt_to_bus((void *)dev_priv->real_status_page), 736 PAGE_SIZE); 737 738 if(dev_priv->status_page == NULL) { 739 mga_dma_cleanup(dev); 740 DRM_ERROR("Can not remap status page\n"); 741 return -ENOMEM; 742 } 743 744 /* Write status page when secend or softrap occurs */ 745 MGA_WRITE(MGAREG_PRIMPTR, 746 virt_to_bus((void *)dev_priv->real_status_page) | 0x00000003); 747 748 749 /* Private is now filled in, initialize the hardware */ 750 { 751 PRIMLOCALS; 752 PRIMGETPTR( dev_priv ); 753 754 PRIMOUTREG(MGAREG_DMAPAD, 0); 755 PRIMOUTREG(MGAREG_DMAPAD, 0); 756 PRIMOUTREG(MGAREG_DWGSYNC, 0x0100); 757 PRIMOUTREG(MGAREG_SOFTRAP, 0); 758 /* Poll for the first buffer to insure that 759 * the status register will be correct 760 */ 761 762 mga_flush_write_combine(); 763 MGA_WRITE(MGAREG_PRIMADDRESS, phys_head | TT_GENERAL); 764 765 MGA_WRITE(MGAREG_PRIMEND, ((phys_head + num_dwords * 4) | 766 PDEA_pagpxfer_enable)); 767 768 while(MGA_READ(MGAREG_DWGSYNC) != 0x0100) ; 769 } 770 771 if(mga_freelist_init(dev) != 0) { 772 DRM_ERROR("Could not initialize freelist\n"); 773 mga_dma_cleanup(dev); 774 return -ENOMEM; 775 } 776 return 0; 777} 778 779int mga_dma_init(struct inode *inode, struct file *filp, 780 unsigned int cmd, unsigned long arg) 781{ 782 drm_file_t *priv = filp->private_data; 783 drm_device_t *dev = priv->dev; 784 drm_mga_init_t init; 785 786 if (copy_from_user(&init, (drm_mga_init_t *)arg, sizeof(init))) 787 return -EFAULT; 788 789 switch(init.func) { 790 case MGA_INIT_DMA: 791 return mga_dma_initialize(dev, &init); 792 case MGA_CLEANUP_DMA: 793 return mga_dma_cleanup(dev); 794 } 795 796 return -EINVAL; 797} 798 799int mga_irq_install(drm_device_t *dev, int irq) 800{ 801 int retcode; 802 803 if (!irq) return -EINVAL; 804 805 down(&dev->struct_sem); 806 if (dev->irq) { 807 up(&dev->struct_sem); 808 return -EBUSY; 809 } 810 dev->irq = irq; 811 up(&dev->struct_sem); 812 813 DRM_DEBUG("install irq handler %d\n", irq); 814 815 dev->context_flag = 0; 816 dev->interrupt_flag = 0; 817 dev->dma_flag = 0; 818 dev->dma->next_buffer = NULL; 819 dev->dma->next_queue = NULL; 820 dev->dma->this_buffer = NULL; 821 INIT_LIST_HEAD(&dev->tq.list); 822 dev->tq.sync = 0; 823 dev->tq.routine = mga_dma_task_queue; 824 dev->tq.data = dev; 825 826 /* Before installing handler */ 827 MGA_WRITE(MGAREG_IEN, 0); 828 /* Install handler */ 829 if ((retcode = request_irq(dev->irq, 830 mga_dma_service, 831 SA_SHIRQ, 832 dev->devname, 833 dev))) { 834 down(&dev->struct_sem); 835 dev->irq = 0; 836 up(&dev->struct_sem); 837 return retcode; 838 } 839 /* After installing handler */ 840 MGA_WRITE(MGAREG_ICLEAR, 0x00000001); 841 MGA_WRITE(MGAREG_IEN, 0x00000001); 842 return 0; 843} 844 845int mga_irq_uninstall(drm_device_t *dev) 846{ 847 int irq; 848 849 down(&dev->struct_sem); 850 irq = dev->irq; 851 dev->irq = 0; 852 up(&dev->struct_sem); 853 854 if (!irq) return -EINVAL; 855 DRM_DEBUG("remove irq handler %d\n", irq); 856 MGA_WRITE(MGAREG_ICLEAR, 0x00000001); 857 MGA_WRITE(MGAREG_IEN, 0); 858 free_irq(irq, dev); 859 return 0; 860} 861 862int mga_control(struct inode *inode, struct file *filp, unsigned int cmd, 863 unsigned long arg) 864{ 865 drm_file_t *priv = filp->private_data; 866 drm_device_t *dev = priv->dev; 867 drm_control_t ctl; 868 869 if (copy_from_user(&ctl, (drm_control_t *)arg, sizeof(ctl))) 870 return -EFAULT; 871 872 switch (ctl.func) { 873 case DRM_INST_HANDLER: 874 return mga_irq_install(dev, ctl.irq); 875 case DRM_UNINST_HANDLER: 876 return mga_irq_uninstall(dev); 877 default: 878 return -EINVAL; 879 } 880} 881 882static int mga_flush_queue(drm_device_t *dev) 883{ 884 DECLARE_WAITQUEUE(entry, current); 885 drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private; 886 int ret = 0; 887 888 if(!dev_priv) return 0; 889 890 if(dev_priv->next_prim->num_dwords != 0) { 891 add_wait_queue(&dev_priv->flush_queue, &entry); 892 if (test_bit(MGA_IN_FLUSH, &dev_priv->dispatch_status)) 893 DRM_ERROR("Incorrect mga_flush_queue logic\n"); 894 set_bit(MGA_IN_FLUSH, &dev_priv->dispatch_status); 895 mga_dma_schedule(dev, 0); 896 for (;;) { 897 current->state = TASK_INTERRUPTIBLE; 898 if (!test_bit(MGA_IN_FLUSH, 899 &dev_priv->dispatch_status)) 900 break; 901 atomic_inc(&dev->total_sleeps); 902 schedule(); 903 if (signal_pending(current)) { 904 ret = -EINTR; /* Can't restart */ 905 clear_bit(MGA_IN_FLUSH, 906 &dev_priv->dispatch_status); 907 break; 908 } 909 } 910 current->state = TASK_RUNNING; 911 remove_wait_queue(&dev_priv->flush_queue, &entry); 912 } 913 return ret; 914} 915 916/* Must be called with the lock held */ 917void mga_reclaim_buffers(drm_device_t *dev, pid_t pid) 918{ 919 drm_device_dma_t *dma = dev->dma; 920 int i; 921 922 if (!dma) return; 923 if(dev->dev_private == NULL) return; 924 if(dma->buflist == NULL) return; 925 926 DRM_DEBUG("buf_count=%d\n", dma->buf_count); 927 928 mga_flush_queue(dev); 929 930 for (i = 0; i < dma->buf_count; i++) { 931 drm_buf_t *buf = dma->buflist[ i ]; 932 drm_mga_buf_priv_t *buf_priv = buf->dev_private; 933 934 /* Only buffers that need to get reclaimed ever 935 * get set to free 936 */ 937 if (buf->pid == pid && buf_priv) { 938 if(buf_priv->my_freelist->age == MGA_BUF_USED) 939 buf_priv->my_freelist->age = MGA_BUF_FREE; 940 } 941 } 942} 943 944int mga_lock(struct inode *inode, struct file *filp, unsigned int cmd, 945 unsigned long arg) 946{ 947 drm_file_t *priv = filp->private_data; 948 drm_device_t *dev = priv->dev; 949 DECLARE_WAITQUEUE(entry, current); 950 int ret = 0; 951 drm_lock_t lock; 952 953 if (copy_from_user(&lock, (drm_lock_t *)arg, sizeof(lock))) 954 return -EFAULT; 955 956 if (lock.context == DRM_KERNEL_CONTEXT) { 957 DRM_ERROR("Process %d using kernel context %d\n", 958 current->pid, lock.context); 959 return -EINVAL; 960 } 961 962 if (lock.context < 0) return -EINVAL; 963 964 /* Only one queue: 965 */ 966 967 if (!ret) { 968 add_wait_queue(&dev->lock.lock_queue, &entry); 969 for (;;) { 970 current->state = TASK_INTERRUPTIBLE; 971 if (!dev->lock.hw_lock) { 972 /* Device has been unregistered */ 973 ret = -EINTR; 974 break; 975 } 976 if (drm_lock_take(&dev->lock.hw_lock->lock, 977 lock.context)) { 978 dev->lock.pid = current->pid; 979 dev->lock.lock_time = jiffies; 980 atomic_inc(&dev->total_locks); 981 break; /* Got lock */ 982 } 983 984 /* Contention */ 985 atomic_inc(&dev->total_sleeps); 986 schedule(); 987 if (signal_pending(current)) { 988 ret = -ERESTARTSYS; 989 break; 990 } 991 } 992 current->state = TASK_RUNNING; 993 remove_wait_queue(&dev->lock.lock_queue, &entry); 994 } 995 996 if (!ret) { 997 sigemptyset(&dev->sigmask); 998 sigaddset(&dev->sigmask, SIGSTOP); 999 sigaddset(&dev->sigmask, SIGTSTP); 1000 sigaddset(&dev->sigmask, SIGTTIN); 1001 sigaddset(&dev->sigmask, SIGTTOU); 1002 dev->sigdata.context = lock.context; 1003 dev->sigdata.lock = dev->lock.hw_lock; 1004 block_all_signals(drm_notifier, &dev->sigdata, &dev->sigmask); 1005 1006 if (lock.flags & _DRM_LOCK_QUIESCENT) { 1007 DRM_DEBUG("_DRM_LOCK_QUIESCENT\n"); 1008 mga_flush_queue(dev); 1009 mga_dma_quiescent(dev); 1010 } 1011 } 1012 1013 if (ret) DRM_DEBUG("%d %s\n", lock.context, 1014 ret ? "interrupted" : "has lock"); 1015 return ret; 1016} 1017 1018int mga_flush_ioctl(struct inode *inode, struct file *filp, 1019 unsigned int cmd, unsigned long arg) 1020{ 1021 drm_file_t *priv = filp->private_data; 1022 drm_device_t *dev = priv->dev; 1023 drm_lock_t lock; 1024 drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private; 1025 1026 if (copy_from_user(&lock, (drm_lock_t *)arg, sizeof(lock))) 1027 return -EFAULT; 1028 1029 if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) { 1030 DRM_ERROR("lock not held\n"); 1031 return -EINVAL; 1032 } 1033 1034 if(lock.flags & _DRM_LOCK_FLUSH || lock.flags & _DRM_LOCK_FLUSH_ALL) { 1035 drm_mga_prim_buf_t *temp_buf; 1036 1037 temp_buf = dev_priv->current_prim; 1038 1039 if(temp_buf && temp_buf->num_dwords) { 1040 set_bit(MGA_BUF_FORCE_FIRE, &temp_buf->buffer_status); 1041 mga_advance_primary(dev); 1042 } 1043 mga_dma_schedule(dev, 1); 1044 } 1045 if(lock.flags & _DRM_LOCK_QUIESCENT) { 1046 mga_flush_queue(dev); 1047 mga_dma_quiescent(dev); 1048 } 1049 1050 return 0; 1051} 1052