diff options
author | Jeff Hartmann <jhartmann@valinux.com> | 2000-05-05 21:17:13 +0000 |
---|---|---|
committer | Jeff Hartmann <jhartmann@valinux.com> | 2000-05-05 21:17:13 +0000 |
commit | fed8c1a177184b192346045c626dfa4e89df27db (patch) | |
tree | 1467326481d664ca91ced8afbbd1d9f34a99b043 /linux | |
parent | c6e6ec0acef2a4fdaa15395bf369a0dc75ded185 (diff) |
Added option to enable 3dnow in the host.def file. Enabled by default in
our host.def file.
Turned on G200.
Major rewrite of how the kernel module deals with primary/secondary
buffers.
Added fastpath asm that was posted on the Utah-GLX devel list.
Audit of use of int's when they should be unsigned int's.
-Jeff
Diffstat (limited to 'linux')
-rw-r--r-- | linux/mga_dma.c | 292 | ||||
-rw-r--r-- | linux/mga_drm.h | 38 | ||||
-rw-r--r-- | linux/mga_drv.h | 42 | ||||
-rw-r--r-- | linux/mga_state.c | 198 |
4 files changed, 268 insertions, 302 deletions
diff --git a/linux/mga_dma.c b/linux/mga_dma.c index d918aff1..fe6a7b52 100644 --- a/linux/mga_dma.c +++ b/linux/mga_dma.c @@ -53,6 +53,7 @@ static unsigned long mga_alloc_page(drm_device_t *dev) { unsigned long address; + DRM_DEBUG("%s\n", __FUNCTION__); address = __get_free_page(GFP_KERNEL); if(address == 0UL) { return 0; @@ -65,6 +66,8 @@ static unsigned long mga_alloc_page(drm_device_t *dev) static void mga_free_page(drm_device_t *dev, unsigned long page) { + DRM_DEBUG("%s\n", __FUNCTION__); + if(page == 0UL) { return; } @@ -80,9 +83,11 @@ static void mga_delay(void) return; } -static void mga_flush_write_combine(void) +void mga_flush_write_combine(void) { int xchangeDummy; + DRM_DEBUG("%s\n", __FUNCTION__); + __asm__ volatile(" push %%eax ; xchg %%eax, %0 ; pop %%eax" : : "m" (xchangeDummy)); __asm__ volatile(" push %%eax ; push %%ebx ; push %%ecx ; push %%edx ;" " movl $0,%%eax ; cpuid ; pop %%edx ; pop %%ecx ; pop %%ebx ;" @@ -94,18 +99,6 @@ static void mga_flush_write_combine(void) #define MGA_BUF_USED 0xffffffff #define MGA_BUF_FREE 0 -static void mga_freelist_debug(drm_mga_freelist_t *item) -{ - if(item->buf != NULL) { - DRM_DEBUG("buf index : %d\n", item->buf->idx); - } else { - DRM_DEBUG("Freelist head\n"); - } - DRM_DEBUG("item->age : %x\n", item->age); - DRM_DEBUG("item->next : %p\n", item->next); - DRM_DEBUG("item->prev : %p\n", item->prev); -} - static int mga_freelist_init(drm_device_t *dev) { drm_device_dma_t *dma = dev->dma; @@ -114,7 +107,9 @@ static int mga_freelist_init(drm_device_t *dev) drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private; drm_mga_freelist_t *item; int i; - + + DRM_DEBUG("%s\n", __FUNCTION__); + dev_priv->head = drm_alloc(sizeof(drm_mga_freelist_t), DRM_MEM_DRIVER); if(dev_priv->head == NULL) return -ENOMEM; memset(dev_priv->head, 0, sizeof(drm_mga_freelist_t)); @@ -136,19 +131,10 @@ static int mga_freelist_init(drm_device_t *dev) item->buf = buf; buf_priv->my_freelist = item; buf_priv->discard = 0; + buf_priv->dispatched = 0; dev_priv->head->next = item; } - item = dev_priv->head; - while(item) { - mga_freelist_debug(item); - item = item->next; - } - DRM_DEBUG("Head\n"); - mga_freelist_debug(dev_priv->head); - DRM_DEBUG("Tail\n"); - mga_freelist_debug(dev_priv->tail); - return 0; } @@ -158,6 +144,8 @@ static void mga_freelist_cleanup(drm_device_t *dev) drm_mga_freelist_t *item; drm_mga_freelist_t *prev; + DRM_DEBUG("%s\n", __FUNCTION__); + item = dev_priv->head; while(item) { prev = item; @@ -174,11 +162,10 @@ static inline void mga_dma_quiescent(drm_device_t *dev) drm_device_dma_t *dma = dev->dma; drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private; drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; - __volatile__ unsigned int *status = - (__volatile__ unsigned int *)dev_priv->status_page; unsigned long end; int i; + DRM_DEBUG("%s\n", __FUNCTION__); end = jiffies + (HZ*3); while(1) { if(!test_and_set_bit(MGA_IN_DISPATCH, @@ -206,8 +193,6 @@ static inline void mga_dma_quiescent(drm_device_t *dev) } for (i = 0 ; i < 2000 ; i++) mga_delay(); } - DRM_DEBUG("status[1] : %x last_sync_tag : %x\n", status[1], - dev_priv->last_sync_tag); sarea_priv->dirty |= MGA_DMA_FLUSH; out_status: @@ -215,42 +200,18 @@ out_status: out_nolock: } -#define FREELIST_INITIAL (MGA_DMA_BUF_NR * 2) -#define FREELIST_COMPARE(age) ((age >> 2)) - -unsigned int mga_create_sync_tag(drm_device_t *dev) +static void mga_reset_freelist(drm_device_t *dev) { - drm_mga_private_t *dev_priv = - (drm_mga_private_t *) dev->dev_private; - unsigned int temp; - drm_buf_t *buf; + drm_device_dma_t *dma = dev->dma; + drm_buf_t *buf; drm_mga_buf_priv_t *buf_priv; - drm_device_dma_t *dma = dev->dma; - int i; - - dev_priv->sync_tag++; - - if(dev_priv->sync_tag < FREELIST_INITIAL) { - dev_priv->sync_tag = FREELIST_INITIAL; - } - if(dev_priv->sync_tag > 0x3fffffff) { - mga_flush_queue(dev); - mga_dma_quiescent(dev); - - for (i = 0; i < dma->buf_count; i++) { - buf = dma->buflist[ i ]; - buf_priv = buf->dev_private; - buf_priv->my_freelist->age = MGA_BUF_FREE; - } - - dev_priv->sync_tag = FREELIST_INITIAL; - } - temp = dev_priv->sync_tag << 2; - - dev_priv->sarea_priv->last_enqueue = temp; + int i; - DRM_DEBUG("sync_tag : %x\n", temp); - return temp; + for (i = 0; i < dma->buf_count; i++) { + buf = dma->buflist[ i ]; + buf_priv = buf->dev_private; + buf_priv->my_freelist->age = MGA_BUF_FREE; + } } /* Least recently used : @@ -259,23 +220,52 @@ unsigned int mga_create_sync_tag(drm_device_t *dev) drm_buf_t *mga_freelist_get(drm_device_t *dev) { + DECLARE_WAITQUEUE(entry, current); drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private; - __volatile__ unsigned int *status = - (__volatile__ unsigned int *)dev_priv->status_page; drm_mga_freelist_t *prev; drm_mga_freelist_t *next; + static int failed = 0; + + DRM_DEBUG("%s : tail->age : %d last_prim_age : %d\n", __FUNCTION__, + dev_priv->tail->age, dev_priv->last_prim_age); - if((dev_priv->tail->age >> 2) <= FREELIST_COMPARE(status[1])) { + if(failed >= 1000 && dev_priv->tail->age >= dev_priv->last_prim_age) { + DRM_DEBUG("I'm waiting on the freelist!!! %d\n", + dev_priv->last_prim_age); + set_bit(MGA_IN_GETBUF, &dev_priv->dispatch_status); + current->state = TASK_INTERRUPTIBLE; + add_wait_queue(&dev_priv->buf_queue, &entry); + for (;;) { + mga_dma_schedule(dev, 0); + if(!test_bit(MGA_IN_GETBUF, + &dev_priv->dispatch_status)) + break; + atomic_inc(&dev->total_sleeps); + schedule(); + if (signal_pending(current)) { + clear_bit(MGA_IN_GETBUF, + &dev_priv->dispatch_status); + goto failed_getbuf; + } + } + current->state = TASK_RUNNING; + remove_wait_queue(&dev_priv->buf_queue, &entry); + } + + if(dev_priv->tail->age < dev_priv->last_prim_age) { prev = dev_priv->tail->prev; next = dev_priv->tail; prev->next = NULL; next->prev = next->next = NULL; dev_priv->tail = prev; next->age = MGA_BUF_USED; + failed = 0; return next->buf; - } + } +failed_getbuf: + failed++; return NULL; } @@ -288,6 +278,8 @@ int mga_freelist_put(drm_device_t *dev, drm_buf_t *buf) drm_mga_freelist_t *head; drm_mga_freelist_t *next; + DRM_DEBUG("%s\n", __FUNCTION__); + if(buf_priv->my_freelist->age == MGA_BUF_USED) { /* Discarded buffer, put it on the tail */ next = buf_priv->my_freelist; @@ -314,34 +306,6 @@ int mga_freelist_put(drm_device_t *dev, drm_buf_t *buf) return 0; } -static void mga_print_all_primary(drm_device_t *dev) -{ -#if 0 - drm_mga_private_t *dev_priv = dev->dev_private; - drm_mga_prim_buf_t *prim; - int i; - - DRM_DEBUG("Full list of primarys\n"); - for(i = 0; i < MGA_NUM_PRIM_BUFS; i++) { - prim = dev_priv->prim_bufs[i]; - DRM_DEBUG("index : %d num_dwords : %d " - "max_dwords : %d phy_head : %x\n", - prim->idx, prim->num_dwords, - prim->max_dwords, prim->phys_head); - DRM_DEBUG("sec_used : %d swap_pending : %x " - "in_use : %x force_fire : %d\n", - prim->sec_used, prim->swap_pending, - prim->in_use, atomic_read(&prim->force_fire)); - DRM_DEBUG("needs_overflow : %d\n", - atomic_read(&prim->needs_overflow)); - } - - DRM_DEBUG("current_idx : %d, next_idx : %d, last_idx : %d\n", - dev_priv->next_prim->idx, dev_priv->last_prim->idx, - dev_priv->current_prim->idx); -#endif -} - static int mga_init_primary_bufs(drm_device_t *dev, drm_mga_init_t *init) { drm_mga_private_t *dev_priv = dev->dev_private; @@ -349,10 +313,9 @@ static int mga_init_primary_bufs(drm_device_t *dev, drm_mga_init_t *init) int i, temp, size_of_buf; int offset = init->reserved_map_agpstart; - DRM_DEBUG("mga_init_primary_bufs\n"); + DRM_DEBUG("%s\n", __FUNCTION__); dev_priv->primary_size = ((init->primary_size + PAGE_SIZE - 1) / PAGE_SIZE) * PAGE_SIZE; - DRM_DEBUG("primary_size\n"); size_of_buf = dev_priv->primary_size / MGA_NUM_PRIM_BUFS; dev_priv->warp_ucode_size = init->warp_ucode_size; dev_priv->prim_bufs = drm_alloc(sizeof(drm_mga_prim_buf_t *) * @@ -362,18 +325,12 @@ static int mga_init_primary_bufs(drm_device_t *dev, drm_mga_init_t *init) DRM_ERROR("Unable to allocate memory for prim_buf\n"); return -ENOMEM; } - DRM_DEBUG("memset\n"); memset(dev_priv->prim_bufs, 0, sizeof(drm_mga_prim_buf_t *) * (MGA_NUM_PRIM_BUFS + 1)); temp = init->warp_ucode_size + dev_priv->primary_size; temp = ((temp + PAGE_SIZE - 1) / PAGE_SIZE) * PAGE_SIZE; - DRM_DEBUG("temp : %x\n", temp); - DRM_DEBUG("dev->agp->base: %lx\n", dev->agp->base); - DRM_DEBUG("init->reserved_map_agpstart: %x\n", - init->reserved_map_agpstart); - DRM_DEBUG("ioremap\n"); dev_priv->ioremap = drm_ioremap(dev->agp->base + offset, temp); if(dev_priv->ioremap == NULL) { @@ -383,11 +340,9 @@ static int mga_init_primary_bufs(drm_device_t *dev, drm_mga_init_t *init) init_waitqueue_head(&dev_priv->wait_queue); for(i = 0; i < MGA_NUM_PRIM_BUFS; i++) { - DRM_DEBUG("For loop\n"); prim_buffer = drm_alloc(sizeof(drm_mga_prim_buf_t), DRM_MEM_DRIVER); if(prim_buffer == NULL) return -ENOMEM; - DRM_DEBUG("memset\n"); memset(prim_buffer, 0, sizeof(drm_mga_prim_buf_t)); prim_buffer->phys_head = offset + dev->agp->base; prim_buffer->current_dma_ptr = @@ -400,17 +355,18 @@ static int mga_init_primary_bufs(drm_device_t *dev, drm_mga_init_t *init) prim_buffer->max_dwords -= 5; /* Leave room for the softrap */ prim_buffer->sec_used = 0; prim_buffer->idx = i; + prim_buffer->prim_age = i + 1; offset = offset + size_of_buf; dev_priv->prim_bufs[i] = prim_buffer; - DRM_DEBUG("Looping\n"); } dev_priv->current_prim_idx = 0; dev_priv->next_prim = dev_priv->last_prim = dev_priv->current_prim = dev_priv->prim_bufs[0]; + dev_priv->next_prim_age = 2; + dev_priv->last_prim_age = 1; set_bit(MGA_BUF_IN_USE, &dev_priv->current_prim->buffer_status); - DRM_DEBUG("init done\n"); return 0; } @@ -424,9 +380,8 @@ void mga_fire_primary(drm_device_t *dev, drm_mga_prim_buf_t *prim) int i; int next_idx; PRIMLOCALS; - - DRM_DEBUG("mga_fire_primary\n"); - dev_priv->last_sync_tag = mga_create_sync_tag(dev); + + DRM_DEBUG("%s\n", __FUNCTION__); dev_priv->last_prim = prim; /* We never check for overflow, b/c there is always room */ @@ -437,7 +392,7 @@ void mga_fire_primary(drm_device_t *dev, drm_mga_prim_buf_t *prim) } PRIMOUTREG( MGAREG_DMAPAD, 0); PRIMOUTREG( MGAREG_DMAPAD, 0); - PRIMOUTREG( MGAREG_DWGSYNC, dev_priv->last_sync_tag); + PRIMOUTREG( MGAREG_DMAPAD, 0); PRIMOUTREG( MGAREG_SOFTRAP, 0); PRIMFINISH(prim); @@ -472,13 +427,13 @@ void mga_fire_primary(drm_device_t *dev, drm_mga_prim_buf_t *prim) for (i = 0 ; i < 4096 ; i++) mga_delay(); } } - + mga_flush_write_combine(); atomic_inc(&dev_priv->pending_bufs); - atomic_inc(&dma->total_lost); MGA_WRITE(MGAREG_PRIMADDRESS, phys_head | TT_GENERAL); MGA_WRITE(MGAREG_PRIMEND, (phys_head + num_dwords * 4) | use_agp); prim->num_dwords = 0; + sarea_priv->last_enqueue = prim->prim_age; next_idx = prim->idx + 1; if(next_idx >= MGA_NUM_PRIM_BUFS) @@ -494,7 +449,6 @@ void mga_fire_primary(drm_device_t *dev, drm_mga_prim_buf_t *prim) wake_up_interruptible(&dev_priv->wait_queue); clear_bit(MGA_BUF_SWAP_PENDING, &prim->buffer_status); clear_bit(MGA_IN_DISPATCH, &dev_priv->dispatch_status); - atomic_dec(&dev_priv->pending_bufs); } int mga_advance_primary(drm_device_t *dev) @@ -509,6 +463,7 @@ int mga_advance_primary(drm_device_t *dev) /* This needs to reset the primary buffer if available, * we should collect stats on how many times it bites * it's tail */ + DRM_DEBUG("%s\n", __FUNCTION__); next_prim_idx = dev_priv->current_prim_idx + 1; if(next_prim_idx >= MGA_NUM_PRIM_BUFS) @@ -520,18 +475,16 @@ int mga_advance_primary(drm_device_t *dev) if(test_and_set_bit(MGA_BUF_IN_USE, &prim_buffer->buffer_status)) { add_wait_queue(&dev_priv->wait_queue, &entry); + current->state = TASK_INTERRUPTIBLE; + for (;;) { - current->state = TASK_INTERRUPTIBLE; mga_dma_schedule(dev, 0); if(!test_and_set_bit(MGA_BUF_IN_USE, &prim_buffer->buffer_status)) break; atomic_inc(&dev->total_sleeps); atomic_inc(&dma->total_missed_sched); - mga_print_all_primary(dev); - DRM_DEBUG("Schedule in advance\n"); - /* Three second delay */ - schedule_timeout(HZ*3); + schedule(); if (signal_pending(current)) { ret = -ERESTARTSYS; break; @@ -547,6 +500,14 @@ int mga_advance_primary(drm_device_t *dev) prim_buffer->current_dma_ptr = prim_buffer->head; prim_buffer->num_dwords = 0; prim_buffer->sec_used = 0; + prim_buffer->prim_age = dev_priv->next_prim_age++; + if(prim_buffer->prim_age == 0 || prim_buffer->prim_age == 0xffffffff) { + mga_flush_queue(dev); + mga_dma_quiescent(dev); + mga_reset_freelist(dev); + prim_buffer->prim_age = (dev_priv->next_prim_age += 2); + } + /* Reset all buffer status stuff */ clear_bit(MGA_BUF_NEEDS_OVERFLOW, &prim_buffer->buffer_status); clear_bit(MGA_BUF_FORCE_FIRE, &prim_buffer->buffer_status); @@ -554,8 +515,6 @@ int mga_advance_primary(drm_device_t *dev) dev_priv->current_prim = prim_buffer; dev_priv->current_prim_idx = next_prim_idx; - DRM_DEBUG("Primarys at advance\n"); - mga_print_all_primary(dev); return 0; } @@ -564,12 +523,20 @@ static inline int mga_decide_to_fire(drm_device_t *dev) { drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private; drm_device_dma_t *dma = dev->dma; - + + DRM_DEBUG("%s\n", __FUNCTION__); + if(test_bit(MGA_BUF_FORCE_FIRE, &dev_priv->next_prim->buffer_status)) { atomic_inc(&dma->total_prio); return 1; } + if (test_bit(MGA_IN_GETBUF, &dev_priv->dispatch_status) && + dev_priv->next_prim->num_dwords) { + atomic_inc(&dma->total_prio); + return 1; + } + if (test_bit(MGA_IN_FLUSH, &dev_priv->dispatch_status) && dev_priv->next_prim->num_dwords) { atomic_inc(&dma->total_prio); @@ -612,10 +579,11 @@ int mga_dma_schedule(drm_device_t *dev, int locked) return -EBUSY; } - DRM_DEBUG("mga_dma_schedule\n"); + DRM_DEBUG("%s\n", __FUNCTION__); if(test_bit(MGA_IN_FLUSH, &dev_priv->dispatch_status) || - test_bit(MGA_IN_WAIT, &dev_priv->dispatch_status)) { + test_bit(MGA_IN_WAIT, &dev_priv->dispatch_status) || + test_bit(MGA_IN_GETBUF, &dev_priv->dispatch_status)) { locked = 1; } @@ -623,6 +591,7 @@ int mga_dma_schedule(drm_device_t *dev, int locked) !drm_lock_take(&dev->lock.hw_lock->lock, DRM_KERNEL_CONTEXT)) { atomic_inc(&dma->total_missed_lock); clear_bit(0, &dev->dma_flag); + DRM_DEBUG("Not locked\n"); return -EBUSY; } DRM_DEBUG("I'm locked\n"); @@ -630,7 +599,6 @@ int mga_dma_schedule(drm_device_t *dev, int locked) if(!test_and_set_bit(MGA_IN_DISPATCH, &dev_priv->dispatch_status)) { /* Fire dma buffer */ if(mga_decide_to_fire(dev)) { - DRM_DEBUG("mga_fire_primary\n"); DRM_DEBUG("idx :%d\n", dev_priv->next_prim->idx); clear_bit(MGA_BUF_FORCE_FIRE, &dev_priv->next_prim->buffer_status); @@ -654,16 +622,26 @@ int mga_dma_schedule(drm_device_t *dev, int locked) } } - clear_bit(0, &dev->dma_flag); if(test_bit(MGA_IN_FLUSH, &dev_priv->dispatch_status) && - dev_priv->next_prim->num_dwords == 0) { - /* Everything is on the hardware */ - DRM_DEBUG("Primarys at Flush\n"); - mga_print_all_primary(dev); + dev_priv->next_prim->num_dwords == 0 && + atomic_read(&dev_priv->pending_bufs) == 0) { + /* Everything has been processed by the hardware */ clear_bit(MGA_IN_FLUSH, &dev_priv->dispatch_status); wake_up_interruptible(&dev_priv->flush_queue); } + if(test_bit(MGA_IN_GETBUF, &dev_priv->dispatch_status) && + dev_priv->tail->age < dev_priv->last_prim_age) { + clear_bit(MGA_IN_GETBUF, &dev_priv->dispatch_status); + DRM_DEBUG("Waking up buf queue\n"); + wake_up_interruptible(&dev_priv->buf_queue); + } else if (test_bit(MGA_IN_GETBUF, &dev_priv->dispatch_status)) { + DRM_DEBUG("Not waking buf_queue on %d %d\n", + atomic_read(&dev->total_irq), + dev_priv->last_prim_age); + } + + clear_bit(0, &dev->dma_flag); return 0; } @@ -672,32 +650,35 @@ static void mga_dma_service(int irq, void *device, struct pt_regs *regs) drm_device_t *dev = (drm_device_t *)device; drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private; drm_mga_prim_buf_t *last_prim_buffer; - __volatile__ unsigned int *status = - (__volatile__ unsigned int *)dev_priv->status_page; - + + DRM_DEBUG("%s\n", __FUNCTION__); atomic_inc(&dev->total_irq); if((MGA_READ(MGAREG_STATUS) & 0x00000001) != 0x00000001) return; MGA_WRITE(MGAREG_ICLEAR, 0x00000001); last_prim_buffer = dev_priv->last_prim; last_prim_buffer->num_dwords = 0; last_prim_buffer->sec_used = 0; + dev_priv->sarea_priv->last_dispatch = + dev_priv->last_prim_age = last_prim_buffer->prim_age; clear_bit(MGA_BUF_IN_USE, &last_prim_buffer->buffer_status); wake_up_interruptible(&dev_priv->wait_queue); clear_bit(MGA_BUF_SWAP_PENDING, &last_prim_buffer->buffer_status); clear_bit(MGA_IN_DISPATCH, &dev_priv->dispatch_status); atomic_dec(&dev_priv->pending_bufs); - dev_priv->sarea_priv->last_dispatch = status[1]; queue_task(&dev->tq, &tq_immediate); mark_bh(IMMEDIATE_BH); } static void mga_dma_task_queue(void *device) { + DRM_DEBUG("%s\n", __FUNCTION__); mga_dma_schedule((drm_device_t *)device, 0); } int mga_dma_cleanup(drm_device_t *dev) { + DRM_DEBUG("%s\n", __FUNCTION__); + if(dev->dev_private) { drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private; @@ -746,12 +727,12 @@ static int mga_dma_initialize(drm_device_t *dev, drm_mga_init_t *init) { drm_map_t *sarea_map = NULL; int i; + DRM_DEBUG("%s\n", __FUNCTION__); + dev_priv = drm_alloc(sizeof(drm_mga_private_t), DRM_MEM_DRIVER); if(dev_priv == NULL) return -ENOMEM; dev->dev_private = (void *) dev_priv; - DRM_DEBUG("dev_private\n"); - memset(dev_priv, 0, sizeof(drm_mga_private_t)); if((init->reserved_map_idx >= dev->map_count) || @@ -767,7 +748,6 @@ static int mga_dma_initialize(drm_device_t *dev, drm_mga_init_t *init) { dev_priv->sarea_priv = (drm_mga_sarea_t *) ((u8 *)sarea_map->handle + init->sarea_priv_offset); - DRM_DEBUG("sarea_priv\n"); /* Scale primary size to the next page */ dev_priv->chipset = init->chipset; @@ -782,6 +762,7 @@ static int mga_dma_initialize(drm_device_t *dev, drm_mga_init_t *init) { dev_priv->mAccess = init->mAccess; init_waitqueue_head(&dev_priv->flush_queue); + init_waitqueue_head(&dev_priv->buf_queue); dev_priv->WarpPipe = -1; DRM_DEBUG("chipset: %d ucode_size: %d backOffset: %x depthOffset: %x\n", @@ -801,20 +782,17 @@ static int mga_dma_initialize(drm_device_t *dev, drm_mga_init_t *init) { dev_priv->WarpIndex[i].phys_addr, dev_priv->WarpIndex[i].size); - DRM_DEBUG("Doing init prim buffers\n"); if(mga_init_primary_bufs(dev, init) != 0) { DRM_ERROR("Can not initialize primary buffers\n"); mga_dma_cleanup(dev); return -ENOMEM; } - DRM_DEBUG("Done with init prim buffers\n"); dev_priv->real_status_page = mga_alloc_page(dev); if(dev_priv->real_status_page == 0UL) { mga_dma_cleanup(dev); DRM_ERROR("Can not allocate status page\n"); return -ENOMEM; } - DRM_DEBUG("Status page at %lx\n", dev_priv->real_status_page); dev_priv->status_page = ioremap_nocache(virt_to_bus((void *)dev_priv->real_status_page), @@ -826,31 +804,23 @@ static int mga_dma_initialize(drm_device_t *dev, drm_mga_init_t *init) { return -ENOMEM; } - DRM_DEBUG("Status page remapped to %p\n", dev_priv->status_page); /* Write status page when secend or softrap occurs */ MGA_WRITE(MGAREG_PRIMPTR, virt_to_bus((void *)dev_priv->real_status_page) | 0x00000003); - DRM_DEBUG("dma initialization\n"); /* Private is now filled in, initialize the hardware */ { - __volatile__ unsigned int *status = - (unsigned int *)dev_priv->status_page; PRIMLOCALS; PRIMGETPTR( dev_priv ); - - dev_priv->last_sync_tag = mga_create_sync_tag(dev); - + PRIMOUTREG(MGAREG_DMAPAD, 0); PRIMOUTREG(MGAREG_DMAPAD, 0); - PRIMOUTREG(MGAREG_DWGSYNC, dev_priv->last_sync_tag); + PRIMOUTREG(MGAREG_DWGSYNC, 0x0100); PRIMOUTREG(MGAREG_SOFTRAP, 0); /* Poll for the first buffer to insure that * the status register will be correct */ - DRM_DEBUG("phys_head : %lx\n", (unsigned long)phys_head); - status[1] = 0; mga_flush_write_combine(); MGA_WRITE(MGAREG_PRIMADDRESS, phys_head | TT_GENERAL); @@ -858,9 +828,7 @@ static int mga_dma_initialize(drm_device_t *dev, drm_mga_init_t *init) { MGA_WRITE(MGAREG_PRIMEND, ((phys_head + num_dwords * 4) | PDEA_pagpxfer_enable)); - while(MGA_READ(MGAREG_DWGSYNC) != dev_priv->last_sync_tag) ; - DRM_DEBUG("status[0] after initialization : %x\n", status[0]); - DRM_DEBUG("status[1] after initialization : %x\n", status[1]); + while(MGA_READ(MGAREG_DWGSYNC) != 0x0100) ; } if(mga_freelist_init(dev) != 0) { @@ -868,7 +836,6 @@ static int mga_dma_initialize(drm_device_t *dev, drm_mga_init_t *init) { mga_dma_cleanup(dev); return -ENOMEM; } - DRM_DEBUG("dma init was successful\n"); return 0; } @@ -879,6 +846,8 @@ int mga_dma_init(struct inode *inode, struct file *filp, drm_device_t *dev = priv->dev; drm_mga_init_t init; + DRM_DEBUG("%s\n", __FUNCTION__); + copy_from_user_ret(&init, (drm_mga_init_t *)arg, sizeof(init), -EFAULT); switch(init.func) { @@ -962,7 +931,9 @@ int mga_control(struct inode *inode, struct file *filp, unsigned int cmd, drm_control_t ctl; copy_from_user_ret(&ctl, (drm_control_t *)arg, sizeof(ctl), -EFAULT); - + + DRM_DEBUG("%s\n", __FUNCTION__); + switch (ctl.func) { case DRM_INST_HANDLER: return mga_irq_install(dev, ctl.irq); @@ -979,6 +950,8 @@ static int mga_flush_queue(drm_device_t *dev) drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private; int ret = 0; + DRM_DEBUG("%s\n", __FUNCTION__); + if(dev_priv == NULL) { return 0; } @@ -993,8 +966,7 @@ static int mga_flush_queue(drm_device_t *dev) &dev_priv->dispatch_status)) break; atomic_inc(&dev->total_sleeps); - DRM_DEBUG("Schedule in flush_queue\n"); - schedule_timeout(HZ*3); + schedule(); if (signal_pending(current)) { ret = -EINTR; /* Can't restart */ clear_bit(MGA_IN_FLUSH, @@ -1018,6 +990,7 @@ void mga_reclaim_buffers(drm_device_t *dev, pid_t pid) if(dev->dev_private == NULL) return; if(dma->buflist == NULL) return; + DRM_DEBUG("%s\n", __FUNCTION__); mga_flush_queue(dev); for (i = 0; i < dma->buf_count; i++) { @@ -1043,6 +1016,7 @@ int mga_lock(struct inode *inode, struct file *filp, unsigned int cmd, int ret = 0; drm_lock_t lock; + DRM_DEBUG("%s\n", __FUNCTION__); copy_from_user_ret(&lock, (drm_lock_t *)arg, sizeof(lock), -EFAULT); if (lock.context == DRM_KERNEL_CONTEXT) { @@ -1081,7 +1055,6 @@ int mga_lock(struct inode *inode, struct file *filp, unsigned int cmd, /* Contention */ atomic_inc(&dev->total_sleeps); current->state = TASK_INTERRUPTIBLE; - DRM_DEBUG("Calling lock schedule\n"); schedule(); if (signal_pending(current)) { ret = -ERESTARTSYS; @@ -1111,11 +1084,8 @@ int mga_flush_ioctl(struct inode *inode, struct file *filp, drm_device_t *dev = priv->dev; drm_lock_t lock; drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private; - drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; - __volatile__ unsigned int *status = - (__volatile__ unsigned int *)dev_priv->status_page; - int i; - + + DRM_DEBUG("%s\n", __FUNCTION__); copy_from_user_ret(&lock, (drm_lock_t *)arg, sizeof(lock), -EFAULT); if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) { diff --git a/linux/mga_drm.h b/linux/mga_drm.h index f2f5ae42..7228b905 100644 --- a/linux/mga_drm.h +++ b/linux/mga_drm.h @@ -160,19 +160,19 @@ typedef struct drm_mga_init { int sarea_priv_offset; int primary_size; int warp_ucode_size; - int frontOffset; - int backOffset; - int depthOffset; - int textureOffset; - int textureSize; - int agpTextureOffset; - int agpTextureSize; - int cpp; - int stride; + unsigned int frontOffset; + unsigned int backOffset; + unsigned int depthOffset; + unsigned int textureOffset; + unsigned int textureSize; + unsigned int agpTextureOffset; + unsigned int agpTextureSize; + unsigned int cpp; + unsigned int stride; int sgram; int chipset; drm_mga_warp_index_t WarpIndex[MGA_MAX_WARP_PIPES]; - int mAccess; + unsigned int mAccess; } drm_mga_init_t; /* Warning: if you change the sarea structure, you must change the Xserver @@ -181,7 +181,7 @@ typedef struct drm_mga_init { typedef struct _drm_mga_tex_region { unsigned char next, prev; unsigned char in_use; - int age; + unsigned int age; } drm_mga_tex_region_t; typedef struct _drm_mga_sarea { @@ -220,9 +220,9 @@ typedef struct _drm_mga_sarea { /* Counters for aging textures and for client-side throttling. */ - int last_enqueue; /* last time a buffer was enqueued */ - int last_dispatch; /* age of the most recently dispatched buffer */ - int last_quiescent; /* */ + unsigned int last_enqueue; /* last time a buffer was enqueued */ + unsigned int last_dispatch; /* age of the most recently dispatched buffer */ + unsigned int last_quiescent; /* */ /* LRU lists for texture memory in agp space and on the card @@ -238,9 +238,9 @@ typedef struct _drm_mga_sarea { /* Device specific ioctls: */ typedef struct _drm_mga_clear { - int clear_color; - int clear_depth; - int flags; + unsigned int clear_color; + unsigned int clear_depth; + unsigned int flags; } drm_mga_clear_t; typedef struct _drm_mga_swap { @@ -261,8 +261,8 @@ typedef struct _drm_mga_vertex { typedef struct _drm_mga_indices { int idx; /* buffer to queue */ - int start; - int end; + unsigned int start; + unsigned int end; int discard; /* client finished with buffer? */ } drm_mga_indices_t; diff --git a/linux/mga_drv.h b/linux/mga_drv.h index ceee5846..80d63c45 100644 --- a/linux/mga_drv.h +++ b/linux/mga_drv.h @@ -44,6 +44,7 @@ typedef struct { u32 *current_dma_ptr; u32 *head; u32 phys_head; + unsigned int prim_age; int sec_used; int idx; } drm_mga_prim_buf_t; @@ -58,29 +59,30 @@ typedef struct _drm_mga_freelist { #define MGA_IN_DISPATCH 0 #define MGA_IN_FLUSH 1 #define MGA_IN_WAIT 2 +#define MGA_IN_GETBUF 3 typedef struct _drm_mga_private { u32 dispatch_status; + unsigned int next_prim_age; + __volatile__ unsigned int last_prim_age; int reserved_map_idx; int buffer_map_idx; drm_mga_sarea_t *sarea_priv; int primary_size; int warp_ucode_size; int chipset; - int frontOffset; - int backOffset; - int depthOffset; - int textureOffset; - int textureSize; + unsigned int frontOffset; + unsigned int backOffset; + unsigned int depthOffset; + unsigned int textureOffset; + unsigned int textureSize; int cpp; - int stride; + unsigned int stride; int sgram; int use_agp; drm_mga_warp_index_t WarpIndex[MGA_MAX_G400_PIPES]; unsigned int WarpPipe; atomic_t pending_bufs; - unsigned int last_sync_tag; - unsigned int sync_tag; void *status_page; unsigned long real_status_page; u8 *ioremap; @@ -93,7 +95,7 @@ typedef struct _drm_mga_private { drm_mga_freelist_t *tail; wait_queue_head_t flush_queue; /* Processes waiting until flush */ wait_queue_head_t wait_queue; /* Processes waiting until interrupt */ - + wait_queue_head_t buf_queue; /* Processes waiting for a free buf */ /* Some validated register values: */ u32 mAccess; @@ -128,7 +130,7 @@ extern int mga_dma_init(struct inode *inode, struct file *filp, extern int mga_dma_cleanup(drm_device_t *dev); extern int mga_flush_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); - +extern void mga_flush_write_combine(void); extern unsigned int mga_create_sync_tag(drm_device_t *dev); extern drm_buf_t *mga_freelist_get(drm_device_t *dev); extern int mga_freelist_put(drm_device_t *dev, drm_buf_t *buf); @@ -190,6 +192,7 @@ typedef enum { typedef struct { drm_mga_freelist_t *my_freelist; int discard; + int dispatched; } drm_mga_buf_priv_t; #define DWGREG0 0x1c00 @@ -211,16 +214,16 @@ typedef struct { #define PRIM_OVERFLOW(dev, dev_priv, length) do { \ drm_mga_prim_buf_t *tmp_buf = \ dev_priv->prim_bufs[dev_priv->current_prim_idx]; \ - if( tmp_buf->max_dwords - tmp_buf->num_dwords < length || \ - tmp_buf->sec_used > MGA_DMA_BUF_NR/2) { \ - set_bit(MGA_BUF_FORCE_FIRE, &tmp_buf->buffer_status); \ + if( test_bit(MGA_BUF_NEEDS_OVERFLOW, \ + &tmp_buf->buffer_status)) { \ mga_advance_primary(dev); \ mga_dma_schedule(dev, 1); \ - } else if( test_bit(MGA_BUF_NEEDS_OVERFLOW, \ - &tmp_buf->buffer_status)) { \ + } else if( tmp_buf->max_dwords - tmp_buf->num_dwords < length ||\ + tmp_buf->sec_used > MGA_DMA_BUF_NR/2) { \ + set_bit(MGA_BUF_FORCE_FIRE, &tmp_buf->buffer_status); \ mga_advance_primary(dev); \ mga_dma_schedule(dev, 1); \ - } \ + } \ } while(0) #define PRIMGETPTR(dev_priv) do { \ @@ -271,6 +274,13 @@ drm_mga_prim_buf_t *tmp_buf = \ tmp_buf->sec_used++; \ } while (0) +#define AGEBUF(dev_priv, buf_priv) do { \ + drm_mga_prim_buf_t *tmp_buf = \ + dev_priv->prim_bufs[dev_priv->current_prim_idx]; \ + buf_priv->my_freelist->age = tmp_buf->prim_age; \ +} while (0) + + #define PRIMOUTREG(reg, val) do { \ tempIndex[outcount]=ADRINDEX(reg); \ dma_ptr[1+outcount] = val; \ diff --git a/linux/mga_state.c b/linux/mga_state.c index 675e130e..dc227769 100644 --- a/linux/mga_state.c +++ b/linux/mga_state.c @@ -41,14 +41,15 @@ static void mgaEmitClipRect( drm_mga_private_t *dev_priv, drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; unsigned int *regs = sarea_priv->ContextState; PRIMLOCALS; + DRM_DEBUG("%s\n", __FUNCTION__); /* This takes 10 dwords */ PRIMGETPTR( dev_priv ); /* Force reset of dwgctl (eliminates clip disable) */ PRIMOUTREG( MGAREG_DMAPAD, 0 ); - PRIMOUTREG( MGAREG_DWGSYNC, dev_priv->last_sync_tag - 1 ); - PRIMOUTREG( MGAREG_DWGSYNC, dev_priv->last_sync_tag - 1 ); + PRIMOUTREG( MGAREG_DWGSYNC, 0 ); + PRIMOUTREG( MGAREG_DWGSYNC, 0 ); PRIMOUTREG( MGAREG_DWGCTL, regs[MGA_CTXREG_DWGCTL] ); PRIMOUTREG( MGAREG_DMAPAD, 0 ); @@ -64,6 +65,7 @@ static void mgaEmitContext(drm_mga_private_t *dev_priv ) drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; unsigned int *regs = sarea_priv->ContextState; PRIMLOCALS; + DRM_DEBUG("%s\n", __FUNCTION__); /* This takes a max of 15 dwords */ PRIMGETPTR( dev_priv ); @@ -98,6 +100,7 @@ static void mgaG200EmitTex( drm_mga_private_t *dev_priv ) drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; unsigned int *regs = sarea_priv->TexState[0]; PRIMLOCALS; + DRM_DEBUG("%s\n", __FUNCTION__); PRIMGETPTR( dev_priv ); @@ -132,6 +135,7 @@ static void mgaG400EmitTex0( drm_mga_private_t *dev_priv ) unsigned int *regs = sarea_priv->TexState[0]; int multitex = sarea_priv->WarpPipe & MGA_T2; PRIMLOCALS; + DRM_DEBUG("%s\n", __FUNCTION__); PRIMGETPTR( dev_priv ); @@ -179,6 +183,7 @@ static void mgaG400EmitTex1( drm_mga_private_t *dev_priv ) drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; unsigned int *regs = sarea_priv->TexState[1]; PRIMLOCALS; + DRM_DEBUG("%s\n", __FUNCTION__); PRIMGETPTR(dev_priv); @@ -217,6 +222,7 @@ static void mgaG400EmitPipe(drm_mga_private_t *dev_priv ) unsigned int pipe = sarea_priv->WarpPipe; float fParam = 12800.0f; PRIMLOCALS; + DRM_DEBUG("%s\n", __FUNCTION__); PRIMGETPTR(dev_priv); @@ -255,7 +261,7 @@ static void mgaG400EmitPipe(drm_mga_private_t *dev_priv ) PRIMOUTREG(MGAREG_DMAPAD, 0xffffffff); PRIMOUTREG(MGAREG_DMAPAD, 0xffffffff); PRIMOUTREG(MGAREG_DMAPAD, 0xffffffff); - PRIMOUTREG(MGAREG_WIADDR2, (__u32)(dev_priv->WarpIndex[pipe].phys_addr | + PRIMOUTREG(MGAREG_WIADDR2, (u32)(dev_priv->WarpIndex[pipe].phys_addr | WIA_wmode_start | WIA_wagp_agp)); PRIMADVANCE(dev_priv); } @@ -265,6 +271,7 @@ static void mgaG200EmitPipe( drm_mga_private_t *dev_priv ) drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; unsigned int pipe = sarea_priv->WarpPipe; PRIMLOCALS; + DRM_DEBUG("%s\n", __FUNCTION__); PRIMGETPTR(dev_priv); @@ -284,7 +291,7 @@ static void mgaG200EmitPipe( drm_mga_private_t *dev_priv ) PRIMOUTREG(MGAREG_DMAPAD, 0xffffffff); PRIMOUTREG(MGAREG_DMAPAD, 0xffffffff); PRIMOUTREG(MGAREG_DMAPAD, 0xffffffff); - PRIMOUTREG(MGAREG_WIADDR, (__u32)(dev_priv->WarpIndex[pipe].phys_addr | + PRIMOUTREG(MGAREG_WIADDR, (u32)(dev_priv->WarpIndex[pipe].phys_addr | WIA_wmode_start | WIA_wagp_agp)); PRIMADVANCE(dev_priv); @@ -294,6 +301,7 @@ static void mgaEmitState( drm_mga_private_t *dev_priv ) { drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; unsigned int dirty = sarea_priv->dirty; + DRM_DEBUG("%s\n", __FUNCTION__); if (dev_priv->chipset == MGA_CARD_TYPE_G400) { int multitex = sarea_priv->WarpPipe & MGA_T2; @@ -343,6 +351,8 @@ static int mgaVerifyContext(drm_mga_private_t *dev_priv ) drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; unsigned int *regs = sarea_priv->ContextState; + DRM_DEBUG("%s\n", __FUNCTION__); + if (regs[MGA_CTXREG_DSTORG] != dev_priv->frontOffset && regs[MGA_CTXREG_DSTORG] != dev_priv->backOffset) { DRM_DEBUG("BAD DSTORG: %x (front %x, back %x)\n\n", @@ -362,6 +372,8 @@ static int mgaVerifyTex(drm_mga_private_t *dev_priv, { drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; + DRM_DEBUG("%s\n", __FUNCTION__); + if ((sarea_priv->TexState[unit][MGA_TEXREG_ORG] & 0x3) == 0x1) { DRM_DEBUG("BAD TEXREG_ORG: %x, unit %d\n", sarea_priv->TexState[unit][MGA_TEXREG_ORG], @@ -379,6 +391,8 @@ static int mgaVerifyState( drm_mga_private_t *dev_priv ) unsigned int dirty = sarea_priv->dirty; int rv = 0; + DRM_DEBUG("%s\n", __FUNCTION__); + if (sarea_priv->nbox > MGA_NR_SAREA_CLIPRECTS) sarea_priv->nbox = MGA_NR_SAREA_CLIPRECTS; @@ -409,6 +423,8 @@ static int mgaVerifyIload( drm_mga_private_t *dev_priv, unsigned long bus_address, unsigned int dstOrg, int length ) { + DRM_DEBUG("%s\n", __FUNCTION__); + if(dstOrg < dev_priv->textureOffset || dstOrg + length > (dev_priv->textureOffset + dev_priv->textureSize)) { @@ -432,14 +448,13 @@ static void mga_dma_dispatch_tex_blit( drm_device_t *dev, int use_agp = PDEA_pagpxfer_enable | 0x00000001; u16 y2; PRIMLOCALS; + DRM_DEBUG("%s\n", __FUNCTION__); y2 = length / 64; PRIM_OVERFLOW(dev, dev_priv, 30); PRIMGETPTR( dev_priv ); - dev_priv->last_sync_tag = mga_create_sync_tag(dev); - PRIMOUTREG( MGAREG_DSTORG, destOrg); PRIMOUTREG( MGAREG_MACCESS, 0x00000000); DRM_DEBUG("srcorg : %lx\n", bus_address | use_agp); @@ -459,7 +474,7 @@ static void mga_dma_dispatch_tex_blit( drm_device_t *dev, PRIMOUTREG( MGAREG_SRCORG, 0); PRIMOUTREG( MGAREG_PITCH, dev_priv->stride / dev_priv->cpp); PRIMOUTREG( MGAREG_DMAPAD, 0); - PRIMOUTREG( MGAREG_DWGSYNC, dev_priv->last_sync_tag); + PRIMOUTREG( MGAREG_DMAPAD, 0); PRIMADVANCE(dev_priv); } @@ -475,33 +490,33 @@ static void mga_dma_dispatch_vertex(drm_device_t *dev, int i = 0; int primary_needed; PRIMLOCALS; + DRM_DEBUG("%s\n", __FUNCTION__); DRM_DEBUG("dispatch vertex %d addr 0x%lx, " "length 0x%x nbox %d dirty %x\n", buf->idx, address, length, sarea_priv->nbox, sarea_priv->dirty); - - dev_priv->last_sync_tag = mga_create_sync_tag(dev); - - if (buf_priv->discard) { - buf_priv->my_freelist->age = dev_priv->last_sync_tag; - mga_freelist_put(dev, buf); + DRM_DEBUG("used : %d, total : %d\n", buf->used, buf->total); + if(sarea_priv->WarpPipe & MGA_T2) { + if ((buf->used/4) % 10) + DRM_DEBUG("Multitex Buf is not aligned properly!!!\n"); + } else { + if ((buf->used/4) % 8) + DRM_DEBUG("Buf is not aligned properly!!!\n"); } - - /* WARNING: if you change any of the state functions verify - * these numbers (Overestimating this doesn't hurt). - */ - primary_needed = (25+15+30+25+ - 10 + - 15 * MGA_NR_SAREA_CLIPRECTS); - - - PRIM_OVERFLOW(dev, dev_priv, primary_needed); - mgaEmitState( dev_priv ); - if (buf->used) { + /* WARNING: if you change any of the state functions verify + * these numbers (Overestimating this doesn't hurt). + */ + buf_priv->dispatched = 1; + primary_needed = (25+15+30+25+ + 10 + + 15 * MGA_NR_SAREA_CLIPRECTS); + PRIM_OVERFLOW(dev, dev_priv, primary_needed); + mgaEmitState( dev_priv ); + do { if (i < sarea_priv->nbox) { DRM_DEBUG("idx %d Emit box %d/%d:" @@ -521,28 +536,28 @@ static void mga_dma_dispatch_vertex(drm_device_t *dev, PRIMOUTREG( MGAREG_DMAPAD, 0); PRIMOUTREG( MGAREG_DMAPAD, 0); PRIMOUTREG( MGAREG_SECADDRESS, - ((__u32)address) | TT_VERTEX); + ((u32)address) | TT_VERTEX); PRIMOUTREG( MGAREG_SECEND, - (((__u32)(address + length)) | + (((u32)(address + length)) | use_agp)); PRIMADVANCE( dev_priv ); } while (++i < sarea_priv->nbox); } - PRIMGETPTR( dev_priv ); - PRIMOUTREG(MGAREG_DMAPAD, 0); - PRIMOUTREG(MGAREG_DMAPAD, 0); - PRIMOUTREG(MGAREG_DWGSYNC, 0); - PRIMOUTREG(MGAREG_DWGSYNC, dev_priv->last_sync_tag); - PRIMADVANCE( dev_priv ); -} + if (buf_priv->discard) { + if(buf_priv->dispatched == 1) AGEBUF(dev_priv, buf_priv); + buf_priv->dispatched = 0; + mga_freelist_put(dev, buf); + } + +} static void mga_dma_dispatch_indices(drm_device_t *dev, drm_buf_t *buf, - int start, - int end) + unsigned int start, + unsigned int end) { drm_mga_private_t *dev_priv = dev->dev_private; drm_mga_buf_priv_t *buf_priv = buf->dev_private; @@ -552,33 +567,24 @@ static void mga_dma_dispatch_indices(drm_device_t *dev, int i = 0; int primary_needed; PRIMLOCALS; + DRM_DEBUG("%s\n", __FUNCTION__); - DRM_DEBUG("dispatch indices %d addr 0x%lx, " + DRM_DEBUG("dispatch indices %d addr 0x%x, " "start 0x%x end 0x%x nbox %d dirty %x\n", buf->idx, address, start, end, sarea_priv->nbox, sarea_priv->dirty); - - dev_priv->last_sync_tag = mga_create_sync_tag(dev); - - if (buf_priv->discard) { - buf_priv->my_freelist->age = dev_priv->last_sync_tag; - mga_freelist_put(dev, buf); - } - - - /* WARNING: if you change any of the state functions verify - * these numbers (Overestimating this doesn't hurt). - */ - primary_needed = (25+15+30+25+ - 10 + - 15 * MGA_NR_SAREA_CLIPRECTS); - - - PRIM_OVERFLOW(dev, dev_priv, primary_needed); - mgaEmitState( dev_priv ); - if (start != end) { + /* WARNING: if you change any of the state functions verify + * these numbers (Overestimating this doesn't hurt). + */ + buf_priv->dispatched = 1; + primary_needed = (25+15+30+25+ + 10 + + 15 * MGA_NR_SAREA_CLIPRECTS); + PRIM_OVERFLOW(dev, dev_priv, primary_needed); + mgaEmitState( dev_priv ); + do { if (i < sarea_priv->nbox) { DRM_DEBUG("idx %d Emit box %d/%d:" @@ -604,13 +610,11 @@ static void mga_dma_dispatch_indices(drm_device_t *dev, PRIMADVANCE( dev_priv ); } while (++i < sarea_priv->nbox); } - - PRIMGETPTR( dev_priv ); - PRIMOUTREG(MGAREG_DMAPAD, 0); - PRIMOUTREG(MGAREG_DMAPAD, 0); - PRIMOUTREG(MGAREG_DMAPAD, 0); - PRIMOUTREG(MGAREG_DWGSYNC, dev_priv->last_sync_tag); - PRIMADVANCE( dev_priv ); + if (buf_priv->discard) { + if(buf_priv->dispatched == 1) AGEBUF(dev_priv, buf_priv); + buf_priv->dispatched = 0; + mga_freelist_put(dev, buf); + } } @@ -627,6 +631,7 @@ static void mga_dma_dispatch_clear( drm_device_t *dev, int flags, int i; int primary_needed; PRIMLOCALS; + DRM_DEBUG("%s\n", __FUNCTION__); if ( dev_priv->sgram ) cmd = MGA_CLEAR_CMD | DC_atype_blk; @@ -637,7 +642,6 @@ static void mga_dma_dispatch_clear( drm_device_t *dev, int flags, if(primary_needed == 0) primary_needed = 70; PRIM_OVERFLOW(dev, dev_priv, primary_needed); PRIMGETPTR( dev_priv ); - dev_priv->last_sync_tag = mga_create_sync_tag(dev); for (i = 0 ; i < nbox ; i++) { unsigned int height = pbox[i].y2 - pbox[i].y1; @@ -691,11 +695,6 @@ static void mga_dma_dispatch_clear( drm_device_t *dev, int flags, PRIMOUTREG( MGAREG_DMAPAD, 0); PRIMOUTREG( MGAREG_DMAPAD, 0); PRIMOUTREG( MGAREG_DWGCTL, regs[MGA_CTXREG_DWGCTL] ); - - PRIMOUTREG( MGAREG_DMAPAD, 0); - PRIMOUTREG( MGAREG_DMAPAD, 0); - PRIMOUTREG( MGAREG_DMAPAD, 0); - PRIMOUTREG( MGAREG_DWGSYNC, dev_priv->last_sync_tag); PRIMADVANCE(dev_priv); } @@ -709,14 +708,13 @@ static void mga_dma_dispatch_swap( drm_device_t *dev ) int i; int primary_needed; PRIMLOCALS; + DRM_DEBUG("%s\n", __FUNCTION__); primary_needed = nbox * 5; primary_needed += 60; PRIM_OVERFLOW(dev, dev_priv, primary_needed); PRIMGETPTR( dev_priv ); - dev_priv->last_sync_tag = mga_create_sync_tag(dev); - PRIMOUTREG(MGAREG_DSTORG, dev_priv->frontOffset); PRIMOUTREG(MGAREG_MACCESS, dev_priv->mAccess); PRIMOUTREG(MGAREG_SRCORG, dev_priv->backOffset); @@ -744,13 +742,9 @@ static void mga_dma_dispatch_swap( drm_device_t *dev ) /* Force reset of DWGCTL */ PRIMOUTREG( MGAREG_DMAPAD, 0); PRIMOUTREG( MGAREG_DMAPAD, 0); - PRIMOUTREG( MGAREG_DMAPAD, 0); + PRIMOUTREG( MGAREG_SRCORG, 0); PRIMOUTREG( MGAREG_DWGCTL, regs[MGA_CTXREG_DWGCTL] ); - PRIMOUTREG( MGAREG_SRCORG, 0); - PRIMOUTREG( MGAREG_DMAPAD, 0); - PRIMOUTREG( MGAREG_DMAPAD, 0); - PRIMOUTREG( MGAREG_DWGSYNC, dev_priv->last_sync_tag); PRIMADVANCE(dev_priv); } @@ -761,12 +755,11 @@ int mga_clear_bufs(struct inode *inode, struct file *filp, drm_device_t *dev = priv->dev; drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private; drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; - __volatile__ unsigned int *status = - (__volatile__ unsigned int *)dev_priv->status_page; drm_mga_clear_t clear; copy_from_user_ret(&clear, (drm_mga_clear_t *)arg, sizeof(clear), -EFAULT); + DRM_DEBUG("%s\n", __FUNCTION__); if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) { DRM_ERROR("mga_clear_bufs called without lock held\n"); @@ -783,8 +776,8 @@ int mga_clear_bufs(struct inode *inode, struct file *filp, clear.clear_color, clear.clear_depth ); PRIMUPDATE(dev_priv); + mga_flush_write_combine(); mga_dma_schedule(dev, 1); - sarea_priv->last_dispatch = status[1]; return 0; } @@ -795,8 +788,7 @@ int mga_swap_bufs(struct inode *inode, struct file *filp, drm_device_t *dev = priv->dev; drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private; drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; - __volatile__ unsigned int *status = - (__volatile__ unsigned int *)dev_priv->status_page; + DRM_DEBUG("%s\n", __FUNCTION__); if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) { DRM_ERROR("mga_swap_bufs called without lock held\n"); @@ -812,8 +804,8 @@ int mga_swap_bufs(struct inode *inode, struct file *filp, mga_dma_dispatch_swap( dev ); PRIMUPDATE(dev_priv); set_bit(MGA_BUF_SWAP_PENDING, &dev_priv->current_prim->buffer_status); + mga_flush_write_combine(); mga_dma_schedule(dev, 1); - sarea_priv->last_dispatch = status[1]; return 0; } @@ -825,12 +817,11 @@ int mga_iload(struct inode *inode, struct file *filp, drm_device_dma_t *dma = dev->dma; drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private; drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; - __volatile__ unsigned int *status = - (__volatile__ unsigned int *)dev_priv->status_page; drm_buf_t *buf; drm_mga_buf_priv_t *buf_priv; drm_mga_iload_t iload; unsigned long bus_address; + DRM_DEBUG("%s\n", __FUNCTION__); DRM_DEBUG("Starting Iload\n"); copy_from_user_ret(&iload, (drm_mga_iload_t *)arg, sizeof(iload), @@ -859,11 +850,11 @@ int mga_iload(struct inode *inode, struct file *filp, mga_dma_dispatch_tex_blit(dev, bus_address, iload.length, iload.destOrg); - buf_priv->my_freelist->age = dev_priv->last_sync_tag; + AGEBUF(dev_priv, buf_priv); buf_priv->discard = 1; mga_freelist_put(dev, buf); + mga_flush_write_combine(); mga_dma_schedule(dev, 1); - sarea_priv->last_dispatch = status[1]; return 0; } @@ -873,13 +864,11 @@ int mga_vertex(struct inode *inode, struct file *filp, drm_file_t *priv = filp->private_data; drm_device_t *dev = priv->dev; drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private; - drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; - __volatile__ unsigned int *status = - (__volatile__ unsigned int *)dev_priv->status_page; drm_device_dma_t *dma = dev->dma; drm_buf_t *buf; drm_mga_buf_priv_t *buf_priv; drm_mga_vertex_t vertex; + DRM_DEBUG("%s\n", __FUNCTION__); copy_from_user_ret(&vertex, (drm_mga_vertex_t *)arg, sizeof(vertex), -EFAULT); @@ -898,9 +887,10 @@ int mga_vertex(struct inode *inode, struct file *filp, buf_priv->discard = vertex.discard; if (!mgaVerifyState(dev_priv)) { - if (vertex.discard) { - buf_priv->my_freelist->age = dev_priv->last_sync_tag; - mga_freelist_put(dev, buf); + if (vertex.discard) { + if(buf_priv->dispatched == 1) AGEBUF(dev_priv, buf_priv); + buf_priv->dispatched = 0; + mga_freelist_put(dev, buf); } DRM_DEBUG("bad state\n"); return -EINVAL; @@ -909,8 +899,8 @@ int mga_vertex(struct inode *inode, struct file *filp, mga_dma_dispatch_vertex(dev, buf); PRIMUPDATE(dev_priv); + mga_flush_write_combine(); mga_dma_schedule(dev, 1); - sarea_priv->last_dispatch = status[1]; return 0; } @@ -921,13 +911,11 @@ int mga_indices(struct inode *inode, struct file *filp, drm_file_t *priv = filp->private_data; drm_device_t *dev = priv->dev; drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private; - drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; - __volatile__ unsigned int *status = - (__volatile__ unsigned int *)dev_priv->status_page; drm_device_dma_t *dma = dev->dma; drm_buf_t *buf; drm_mga_buf_priv_t *buf_priv; drm_mga_indices_t indices; + DRM_DEBUG("%s\n", __FUNCTION__); copy_from_user_ret(&indices, (drm_mga_indices_t *)arg, sizeof(indices), -EFAULT); @@ -945,9 +933,10 @@ int mga_indices(struct inode *inode, struct file *filp, buf_priv->discard = indices.discard; if (!mgaVerifyState(dev_priv)) { - if (indices.discard) { - buf_priv->my_freelist->age = dev_priv->last_sync_tag; - mga_freelist_put(dev, buf); + if (indices.discard) { + if(buf_priv->dispatched == 1) AGEBUF(dev_priv, buf_priv); + buf_priv->dispatched = 0; + mga_freelist_put(dev, buf); } return -EINVAL; } @@ -955,8 +944,8 @@ int mga_indices(struct inode *inode, struct file *filp, mga_dma_dispatch_indices(dev, buf, indices.start, indices.end); PRIMUPDATE(dev_priv); + mga_flush_write_combine(); mga_dma_schedule(dev, 1); - sarea_priv->last_dispatch = status[1]; return 0; } @@ -966,6 +955,7 @@ static int mga_dma_get_buffers(drm_device_t *dev, drm_dma_t *d) { int i; drm_buf_t *buf; + DRM_DEBUG("%s\n", __FUNCTION__); for (i = d->granted_count; i < d->request_count; i++) { buf = mga_freelist_get(dev); @@ -990,12 +980,9 @@ int mga_dma(struct inode *inode, struct file *filp, unsigned int cmd, drm_file_t *priv = filp->private_data; drm_device_t *dev = priv->dev; drm_device_dma_t *dma = dev->dma; - drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private; - drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; - __volatile__ unsigned int *status = - (__volatile__ unsigned int *)dev_priv->status_page; int retcode = 0; drm_dma_t d; + DRM_DEBUG("%s\n", __FUNCTION__); copy_from_user_ret(&d, (drm_dma_t *)arg, sizeof(d), -EFAULT); DRM_DEBUG("%d %d: %d send, %d req\n", @@ -1031,6 +1018,5 @@ int mga_dma(struct inode *inode, struct file *filp, unsigned int cmd, DRM_DEBUG("%d returning, granted = %d\n", current->pid, d.granted_count); copy_to_user_ret((drm_dma_t *)arg, &d, sizeof(d), -EFAULT); - sarea_priv->last_dispatch = status[1]; return retcode; } |