int mga_warp_init( drm_mga_private_t *dev_priv ) { u32 wmisc; /* FIXME: Get rid of these damned magic numbers... */ switch ( dev_priv->chipset ) { case MGA_CARD_TYPE_G400: MGA_WRITE( MGA_WIADDR2, MGA_WMODE_SUSPEND ); MGA_WRITE( MGA_WGETMSB, 0x00000E00 ); MGA_WRITE( MGA_WVRTXSZ, 0x00001807 ); MGA_WRITE( MGA_WACCEPTSEQ, 0x18000000 ); break; case MGA_CARD_TYPE_G200: MGA_WRITE( MGA_WIADDR, MGA_WMODE_SUSPEND ); MGA_WRITE( MGA_WGETMSB, 0x1606 ); MGA_WRITE( MGA_WVRTXSZ, 7 ); break; default: return -EINVAL; } MGA_WRITE( MGA_WMISC, (MGA_WUCODECACHE_ENABLE | MGA_WMASTER_ENABLE | MGA_WCACHEFLUSH_ENABLE) ); wmisc = MGA_READ( MGA_WMISC ); if ( wmisc != WMISC_EXPECTED ) { DRM_ERROR( "WARP engine config failed! 0x%x != 0x%x\n", wmisc, WMISC_EXPECTED ); return -EINVAL; } return 0; }
irqreturn_t mga_driver_irq_handler(DRM_IRQ_ARGS) { drm_device_t *dev = (drm_device_t *) arg; drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private; int status; int handled = 0; status = MGA_READ(MGA_STATUS); /* VBLANK interrupt */ if (status & MGA_VLINEPEN) { MGA_WRITE(MGA_ICLEAR, MGA_VLINEICLR); atomic_inc(&dev->vbl_received); DRM_WAKEUP(&dev->vbl_queue); drm_vbl_send_signals(dev); handled = 1; } /* SOFTRAP interrupt */ if (status & MGA_SOFTRAPEN) { const u32 prim_start = MGA_READ(MGA_PRIMADDRESS); const u32 prim_end = MGA_READ(MGA_PRIMEND); MGA_WRITE(MGA_ICLEAR, MGA_SOFTRAPICLR); /* In addition to clearing the interrupt-pending bit, we * have to write to MGA_PRIMEND to re-start the DMA operation. */ if ( (prim_start & ~0x03) != (prim_end & ~0x03) ) { MGA_WRITE(MGA_PRIMEND, prim_end); } atomic_inc(&dev_priv->last_fence_retired); DRM_WAKEUP(&dev_priv->fence_queue); handled = 1; } if ( handled ) { return IRQ_HANDLED; } return IRQ_NONE; }
irqreturn_t mga_driver_irq_handler(DRM_IRQ_ARGS) { struct drm_device *dev = (struct drm_device *) arg; drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private; int status; int handled = 0; status = MGA_READ(MGA_STATUS); if (status & MGA_VLINEPEN) { MGA_WRITE(MGA_ICLEAR, MGA_VLINEICLR); atomic_inc(&dev_priv->vbl_received); drm_handle_vblank(dev, 0); handled = 1; } if (status & MGA_SOFTRAPEN) { const u32 prim_start = MGA_READ(MGA_PRIMADDRESS); const u32 prim_end = MGA_READ(MGA_PRIMEND); MGA_WRITE(MGA_ICLEAR, MGA_SOFTRAPICLR); if ((prim_start & ~0x03) != (prim_end & ~0x03)) MGA_WRITE(MGA_PRIMEND, prim_end); atomic_inc(&dev_priv->last_fence_retired); DRM_WAKEUP(&dev_priv->fence_queue); handled = 1; } if (handled) return IRQ_HANDLED; return IRQ_NONE; }
int mga_do_dma_idle( drm_mga_private_t *dev_priv ) { u32 status = 0; int i; DRM_DEBUG( "\n" ); for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) { status = MGA_READ( MGA_STATUS ) & MGA_DMA_IDLE_MASK; if ( status == MGA_ENDPRDMASTS ) return 0; udelay( 1 ); } #if MGA_DMA_DEBUG DRM_ERROR( "failed! status=0x%08x\n", status ); #endif return -EBUSY; }
static void mga_freelist_print( drm_device_t *dev ) { drm_mga_private_t *dev_priv = dev->dev_private; drm_mga_freelist_t *entry; DRM_INFO( "\n" ); DRM_INFO( "current dispatch: last=0x%x done=0x%x\n", dev_priv->sarea_priv->last_dispatch, (unsigned int)(MGA_READ( MGA_PRIMADDRESS ) - dev_priv->primary->offset) ); DRM_INFO( "current freelist:\n" ); for ( entry = dev_priv->head->next ; entry ; entry = entry->next ) { DRM_INFO( " %p idx=%2d age=0x%x 0x%06lx\n", entry, entry->buf->idx, entry->age.head, entry->age.head - dev_priv->primary->offset ); } DRM_INFO( "\n" ); }
void mga_do_dma_wrap_start( drm_mga_private_t *dev_priv ) { drm_mga_primary_buffer_t *primary = &dev_priv->prim; u32 head, tail; DMA_LOCALS; DRM_DEBUG( "\n" ); BEGIN_DMA_WRAP(); DMA_BLOCK( MGA_DMAPAD, 0x00000000, MGA_DMAPAD, 0x00000000, MGA_DMAPAD, 0x00000000, MGA_DMAPAD, 0x00000000 ); ADVANCE_DMA(); tail = primary->tail + dev_priv->primary->offset; primary->tail = 0; primary->last_flush = 0; primary->last_wrap++; head = MGA_READ( MGA_PRIMADDRESS ); if ( head == dev_priv->primary->offset ) { primary->space = primary->size; } else { primary->space = head - dev_priv->primary->offset; } DRM_DEBUG( " head = 0x%06lx\n", head - dev_priv->primary->offset ); DRM_DEBUG( " tail = 0x%06x\n", primary->tail ); DRM_DEBUG( " wrap = %d\n", primary->last_wrap ); DRM_DEBUG( " space = 0x%06x\n", primary->space ); mga_flush_write_combine(); MGA_WRITE( MGA_PRIMEND, tail | MGA_PAGPXFER ); set_bit( 0, &primary->wrapped ); DRM_DEBUG( "done.\n" ); }
int mga_do_wait_for_idle( drm_mga_private_t *dev_priv ) { u32 status = 0; int i; DRM_DEBUG( "\n" ); for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) { status = MGA_READ( MGA_STATUS ) & MGA_ENGINE_IDLE_MASK; if ( status == MGA_ENDPRDMASTS ) { MGA_WRITE8( MGA_CRTC_INDEX, 0 ); return 0; } udelay( 1 ); } #if MGA_DMA_DEBUG DRM_ERROR( "failed!\n" ); DRM_INFO( " status=0x%08x\n", status ); #endif return -EBUSY; }
/* * Copy the back buffer to the front buffer. */ void mgaSwapBuffers(Display *dpy, void *drawablePrivate) { __DRIdrawablePrivate *dPriv = (__DRIdrawablePrivate *) drawablePrivate; mgaContextPtr mmesa; XF86DRIClipRectPtr pbox; GLint nbox; GLint ret, wait = 0; GLint i; GLuint last_frame, last_wrap; assert(dPriv); assert(dPriv->driContextPriv); assert(dPriv->driContextPriv->driverPrivate); mmesa = (mgaContextPtr) dPriv->driContextPriv->driverPrivate; FLUSH_BATCH( mmesa ); mgaWaitForVBlank( mmesa ); LOCK_HARDWARE( mmesa ); last_frame = mmesa->sarea->last_frame.head; last_wrap = mmesa->sarea->last_frame.wrap; /* FIXME: Add a timeout to this loop... */ while ( 1 ) { if ( last_wrap < mmesa->sarea->last_wrap || ( last_wrap == mmesa->sarea->last_wrap && last_frame <= (MGA_READ( MGAREG_PRIMADDRESS ) - mmesa->primary_offset) ) ) { break; } if ( 0 ) { wait++; fprintf( stderr, " last: head=0x%06x wrap=%d\n", last_frame, last_wrap ); fprintf( stderr, " head: head=0x%06lx wrap=%d\n", (long)(MGA_READ( MGAREG_PRIMADDRESS ) - mmesa->primary_offset), mmesa->sarea->last_wrap ); } UPDATE_LOCK( mmesa, DRM_LOCK_FLUSH ); for ( i = 0 ; i < 1024 ; i++ ) { /* Don't just hammer the register... */ } } if ( wait ) fprintf( stderr, "\n" ); /* Use the frontbuffer cliprects */ if (mmesa->dirty_cliprects & MGA_FRONT) mgaUpdateRects( mmesa, MGA_FRONT ); pbox = dPriv->pClipRects; nbox = dPriv->numClipRects; for (i = 0 ; i < nbox ; ) { int nr = MIN2(i + MGA_NR_SAREA_CLIPRECTS, dPriv->numClipRects); XF86DRIClipRectPtr b = mmesa->sarea->boxes; mmesa->sarea->nbox = nr - i; for ( ; i < nr ; i++) *b++ = pbox[i]; if (0) fprintf(stderr, "DRM_IOCTL_MGA_SWAP\n"); ret = drmCommandNone( mmesa->driFd, DRM_MGA_SWAP ); if ( ret ) { printf("send swap retcode = %d\n", ret); exit(1); } } UNLOCK_HARDWARE( mmesa ); mmesa->dirty |= MGA_UPLOAD_CLIPRECTS; }