int mga_dma_init( DRM_IOCTL_ARGS ) { DRM_DEVICE; drm_mga_init_t init; LOCK_TEST_WITH_RETURN( dev, filp ); DRM_COPY_FROM_USER_IOCTL( init, (drm_mga_init_t *)data, sizeof(init) ); switch ( init.func ) { case MGA_INIT_DMA: return mga_do_init_dma( dev, &init ); case MGA_CLEANUP_DMA: return mga_do_cleanup_dma( dev ); } return DRM_ERR(EINVAL); }
int mga_dma_init( struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg ) { drm_file_t *priv = filp->private_data; drm_device_t *dev = priv->dev; drm_mga_init_t init; if ( copy_from_user( &init, (drm_mga_init_t *)arg, sizeof(init) ) ) return -EFAULT; switch ( init.func ) { case MGA_INIT_DMA: return mga_do_init_dma( dev, &init ); case MGA_CLEANUP_DMA: return mga_do_cleanup_dma( dev ); } return -EINVAL; }
static int mga_do_init_dma( drm_device_t *dev, drm_mga_init_t *init ) { drm_mga_private_t *dev_priv; int ret; DRM_DEBUG( "\n" ); dev_priv = DRM(alloc)( sizeof(drm_mga_private_t), DRM_MEM_DRIVER ); if ( !dev_priv ) return -ENOMEM; memset( dev_priv, 0, sizeof(drm_mga_private_t) ); dev_priv->chipset = init->chipset; dev_priv->usec_timeout = MGA_DEFAULT_USEC_TIMEOUT; if ( init->sgram ) { dev_priv->clear_cmd = MGA_DWGCTL_CLEAR | MGA_ATYPE_BLK; } else { dev_priv->clear_cmd = MGA_DWGCTL_CLEAR | MGA_ATYPE_RSTR; } dev_priv->maccess = init->maccess; dev_priv->fb_cpp = init->fb_cpp; dev_priv->front_offset = init->front_offset; dev_priv->front_pitch = init->front_pitch; dev_priv->back_offset = init->back_offset; dev_priv->back_pitch = init->back_pitch; dev_priv->depth_cpp = init->depth_cpp; dev_priv->depth_offset = init->depth_offset; dev_priv->depth_pitch = init->depth_pitch; /* FIXME: Need to support AGP textures... */ dev_priv->texture_offset = init->texture_offset[0]; dev_priv->texture_size = init->texture_size[0]; DRM_GETSAREA(); if(!dev_priv->sarea) { DRM_ERROR( "failed to find sarea!\n" ); /* Assign dev_private so we can do cleanup. */ dev->dev_private = (void *)dev_priv; mga_do_cleanup_dma( dev ); return -EINVAL; } DRM_FIND_MAP( dev_priv->fb, init->fb_offset ); if(!dev_priv->fb) { DRM_ERROR( "failed to find framebuffer!\n" ); /* Assign dev_private so we can do cleanup. */ dev->dev_private = (void *)dev_priv; mga_do_cleanup_dma( dev ); return -EINVAL; } DRM_FIND_MAP( dev_priv->mmio, init->mmio_offset ); if(!dev_priv->mmio) { DRM_ERROR( "failed to find mmio region!\n" ); /* Assign dev_private so we can do cleanup. */ dev->dev_private = (void *)dev_priv; mga_do_cleanup_dma( dev ); return -EINVAL; } DRM_FIND_MAP( dev_priv->status, init->status_offset ); if(!dev_priv->status) { DRM_ERROR( "failed to find status page!\n" ); /* Assign dev_private so we can do cleanup. */ dev->dev_private = (void *)dev_priv; mga_do_cleanup_dma( dev ); return -EINVAL; } DRM_FIND_MAP( dev_priv->warp, init->warp_offset ); if(!dev_priv->warp) { DRM_ERROR( "failed to find warp microcode region!\n" ); /* Assign dev_private so we can do cleanup. */ dev->dev_private = (void *)dev_priv; mga_do_cleanup_dma( dev ); return -EINVAL; } DRM_FIND_MAP( dev_priv->primary, init->primary_offset ); if(!dev_priv->primary) { DRM_ERROR( "failed to find primary dma region!\n" ); /* Assign dev_private so we can do cleanup. */ dev->dev_private = (void *)dev_priv; mga_do_cleanup_dma( dev ); return -EINVAL; } DRM_FIND_MAP( dev_priv->buffers, init->buffers_offset ); if(!dev_priv->buffers) { DRM_ERROR( "failed to find dma buffer region!\n" ); /* Assign dev_private so we can do cleanup. */ dev->dev_private = (void *)dev_priv; mga_do_cleanup_dma( dev ); return -EINVAL; } dev_priv->sarea_priv = (drm_mga_sarea_t *)((u8 *)dev_priv->sarea->handle + init->sarea_priv_offset); DRM_IOREMAP( dev_priv->warp, dev ); DRM_IOREMAP( dev_priv->primary, dev ); DRM_IOREMAP( dev_priv->buffers, dev ); if(!dev_priv->warp->handle || !dev_priv->primary->handle || !dev_priv->buffers->handle ) { DRM_ERROR( "failed to ioremap agp regions!\n" ); /* Assign dev_private so we can do cleanup. */ dev->dev_private = (void *)dev_priv; mga_do_cleanup_dma( dev ); return -ENOMEM; } ret = mga_warp_install_microcode( dev_priv ); if ( ret < 0 ) { DRM_ERROR( "failed to install WARP ucode!\n" ); /* Assign dev_private so we can do cleanup. */ dev->dev_private = (void *)dev_priv; mga_do_cleanup_dma( dev ); return ret; } ret = mga_warp_init( dev_priv ); if ( ret < 0 ) { DRM_ERROR( "failed to init WARP engine!\n" ); /* Assign dev_private so we can do cleanup. */ dev->dev_private = (void *)dev_priv; mga_do_cleanup_dma( dev ); return ret; } dev_priv->prim.status = (u32 *)dev_priv->status->handle; mga_do_wait_for_idle( dev_priv ); /* Init the primary DMA registers. */ MGA_WRITE( MGA_PRIMADDRESS, dev_priv->primary->offset | MGA_DMA_GENERAL ); #if 0 MGA_WRITE( MGA_PRIMPTR, virt_to_bus((void *)dev_priv->prim.status) | MGA_PRIMPTREN0 | /* Soft trap, SECEND, SETUPEND */ MGA_PRIMPTREN1 ); /* DWGSYNC */ #endif dev_priv->prim.start = (u8 *)dev_priv->primary->handle; dev_priv->prim.end = ((u8 *)dev_priv->primary->handle + dev_priv->primary->size); dev_priv->prim.size = dev_priv->primary->size; dev_priv->prim.tail = 0; dev_priv->prim.space = dev_priv->prim.size; dev_priv->prim.wrapped = 0; dev_priv->prim.last_flush = 0; dev_priv->prim.last_wrap = 0; dev_priv->prim.high_mark = 256 * DMA_BLOCK_SIZE; dev_priv->prim.status[0] = dev_priv->primary->offset; dev_priv->prim.status[1] = 0; dev_priv->sarea_priv->last_wrap = 0; dev_priv->sarea_priv->last_frame.head = 0; dev_priv->sarea_priv->last_frame.wrap = 0; if ( mga_freelist_init( dev, dev_priv ) < 0 ) { DRM_ERROR( "could not initialize freelist\n" ); /* Assign dev_private so we can do cleanup. */ dev->dev_private = (void *)dev_priv; mga_do_cleanup_dma( dev ); return -ENOMEM; } /* Make dev_private visable to others. */ dev->dev_private = (void *)dev_priv; return 0; }