From 6b432655804f704cb7d1fa3e6317548be1cfc164 Mon Sep 17 00:00:00 2001 From: anholt Date: Tue, 9 Sep 2003 00:24:31 +0000 Subject: Merge from DRI CVS. Includes newly ported SiS 300/305/540/630/730 driver and updates to allow system memory to be used for textures on PCI Radeons. Sponsored by: LinuxFund --- sys/dev/drm/drmP.h | 1 + sys/dev/drm/drm_context.h | 8 + sys/dev/drm/drm_memory.h | 5 + sys/dev/drm/radeon.h | 8 +- sys/dev/drm/radeon_cp.c | 65 ++++---- sys/dev/drm/radeon_drm.h | 20 +-- sys/dev/drm/radeon_drv.c | 8 +- sys/dev/drm/radeon_drv.h | 12 +- sys/dev/drm/radeon_mem.c | 8 +- sys/dev/drm/radeon_state.c | 18 +- sys/dev/drm/sis.h | 79 +++++++++ sys/dev/drm/sis_drm.h | 36 ++++ sys/dev/drm/sis_drv.c | 60 +++++++ sys/dev/drm/sis_drv.h | 48 ++++++ sys/dev/drm/sis_ds.c | 387 +++++++++++++++++++++++++++++++++++++++++++ sys/dev/drm/sis_ds.h | 165 ++++++++++++++++++ sys/dev/drm/sis_mm.c | 404 +++++++++++++++++++++++++++++++++++++++++++++ 17 files changed, 1261 insertions(+), 71 deletions(-) create mode 100644 sys/dev/drm/sis.h create mode 100644 sys/dev/drm/sis_drm.h create mode 100644 sys/dev/drm/sis_drv.c create mode 100644 sys/dev/drm/sis_drv.h create mode 100644 sys/dev/drm/sis_ds.c create mode 100644 sys/dev/drm/sis_ds.h create mode 100644 sys/dev/drm/sis_mm.c diff --git a/sys/dev/drm/drmP.h b/sys/dev/drm/drmP.h index c91d33c..8ecb2c4 100644 --- a/sys/dev/drm/drmP.h +++ b/sys/dev/drm/drmP.h @@ -402,6 +402,7 @@ extern int DRM(version)( DRM_IOCTL_ARGS ); extern void DRM(mem_init)(void); extern void DRM(mem_uninit)(void); extern void *DRM(alloc)(size_t size, int area); +extern void *DRM(calloc)(size_t nmemb, size_t size, int area); extern void *DRM(realloc)(void *oldpt, size_t oldsize, size_t size, int area); extern void DRM(free)(void *pt, size_t size, int area); diff --git a/sys/dev/drm/drm_context.h b/sys/dev/drm/drm_context.h index 3cedfc8..2c8b780 100644 --- a/sys/dev/drm/drm_context.h +++ b/sys/dev/drm/drm_context.h @@ -283,6 +283,11 @@ int DRM(addctx)( DRM_IOCTL_ARGS ) return DRM_ERR(ENOMEM); } +#ifdef DRIVER_CTX_CTOR + if ( ctx.handle != DRM_KERNEL_CONTEXT ) + DRIVER_CTX_CTOR(ctx.handle); /* XXX: also pass dev ? */ +#endif + DRM_COPY_TO_USER_IOCTL( (drm_ctx_t *)data, ctx, sizeof(ctx) ); return 0; @@ -341,6 +346,9 @@ int DRM(rmctx)( DRM_IOCTL_ARGS ) DRM_DEBUG( "%d\n", ctx.handle ); if ( ctx.handle != DRM_KERNEL_CONTEXT ) { +#ifdef DRIVER_CTX_DTOR + DRIVER_CTX_DTOR(ctx.handle); /* XXX: also pass dev ? */ +#endif DRM(ctxbitmap_free)( dev, ctx.handle ); } diff --git a/sys/dev/drm/drm_memory.h b/sys/dev/drm/drm_memory.h index f4e1133..a0e88ee 100644 --- a/sys/dev/drm/drm_memory.h +++ b/sys/dev/drm/drm_memory.h @@ -59,6 +59,11 @@ void *DRM(alloc)(size_t size, int area) return malloc(size, DRM(M_DRM), M_NOWAIT); } +void *DRM(calloc)(size_t nmemb, size_t size, int area) +{ + return malloc(size * nmemb, DRM(M_DRM), M_NOWAIT | M_ZERO); +} + void *DRM(realloc)(void *oldpt, size_t oldsize, size_t size, int area) { void *pt; diff --git a/sys/dev/drm/radeon.h b/sys/dev/drm/radeon.h index c0af52b..99c6d8a 100644 --- a/sys/dev/drm/radeon.h +++ b/sys/dev/drm/radeon.h @@ -70,11 +70,11 @@ * 1.5 - Add r200 packets to cmdbuf ioctl * - Add r200 function to init ioctl * - Add 'scalar2' instruction to cmdbuf - * 1.6 - Add static agp memory manager + * 1.6 - Add static GART memory manager * Add irq handler (won't be turned on unless X server knows to) * Add irq ioctls and irq_active getparam. * Add wait command for cmdbuf ioctl - * Add agp offset query for getparam + * Add GART offset query for getparam * 1.7 - Add support for cube map registers: R200_PP_CUBIC_FACES_[0..5] * and R200_PP_CUBIC_OFFSET_F1_[0..5]. * Added packets R200_EMIT_PP_CUBIC_FACES_[0..5] and @@ -115,7 +115,7 @@ /* When a client dies: * - Check for and clean up flipped page state - * - Free any alloced agp memory. + * - Free any alloced GART memory. * * DRM infrastructure takes care of reclaiming dma buffers. */ @@ -126,7 +126,7 @@ do { \ if ( dev_priv->page_flipping ) { \ radeon_do_cleanup_pageflip( dev ); \ } \ - radeon_mem_release( filp, dev_priv->agp_heap ); \ + radeon_mem_release( filp, dev_priv->gart_heap ); \ radeon_mem_release( filp, dev_priv->fb_heap ); \ } \ } while (0) diff --git a/sys/dev/drm/radeon_cp.c b/sys/dev/drm/radeon_cp.c index 4cabde8..7fb205d 100644 --- a/sys/dev/drm/radeon_cp.c +++ b/sys/dev/drm/radeon_cp.c @@ -857,25 +857,23 @@ static void radeon_cp_init_ring_buffer( drm_device_t *dev, /* Initialize the memory controller */ RADEON_WRITE( RADEON_MC_FB_LOCATION, - (dev_priv->agp_vm_start - 1) & 0xffff0000 ); + (dev_priv->gart_vm_start - 1) & 0xffff0000 ); +#if __REALLY_HAVE_AGP if ( !dev_priv->is_pci ) { RADEON_WRITE( RADEON_MC_AGP_LOCATION, - (((dev_priv->agp_vm_start - 1 + - dev_priv->agp_size) & 0xffff0000) | - (dev_priv->agp_vm_start >> 16)) ); - } + (((dev_priv->gart_vm_start - 1 + + dev_priv->gart_size) & 0xffff0000) | + (dev_priv->gart_vm_start >> 16)) ); -#if __REALLY_HAVE_AGP - if ( !dev_priv->is_pci ) ring_start = (dev_priv->cp_ring->offset - dev->agp->base - + dev_priv->agp_vm_start); - else + + dev_priv->gart_vm_start); + } else #endif ring_start = (dev_priv->cp_ring->offset - dev->sg->handle - + dev_priv->agp_vm_start); + + dev_priv->gart_vm_start); RADEON_WRITE( RADEON_CP_RB_BASE, ring_start ); @@ -893,7 +891,7 @@ static void radeon_cp_init_ring_buffer( drm_device_t *dev, RADEON_WRITE( RADEON_CP_RB_RPTR_ADDR, dev_priv->ring_rptr->offset - dev->agp->base - + dev_priv->agp_vm_start); + + dev_priv->gart_vm_start); } else #endif { @@ -991,11 +989,11 @@ static void radeon_set_pcigart( drm_radeon_private_t *dev_priv, int on ) /* set address range for PCI address translate */ - RADEON_WRITE( RADEON_AIC_LO_ADDR, dev_priv->agp_vm_start ); - RADEON_WRITE( RADEON_AIC_HI_ADDR, dev_priv->agp_vm_start - + dev_priv->agp_size - 1); + RADEON_WRITE( RADEON_AIC_LO_ADDR, dev_priv->gart_vm_start ); + RADEON_WRITE( RADEON_AIC_HI_ADDR, dev_priv->gart_vm_start + + dev_priv->gart_size - 1); - /* Turn off AGP aperture -- is this required for PCIGART? + /* Turn off AGP aperture -- is this required for PCI GART? */ RADEON_WRITE( RADEON_MC_AGP_LOCATION, 0xffffffc0 ); /* ?? */ RADEON_WRITE( RADEON_AGP_COMMAND, 0 ); /* clear AGP_COMMAND */ @@ -1119,7 +1117,7 @@ static int radeon_do_init_cp( drm_device_t *dev, drm_radeon_init_t *init ) dev_priv->ring_offset = init->ring_offset; dev_priv->ring_rptr_offset = init->ring_rptr_offset; dev_priv->buffers_offset = init->buffers_offset; - dev_priv->agp_textures_offset = init->agp_textures_offset; + dev_priv->gart_textures_offset = init->gart_textures_offset; if(!dev_priv->sarea) { DRM_ERROR("could not find sarea!\n"); @@ -1164,11 +1162,10 @@ static int radeon_do_init_cp( drm_device_t *dev, drm_radeon_init_t *init ) return DRM_ERR(EINVAL); } - if ( !dev_priv->is_pci ) { - DRM_FIND_MAP( dev_priv->agp_textures, - init->agp_textures_offset ); - if(!dev_priv->agp_textures) { - DRM_ERROR("could not find agp texture region!\n"); + if ( init->gart_textures_offset ) { + DRM_FIND_MAP( dev_priv->gart_textures, init->gart_textures_offset ); + if ( !dev_priv->gart_textures ) { + DRM_ERROR("could not find GART texture region!\n"); dev->dev_private = (void *)dev_priv; radeon_do_cleanup_cp(dev); return DRM_ERR(EINVAL); @@ -1210,25 +1207,25 @@ static int radeon_do_init_cp( drm_device_t *dev, drm_radeon_init_t *init ) } - dev_priv->agp_size = init->agp_size; - dev_priv->agp_vm_start = RADEON_READ( RADEON_CONFIG_APER_SIZE ); + dev_priv->gart_size = init->gart_size; + dev_priv->gart_vm_start = RADEON_READ( RADEON_CONFIG_APER_SIZE ); #if __REALLY_HAVE_AGP if ( !dev_priv->is_pci ) - dev_priv->agp_buffers_offset = (dev_priv->buffers->offset + dev_priv->gart_buffers_offset = (dev_priv->buffers->offset - dev->agp->base - + dev_priv->agp_vm_start); + + dev_priv->gart_vm_start); else #endif - dev_priv->agp_buffers_offset = (dev_priv->buffers->offset + dev_priv->gart_buffers_offset = (dev_priv->buffers->offset - dev->sg->handle - + dev_priv->agp_vm_start); + + dev_priv->gart_vm_start); - DRM_DEBUG( "dev_priv->agp_size %d\n", - dev_priv->agp_size ); - DRM_DEBUG( "dev_priv->agp_vm_start 0x%x\n", - dev_priv->agp_vm_start ); - DRM_DEBUG( "dev_priv->agp_buffers_offset 0x%lx\n", - dev_priv->agp_buffers_offset ); + DRM_DEBUG( "dev_priv->gart_size %d\n", + dev_priv->gart_size ); + DRM_DEBUG( "dev_priv->gart_vm_start 0x%x\n", + dev_priv->gart_vm_start ); + DRM_DEBUG( "dev_priv->gart_buffers_offset 0x%lx\n", + dev_priv->gart_buffers_offset ); dev_priv->ring.start = (u32 *)dev_priv->cp_ring->handle; dev_priv->ring.end = ((u32 *)dev_priv->cp_ring->handle @@ -1465,7 +1462,7 @@ void radeon_do_release( drm_device_t *dev ) RADEON_WRITE( RADEON_GEN_INT_CNTL, 0 ); /* Free memory heap structures */ - radeon_mem_takedown( &(dev_priv->agp_heap) ); + radeon_mem_takedown( &(dev_priv->gart_heap) ); radeon_mem_takedown( &(dev_priv->fb_heap) ); /* deallocate kernel resources */ diff --git a/sys/dev/drm/radeon_drm.h b/sys/dev/drm/radeon_drm.h index c228c9e..3bf4877 100644 --- a/sys/dev/drm/radeon_drm.h +++ b/sys/dev/drm/radeon_drm.h @@ -216,11 +216,11 @@ typedef union { #define RADEON_NR_SAREA_CLIPRECTS 12 -/* There are 2 heaps (local/AGP). Each region within a heap is a +/* There are 2 heaps (local/GART). Each region within a heap is a * minimum of 64k, and there are at most 64 of them per heap. */ #define RADEON_LOCAL_TEX_HEAP 0 -#define RADEON_AGP_TEX_HEAP 1 +#define RADEON_GART_TEX_HEAP 1 #define RADEON_NR_TEX_HEAPS 2 #define RADEON_NR_TEX_REGIONS 64 #define RADEON_LOG_TEX_GRANULARITY 16 @@ -402,7 +402,7 @@ typedef struct drm_radeon_init { unsigned long sarea_priv_offset; int is_pci; int cp_mode; - int agp_size; + int gart_size; int ring_size; int usec_timeout; @@ -417,7 +417,7 @@ typedef struct drm_radeon_init { unsigned long ring_offset; unsigned long ring_rptr_offset; unsigned long buffers_offset; - unsigned long agp_textures_offset; + unsigned long gart_textures_offset; } drm_radeon_init_t; typedef struct drm_radeon_cp_stop { @@ -527,18 +527,18 @@ typedef struct drm_radeon_indirect { /* 1.3: An ioctl to get parameters that aren't available to the 3d * client any other way. */ -#define RADEON_PARAM_AGP_BUFFER_OFFSET 1 /* card offset of 1st agp buffer */ +#define RADEON_PARAM_GART_BUFFER_OFFSET 1 /* card offset of 1st GART buffer */ #define RADEON_PARAM_LAST_FRAME 2 #define RADEON_PARAM_LAST_DISPATCH 3 #define RADEON_PARAM_LAST_CLEAR 4 /* Added with DRM version 1.6. */ #define RADEON_PARAM_IRQ_NR 5 -#define RADEON_PARAM_AGP_BASE 6 /* card offset of agp base */ +#define RADEON_PARAM_GART_BASE 6 /* card offset of GART base */ /* Added with DRM version 1.8. */ #define RADEON_PARAM_REGISTER_HANDLE 7 /* for drmMap() */ #define RADEON_PARAM_STATUS_HANDLE 8 #define RADEON_PARAM_SAREA_HANDLE 9 -#define RADEON_PARAM_AGP_TEX_HANDLE 10 +#define RADEON_PARAM_GART_TEX_HANDLE 10 typedef struct drm_radeon_getparam { int param; @@ -547,14 +547,14 @@ typedef struct drm_radeon_getparam { /* 1.6: Set up a memory manager for regions of shared memory: */ -#define RADEON_MEM_REGION_AGP 1 -#define RADEON_MEM_REGION_FB 2 +#define RADEON_MEM_REGION_GART 1 +#define RADEON_MEM_REGION_FB 2 typedef struct drm_radeon_mem_alloc { int region; int alignment; int size; - int *region_offset; /* offset from start of fb or agp */ + int *region_offset; /* offset from start of fb or GART */ } drm_radeon_mem_alloc_t; typedef struct drm_radeon_mem_free { diff --git a/sys/dev/drm/radeon_drv.c b/sys/dev/drm/radeon_drv.c index 115dab5..c8f23c4 100644 --- a/sys/dev/drm/radeon_drv.c +++ b/sys/dev/drm/radeon_drv.c @@ -40,7 +40,6 @@ drm_chipinfo_t DRM(devicelist)[] = { {0x1002, 0x4242, 1, "ATI Radeon BB R200 AIW 8500DV"}, - {0x1002, 0x4336, 1, "ATI Radeon Mobility U1"}, {0x1002, 0x4964, 1, "ATI Radeon Id R250 9000"}, {0x1002, 0x4965, 1, "ATI Radeon Ie R250 9000"}, {0x1002, 0x4966, 1, "ATI Radeon If R250 9000"}, @@ -57,7 +56,7 @@ drm_chipinfo_t DRM(devicelist)[] = { {0x1002, 0x5145, 1, "ATI Radeon QE R100"}, {0x1002, 0x5146, 1, "ATI Radeon QF R100"}, {0x1002, 0x5147, 1, "ATI Radeon QG R100"}, - {0x1002, 0x5148, 1, "ATI Radeon QH FireGL 8x00"}, + {0x1002, 0x5148, 1, "ATI Radeon QH R200 8500"}, {0x1002, 0x5149, 1, "ATI Radeon QI R200"}, {0x1002, 0x514A, 1, "ATI Radeon QJ R200"}, {0x1002, 0x514B, 1, "ATI Radeon QK R200"}, @@ -67,13 +66,14 @@ drm_chipinfo_t DRM(devicelist)[] = { {0x1002, 0x514F, 1, "ATI Radeon QO R200 8500 LE"}, {0x1002, 0x5157, 1, "ATI Radeon QW RV200 7500"}, {0x1002, 0x5158, 1, "ATI Radeon QX RV200 7500"}, - {0x1002, 0x5159, 1, "ATI Radeon QY RV100 VE"}, - {0x1002, 0x515A, 1, "ATI Radeon QZ RV100 VE"}, + {0x1002, 0x5159, 1, "ATI Radeon QY RV100 7000/VE"}, + {0x1002, 0x515A, 1, "ATI Radeon QZ RV100 7000/VE"}, {0x1002, 0x5168, 1, "ATI Radeon Qh R200"}, {0x1002, 0x5169, 1, "ATI Radeon Qi R200"}, {0x1002, 0x516A, 1, "ATI Radeon Qj R200"}, {0x1002, 0x516B, 1, "ATI Radeon Qk R200"}, {0x1002, 0x516C, 1, "ATI Radeon Ql R200"}, + {0x1002, 0x5961, 1, "ATI Radeon RV280 9200"}, {0, 0, 0, NULL} }; diff --git a/sys/dev/drm/radeon_drv.h b/sys/dev/drm/radeon_drv.h index e23ec0f..1e9d2af 100644 --- a/sys/dev/drm/radeon_drv.h +++ b/sys/dev/drm/radeon_drv.h @@ -75,9 +75,9 @@ typedef struct drm_radeon_private { drm_radeon_ring_buffer_t ring; drm_radeon_sarea_t *sarea_priv; - int agp_size; - u32 agp_vm_start; - unsigned long agp_buffers_offset; + int gart_size; + u32 gart_vm_start; + unsigned long gart_buffers_offset; int cp_mode; int cp_running; @@ -132,7 +132,7 @@ typedef struct drm_radeon_private { unsigned long ring_offset; unsigned long ring_rptr_offset; unsigned long buffers_offset; - unsigned long agp_textures_offset; + unsigned long gart_textures_offset; drm_local_map_t *sarea; drm_local_map_t *fb; @@ -140,9 +140,9 @@ typedef struct drm_radeon_private { drm_local_map_t *cp_ring; drm_local_map_t *ring_rptr; drm_local_map_t *buffers; - drm_local_map_t *agp_textures; + drm_local_map_t *gart_textures; - struct mem_block *agp_heap; + struct mem_block *gart_heap; struct mem_block *fb_heap; /* SW interrupt */ diff --git a/sys/dev/drm/radeon_mem.c b/sys/dev/drm/radeon_mem.c index 62d57fd..ed72dd6 100644 --- a/sys/dev/drm/radeon_mem.c +++ b/sys/dev/drm/radeon_mem.c @@ -1,4 +1,4 @@ -/* radeon_mem.c -- Simple agp/fb memory manager for radeon -*- linux-c -*- +/* radeon_mem.c -- Simple GART/fb memory manager for radeon -*- linux-c -*- * * Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved. * @@ -39,7 +39,7 @@ __FBSDID("$FreeBSD$"); #include "dev/drm/radeon_drm.h" #include "dev/drm/radeon_drv.h" -/* Very simple allocator for agp memory, working on a static range +/* Very simple allocator for GART memory, working on a static range * already mapped into each client's address space. */ @@ -216,8 +216,8 @@ static struct mem_block **get_heap( drm_radeon_private_t *dev_priv, int region ) { switch( region ) { - case RADEON_MEM_REGION_AGP: - return &dev_priv->agp_heap; + case RADEON_MEM_REGION_GART: + return &dev_priv->gart_heap; case RADEON_MEM_REGION_FB: return &dev_priv->fb_heap; default: diff --git a/sys/dev/drm/radeon_state.c b/sys/dev/drm/radeon_state.c index 235fa17..cbeeedd 100644 --- a/sys/dev/drm/radeon_state.c +++ b/sys/dev/drm/radeon_state.c @@ -895,7 +895,7 @@ static void radeon_cp_dispatch_vertex( drm_device_t *dev, { drm_radeon_private_t *dev_priv = dev->dev_private; drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv; - int offset = dev_priv->agp_buffers_offset + buf->offset + prim->start; + int offset = dev_priv->gart_buffers_offset + buf->offset + prim->start; int numverts = (int)prim->numverts; int nbox = sarea_priv->nbox; int i = 0; @@ -968,7 +968,7 @@ static void radeon_cp_dispatch_indirect( drm_device_t *dev, buf->idx, start, end ); if ( start != end ) { - int offset = (dev_priv->agp_buffers_offset + int offset = (dev_priv->gart_buffers_offset + buf->offset + start); int dwords = (end - start + 3) / sizeof(u32); @@ -1001,7 +1001,7 @@ static void radeon_cp_dispatch_indices( drm_device_t *dev, { drm_radeon_private_t *dev_priv = dev->dev_private; drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv; - int offset = dev_priv->agp_buffers_offset + prim->offset; + int offset = dev_priv->gart_buffers_offset + prim->offset; u32 *data; int dwords; int i = 0; @@ -2161,8 +2161,8 @@ int radeon_cp_getparam( DRM_IOCTL_ARGS ) DRM_DEBUG( "pid=%d\n", DRM_CURRENTPID ); switch( param.param ) { - case RADEON_PARAM_AGP_BUFFER_OFFSET: - value = dev_priv->agp_buffers_offset; + case RADEON_PARAM_GART_BUFFER_OFFSET: + value = dev_priv->gart_buffers_offset; break; case RADEON_PARAM_LAST_FRAME: dev_priv->stats.last_frame_reads++; @@ -2178,8 +2178,8 @@ int radeon_cp_getparam( DRM_IOCTL_ARGS ) case RADEON_PARAM_IRQ_NR: value = dev->irq; break; - case RADEON_PARAM_AGP_BASE: - value = dev_priv->agp_vm_start; + case RADEON_PARAM_GART_BASE: + value = dev_priv->gart_vm_start; break; case RADEON_PARAM_REGISTER_HANDLE: value = dev_priv->mmio_offset; @@ -2191,8 +2191,8 @@ int radeon_cp_getparam( DRM_IOCTL_ARGS ) /* The lock is the first dword in the sarea. */ value = (int)dev->lock.hw_lock; break; - case RADEON_PARAM_AGP_TEX_HANDLE: - value = dev_priv->agp_textures_offset; + case RADEON_PARAM_GART_TEX_HANDLE: + value = dev_priv->gart_textures_offset; break; default: return DRM_ERR(EINVAL); diff --git a/sys/dev/drm/sis.h b/sys/dev/drm/sis.h new file mode 100644 index 0000000..23fc413 --- /dev/null +++ b/sys/dev/drm/sis.h @@ -0,0 +1,79 @@ +/* sis_drv.h -- Private header for sis driver -*- linux-c -*- + * + * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. + * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * $FreeBSD$ + */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/sis.h,v 1.3 2002/10/30 12:52:38 alanh Exp $ */ + +#ifndef __SIS_H__ +#define __SIS_H__ + +/* This remains constant for all DRM template files. + * Name it sisdrv_##x as there's a conflict with sis_free/malloc in the kernel + * that's used for fb devices + */ +#ifdef __linux__ +#define DRM(x) sisdrv_##x +#else +#define DRM(x) sis_##x +#endif + +/* General customization: + */ +#define __HAVE_AGP 1 +#define __MUST_HAVE_AGP 0 +#define __HAVE_MTRR 1 +#define __HAVE_CTX_BITMAP 1 + +#define DRIVER_AUTHOR "SIS" +#define DRIVER_NAME "sis" +#define DRIVER_DESC "SIS 300/630/540" +#define DRIVER_DATE "20030826" +#define DRIVER_MAJOR 1 +#define DRIVER_MINOR 1 +#define DRIVER_PATCHLEVEL 0 + +#define DRIVER_IOCTLS \ + [DRM_IOCTL_NR(DRM_IOCTL_SIS_FB_ALLOC)] = { sis_fb_alloc, 1, 0 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_SIS_FB_FREE)] = { sis_fb_free, 1, 0 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_SIS_AGP_INIT)] = { sis_ioctl_agp_init, 1, 1 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_SIS_AGP_ALLOC)] = { sis_ioctl_agp_alloc, 1, 0 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_SIS_AGP_FREE)] = { sis_ioctl_agp_free, 1, 0 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_SIS_FB_INIT)] = { sis_fb_init, 1, 1 } + +#define __HAVE_COUNTERS 5 + +/* Buffer customization: + */ +#define DRIVER_AGP_BUFFERS_MAP( dev ) \ + ((drm_sis_private_t *)((dev)->dev_private))->buffers + +extern int sis_init_context(int context); +extern int sis_final_context(int context); + +#define DRIVER_CTX_CTOR sis_init_context +#define DRIVER_CTX_DTOR sis_final_context + +#endif diff --git a/sys/dev/drm/sis_drm.h b/sys/dev/drm/sis_drm.h new file mode 100644 index 0000000..18711a5 --- /dev/null +++ b/sys/dev/drm/sis_drm.h @@ -0,0 +1,36 @@ +/* + * $FreeBSD$ + */ + +#ifndef __SIS_DRM_H__ +#define __SIS_DRM_H__ + +/* SiS specific ioctls */ +#define DRM_IOCTL_SIS_FB_ALLOC DRM_IOWR(0x44, drm_sis_mem_t) +#define DRM_IOCTL_SIS_FB_FREE DRM_IOW( 0x45, drm_sis_mem_t) +#define DRM_IOCTL_SIS_AGP_INIT DRM_IOWR(0x53, drm_sis_agp_t) +#define DRM_IOCTL_SIS_AGP_ALLOC DRM_IOWR(0x54, drm_sis_mem_t) +#define DRM_IOCTL_SIS_AGP_FREE DRM_IOW( 0x55, drm_sis_mem_t) +#define DRM_IOCTL_SIS_FB_INIT DRM_IOW( 0x56, drm_sis_fb_t) +/* +#define DRM_IOCTL_SIS_FLIP DRM_IOW( 0x48, drm_sis_flip_t) +#define DRM_IOCTL_SIS_FLIP_INIT DRM_IO( 0x49) +#define DRM_IOCTL_SIS_FLIP_FINAL DRM_IO( 0x50) +*/ + +typedef struct { + int context; + unsigned int offset; + unsigned int size; + unsigned long free; +} drm_sis_mem_t; + +typedef struct { + unsigned int offset, size; +} drm_sis_agp_t; + +typedef struct { + unsigned int offset, size; +} drm_sis_fb_t; + +#endif /* __SIS_DRM_H__ */ diff --git a/sys/dev/drm/sis_drv.c b/sys/dev/drm/sis_drv.c new file mode 100644 index 0000000..fdf0f16 --- /dev/null +++ b/sys/dev/drm/sis_drv.c @@ -0,0 +1,60 @@ +/* sis.c -- sis driver -*- linux-c -*- + * + * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. + * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * $FreeBSD$ + */ + +#include "dev/drm/sis.h" +#include "dev/drm/drmP.h" +#include "dev/drm/sis_drm.h" +#include "dev/drm/sis_drv.h" + +drm_chipinfo_t DRM(devicelist)[] = { + {0x1039, 0x0300, 1, "SiS 300"}, + {0x1039, 0x5300, 1, "SiS 540"}, + {0x1039, 0x6300, 1, "SiS 630"}, + {0, 0, 0, NULL} +}; + +#include "dev/drm/drm_auth.h" +#include "dev/drm/drm_agpsupport.h" +#include "dev/drm/drm_bufs.h" +#include "dev/drm/drm_context.h" +#include "dev/drm/drm_dma.h" +#include "dev/drm/drm_drawable.h" +#include "dev/drm/drm_drv.h" +#include "dev/drm/drm_fops.h" +#include "dev/drm/drm_ioctl.h" +#include "dev/drm/drm_lock.h" +#include "dev/drm/drm_memory.h" +#include "dev/drm/drm_vm.h" +#include "dev/drm/drm_sysctl.h" + +#ifdef __FreeBSD__ +/* Avoid clash with sis ethernet */ +DRIVER_MODULE(sisdrm, pci, sis_driver, sis_devclass, 0, 0); +#elif defined(__NetBSD__) +CFDRIVER_DECL(sis, DV_TTY, NULL); +#endif /* __FreeBSD__ */ diff --git a/sys/dev/drm/sis_drv.h b/sys/dev/drm/sis_drv.h new file mode 100644 index 0000000..3f80901 --- /dev/null +++ b/sys/dev/drm/sis_drv.h @@ -0,0 +1,48 @@ +/* sis_drv.h -- Private header for sis driver -*- linux-c -*- + * + * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. + * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * $FreeBSD$ + */ + +#ifndef _SIS_DRV_H_ +#define _SIS_DRV_H_ + +#include "dev/drm/sis_ds.h" + +typedef struct drm_sis_private { + drm_map_t *buffers; + + memHeap_t *AGPHeap; + memHeap_t *FBHeap; +} drm_sis_private_t; + +extern int sis_fb_alloc( DRM_IOCTL_ARGS ); +extern int sis_fb_free( DRM_IOCTL_ARGS ); +extern int sis_ioctl_agp_init( DRM_IOCTL_ARGS ); +extern int sis_ioctl_agp_alloc( DRM_IOCTL_ARGS ); +extern int sis_ioctl_agp_free( DRM_IOCTL_ARGS ); +extern int sis_fb_init( DRM_IOCTL_ARGS ); + +#endif diff --git a/sys/dev/drm/sis_ds.c b/sys/dev/drm/sis_ds.c new file mode 100644 index 0000000..74b111e --- /dev/null +++ b/sys/dev/drm/sis_ds.c @@ -0,0 +1,387 @@ +/* sis_ds.c -- Private header for Direct Rendering Manager -*- linux-c -*- + * Created: Mon Jan 4 10:05:05 1999 by sclin@sis.com.tw + * + * Copyright 2000 Silicon Integrated Systems Corp, Inc., HsinChu, Taiwan. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: + * Sung-Ching Lin + * + * $FreeBSD$ + */ + +#include "dev/drm/sis.h" +#include "dev/drm/drmP.h" +#include "dev/drm/drm.h" +#include "dev/drm/sis_ds.h" + +/* Set Data Structure, not check repeated value + * temporarily used + */ + +set_t *setInit(void) +{ + int i; + set_t *set; + + set = (set_t *)DRM(alloc)(sizeof(set_t), DRM_MEM_DRIVER); + if (set != NULL) { + for (i = 0; i < SET_SIZE; i++) { + set->list[i].free_next = i + 1; + set->list[i].alloc_next = -1; + } + set->list[SET_SIZE-1].free_next = -1; + set->free = 0; + set->alloc = -1; + set->trace = -1; + } + return set; +} + +int setAdd(set_t *set, ITEM_TYPE item) +{ + int free = set->free; + + if (free != -1) { + set->list[free].val = item; + set->free = set->list[free].free_next; + } else { + return 0; + } + + set->list[free].alloc_next = set->alloc; + set->alloc = free; + set->list[free].free_next = -1; + + return 1; +} + +int setDel(set_t *set, ITEM_TYPE item) +{ + int alloc = set->alloc; + int prev = -1; + + while (alloc != -1) { + if (set->list[alloc].val == item) { + if (prev != -1) + set->list[prev].alloc_next = + set->list[alloc].alloc_next; + else + set->alloc = set->list[alloc].alloc_next; + break; + } + prev = alloc; + alloc = set->list[alloc].alloc_next; + } + + if (alloc == -1) + return 0; + + set->list[alloc].free_next = set->free; + set->free = alloc; + set->list[alloc].alloc_next = -1; + + return 1; +} + +/* setFirst -> setAdd -> setNext is wrong */ + +int setFirst(set_t *set, ITEM_TYPE *item) +{ + if (set->alloc == -1) + return 0; + + *item = set->list[set->alloc].val; + set->trace = set->list[set->alloc].alloc_next; + + return 1; +} + +int setNext(set_t *set, ITEM_TYPE *item) +{ + if (set->trace == -1) + return 0; + + *item = set->list[set->trace].val; + set->trace = set->list[set->trace].alloc_next; + + return 1; +} + +int setDestroy(set_t *set) +{ + DRM(free)(set, sizeof(set_t), DRM_MEM_DRIVER); + + return 1; +} + +/* + * GLX Hardware Device Driver common code + * Copyright (C) 1999 Keith Whitwell + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * KEITH WHITWELL, OR ANY OTHER CONTRIBUTORS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#define ISFREE(bptr) ((bptr)->free) + +memHeap_t *mmInit(int ofs, + int size) +{ + PMemBlock blocks; + + if (size <= 0) + return 0; + + blocks = (TMemBlock *)DRM(calloc)(1, sizeof(TMemBlock), DRM_MEM_DRIVER); + if (blocks != NULL) { + blocks->ofs = ofs; + blocks->size = size; + blocks->free = 1; + return (memHeap_t *)blocks; + } else + return 0; +} + +/* Checks if a pointer 'b' is part of the heap 'heap' */ +int mmBlockInHeap(memHeap_t *heap, PMemBlock b) +{ + TMemBlock *p; + + if (heap == NULL || b == NULL) + return 0; + + p = heap; + while (p != NULL && p != b) { + p = p->next; + } + if (p == b) + return 1; + else + return 0; +} + +/* Kludgey workaround for existing i810 server. Remove soon. + */ +memHeap_t *mmAddRange( memHeap_t *heap, + int ofs, + int size ) +{ + PMemBlock blocks; + blocks = (TMemBlock *)DRM(calloc)(2, sizeof(TMemBlock), DRM_MEM_DRIVER); + if (blocks != NULL) { + blocks[0].size = size; + blocks[0].free = 1; + blocks[0].ofs = ofs; + blocks[0].next = &blocks[1]; + + /* Discontinuity - stops JoinBlock from trying to join + * non-adjacent ranges. + */ + blocks[1].size = 0; + blocks[1].free = 0; + blocks[1].ofs = ofs+size; + blocks[1].next = (PMemBlock)heap; + return (memHeap_t *)blocks; + } else + return heap; +} + +static TMemBlock* SliceBlock(TMemBlock *p, + int startofs, int size, + int reserved, int alignment) +{ + TMemBlock *newblock; + + /* break left */ + if (startofs > p->ofs) { + newblock = (TMemBlock*) DRM(calloc)(1, sizeof(TMemBlock), + DRM_MEM_DRIVER); + newblock->ofs = startofs; + newblock->size = p->size - (startofs - p->ofs); + newblock->free = 1; + newblock->next = p->next; + p->size -= newblock->size; + p->next = newblock; + p = newblock; + } + + /* break right */ + if (size < p->size) { + newblock = (TMemBlock*) DRM(calloc)(1, sizeof(TMemBlock), + DRM_MEM_DRIVER); + newblock->ofs = startofs + size; + newblock->size = p->size - size; + newblock->free = 1; + newblock->next = p->next; + p->size = size; + p->next = newblock; + } + + /* p = middle block */ + p->align = alignment; + p->free = 0; + p->reserved = reserved; + return p; +} + +PMemBlock mmAllocMem( memHeap_t *heap, int size, int align2, int startSearch) +{ + int mask,startofs, endofs; + TMemBlock *p; + + if (heap == NULL || align2 < 0 || size <= 0) + return NULL; + + mask = (1 << align2)-1; + startofs = 0; + p = (TMemBlock *)heap; + while (p != NULL) { + if (ISFREE(p)) { + startofs = (p->ofs + mask) & ~mask; + if ( startofs < startSearch ) { + startofs = startSearch; + } + endofs = startofs+size; + if (endofs <= (p->ofs+p->size)) + break; + } + p = p->next; + } + if (p == NULL) + return NULL; + p = SliceBlock(p,startofs,size,0,mask+1); + p->heap = heap; + return p; +} + +static __inline__ int Join2Blocks(TMemBlock *p) +{ + if (p->free && p->next && p->next->free) { + TMemBlock *q = p->next; + p->size += q->size; + p->next = q->next; + DRM(free)(q, sizeof(TMemBlock), DRM_MEM_DRIVER); + return 1; + } + return 0; +} + +int mmFreeMem(PMemBlock b) +{ + TMemBlock *p, *prev; + + if (b == NULL) + return 0; + if (b->heap == NULL) + return -1; + + p = b->heap; + prev = NULL; + while (p != NULL && p != b) { + prev = p; + p = p->next; + } + if (p == NULL || p->free || p->reserved) + return -1; + + p->free = 1; + Join2Blocks(p); + if (prev) + Join2Blocks(prev); + return 0; +} + +int mmReserveMem(memHeap_t *heap, int offset,int size) +{ + int endofs; + TMemBlock *p; + + if (heap == NULL || size <= 0) + return -1; + + endofs = offset + size; + p = (TMemBlock *)heap; + while (p && p->ofs <= offset) { + if (ISFREE(p) && endofs <= (p->ofs+p->size)) { + SliceBlock(p,offset,size,1,1); + return 0; + } + p = p->next; + } + return -1; +} + +int mmFreeReserved(memHeap_t *heap, int offset) +{ + TMemBlock *p,*prev; + + if (heap == NULL) + return -1; + + p = (TMemBlock *)heap; + prev = NULL; + while (p != NULL && p->ofs != offset) { + prev = p; + p = p->next; + } + if (p == NULL || !p->reserved) + return -1; + + p->free = 1; + p->reserved = 0; + Join2Blocks(p); + if (prev != NULL) + Join2Blocks(prev); + return 0; +} + +void mmDestroy(memHeap_t *heap) +{ + TMemBlock *p,*q; + + if (heap == NULL) + return; + + p = (TMemBlock *)heap; + while (p != NULL) { + q = p->next; + DRM(free)(p, sizeof(TMemBlock), DRM_MEM_DRIVER); + p = q; + } +} diff --git a/sys/dev/drm/sis_ds.h b/sys/dev/drm/sis_ds.h new file mode 100644 index 0000000..c57e132 --- /dev/null +++ b/sys/dev/drm/sis_ds.h @@ -0,0 +1,165 @@ +/* sis_ds.h -- Private header for Direct Rendering Manager -*- linux-c -*- + * Created: Mon Jan 4 10:05:05 1999 by sclin@sis.com.tw + * + * Copyright 2000 Silicon Integrated Systems Corp, Inc., HsinChu, Taiwan. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: + * Sung-Ching Lin + * + * $FreeBSD$ + */ + +#ifndef __SIS_DS_H__ +#define __SIS_DS_H__ + +/* Set Data Structure */ + +#define SET_SIZE 5000 + +typedef unsigned int ITEM_TYPE; + +typedef struct { + ITEM_TYPE val; + int alloc_next, free_next; +} list_item_t; + +typedef struct { + int alloc; + int free; + int trace; + list_item_t list[SET_SIZE]; +} set_t; + +set_t *setInit(void); +int setAdd(set_t *set, ITEM_TYPE item); +int setDel(set_t *set, ITEM_TYPE item); +int setFirst(set_t *set, ITEM_TYPE *item); +int setNext(set_t *set, ITEM_TYPE *item); +int setDestroy(set_t *set); + +/* + * GLX Hardware Device Driver common code + * Copyright (C) 1999 Keith Whitwell + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * KEITH WHITWELL, OR ANY OTHER CONTRIBUTORS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +struct mem_block_t { + struct mem_block_t *next; + struct mem_block_t *heap; + int ofs,size; + int align; + int free:1; + int reserved:1; +}; +typedef struct mem_block_t TMemBlock; +typedef struct mem_block_t *PMemBlock; + +/* a heap is just the first block in a chain */ +typedef struct mem_block_t memHeap_t; + +static __inline__ int mmBlockSize(PMemBlock b) +{ + return b->size; +} + +static __inline__ int mmOffset(PMemBlock b) +{ + return b->ofs; +} + +static __inline__ void mmMarkReserved(PMemBlock b) +{ + b->reserved = 1; +} + +/* + * input: total size in bytes + * return: a heap pointer if OK, NULL if error + */ +memHeap_t *mmInit( int ofs, int size ); + +memHeap_t *mmAddRange( memHeap_t *heap, + int ofs, + int size ); + +/* + * Allocate 'size' bytes with 2^align2 bytes alignment, + * restrict the search to free memory after 'startSearch' + * depth and back buffers should be in different 4mb banks + * to get better page hits if possible + * input: size = size of block + * align2 = 2^align2 bytes alignment + * startSearch = linear offset from start of heap to begin search + * return: pointer to the allocated block, 0 if error + */ +PMemBlock mmAllocMem( memHeap_t *heap, int size, int align2, int startSearch ); + +/* + * Returns 1 if the block 'b' is part of the heap 'heap' + */ +int mmBlockInHeap( PMemBlock heap, PMemBlock b ); + +/* + * Free block starts at offset + * input: pointer to a block + * return: 0 if OK, -1 if error + */ +int mmFreeMem( PMemBlock b ); + +/* + * Reserve 'size' bytes block start at offset + * This is used to prevent allocation of memory already used + * by the X server for the front buffer, pixmaps, and cursor + * input: size, offset + * output: 0 if OK, -1 if error + */ +int mmReserveMem( memHeap_t *heap, int offset,int size ); +int mmFreeReserved( memHeap_t *heap, int offset ); + +/* + * destroy MM + */ +void mmDestroy( memHeap_t *mmInit ); + +/* For debuging purpose. */ +void mmDumpMemInfo( memHeap_t *mmInit ); + +#endif /* __SIS_DS_H__ */ diff --git a/sys/dev/drm/sis_mm.c b/sys/dev/drm/sis_mm.c new file mode 100644 index 0000000..7065b95 --- /dev/null +++ b/sys/dev/drm/sis_mm.c @@ -0,0 +1,404 @@ +/* sis_mm.c -- Private header for Direct Rendering Manager -*- linux-c -*- + * Created: Mon Jan 4 10:05:05 1999 by sclin@sis.com.tw + * + * Copyright 2000 Silicon Integrated Systems Corp, Inc., HsinChu, Taiwan. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: + * Sung-Ching Lin + * + * $FreeBSD$ + */ + +#include "dev/drm/sis.h" +#include "dev/drm/drmP.h" +#include "dev/drm/sis_drm.h" +#include "dev/drm/sis_drv.h" +#include "dev/drm/sis_ds.h" +#if defined(__linux__) && defined(CONFIG_FB_SIS) +#include +#endif + +#define MAX_CONTEXT 100 +#define VIDEO_TYPE 0 +#define AGP_TYPE 1 + +typedef struct { + int used; + int context; + set_t *sets[2]; /* 0 for video, 1 for AGP */ +} sis_context_t; + +static sis_context_t global_ppriv[MAX_CONTEXT]; + + +static int add_alloc_set(int context, int type, unsigned int val) +{ + int i, retval = 0; + + for (i = 0; i < MAX_CONTEXT; i++) { + if (global_ppriv[i].used && global_ppriv[i].context == context) + { + retval = setAdd(global_ppriv[i].sets[type], val); + break; + } + } + return retval; +} + +static int del_alloc_set(int context, int type, unsigned int val) +{ + int i, retval = 0; + + for (i = 0; i < MAX_CONTEXT; i++) { + if (global_ppriv[i].used && global_ppriv[i].context == context) + { + retval = setDel(global_ppriv[i].sets[type], val); + break; + } + } + return retval; +} + +/* fb management via fb device */ +#if defined(__linux__) && defined(CONFIG_FB_SIS) + +int sis_fb_init( DRM_IOCTL_ARGS ) +{ + return 0; +} + +int sis_fb_alloc( DRM_IOCTL_ARGS ) +{ + drm_sis_mem_t fb; + struct sis_memreq req; + int retval = 0; + + DRM_COPY_FROM_USER_IOCTL(fb, (drm_sis_mem_t *)data, sizeof(fb)); + + req.size = fb.size; + sis_malloc(&req); + if (req.offset) { + /* TODO */ + fb.offset = req.offset; + fb.free = req.offset; + if (!add_alloc_set(fb.context, VIDEO_TYPE, fb.free)) { + DRM_DEBUG("adding to allocation set fails\n"); + sis_free(req.offset); + retval = DRM_ERR(EINVAL); + } + } else { + fb.offset = 0; + fb.size = 0; + fb.free = 0; + } + + DRM_COPY_TO_USER_IOCTL((drm_sis_mem_t *)data, fb, sizeof(fb)); + + DRM_DEBUG("alloc fb, size = %d, offset = %ld\n", fb.size, req.offset); + + return retval; +} + +int sis_fb_free( DRM_IOCTL_ARGS ) +{ + drm_sis_mem_t fb; + int retval = 0; + + DRM_COPY_FROM_USER_IOCTL(fb, (drm_sis_mem_t *)data, sizeof(fb)); + + if (!fb.free) + return DRM_ERR(EINVAL); + + if (!del_alloc_set(fb.context, VIDEO_TYPE, fb.free)) + retval = DRM_ERR(EINVAL); + sis_free(fb.free); + + DRM_DEBUG("free fb, offset = %d\n", fb.free); + + return retval; +} + +#else + +/* Called by the X Server to initialize the FB heap. Allocations will fail + * unless this is called. Offset is the beginning of the heap from the + * framebuffer offset (MaxXFBMem in XFree86). + * + * Memory layout according to Thomas Winischofer: + * |------------------|DDDDDDDDDDDDDDDDDDDDDDDDDDDDD|HHHH|CCCCCCCCCCC| + * + * X driver/sisfb HW- Command- + * framebuffer memory DRI heap Cursor queue + */ +int sis_fb_init( DRM_IOCTL_ARGS ) +{ + DRM_DEVICE; + drm_sis_private_t *dev_priv = dev->dev_private; + drm_sis_fb_t fb; + + DRM_COPY_FROM_USER_IOCTL(fb, (drm_sis_fb_t *)data, sizeof(fb)); + + if (dev_priv == NULL) { + dev->dev_private = DRM(calloc)(1, sizeof(drm_sis_private_t), + DRM_MEM_DRIVER); + dev_priv = dev->dev_private; + if (dev_priv == NULL) + return ENOMEM; + } + + if (dev_priv->FBHeap != NULL) + return DRM_ERR(EINVAL); + + dev_priv->FBHeap = mmInit(fb.offset, fb.size); + + DRM_DEBUG("offset = %u, size = %u", fb.offset, fb.size); + + return 0; +} + +int sis_fb_alloc( DRM_IOCTL_ARGS ) +{ + DRM_DEVICE; + drm_sis_private_t *dev_priv = dev->dev_private; + drm_sis_mem_t fb; + PMemBlock block; + int retval = 0; + + if (dev_priv == NULL || dev_priv->FBHeap == NULL) + return DRM_ERR(EINVAL); + + DRM_COPY_FROM_USER_IOCTL(fb, (drm_sis_mem_t *)data, sizeof(fb)); + + block = mmAllocMem(dev_priv->FBHeap, fb.size, 0, 0); + if (block) { + /* TODO */ + fb.offset = block->ofs; + fb.free = (unsigned long)block; + if (!add_alloc_set(fb.context, VIDEO_TYPE, fb.free)) { + DRM_DEBUG("adding to allocation set fails\n"); + mmFreeMem((PMemBlock)fb.free); + retval = DRM_ERR(EINVAL); + } + } else { + fb.offset = 0; + fb.size = 0; + fb.free = 0; + } + + DRM_COPY_TO_USER_IOCTL((drm_sis_mem_t *)data, fb, sizeof(fb)); + + DRM_DEBUG("alloc fb, size = %d, offset = %d\n", fb.size, fb.offset); + + return retval; +} + +int sis_fb_free( DRM_IOCTL_ARGS ) +{ + DRM_DEVICE; + drm_sis_private_t *dev_priv = dev->dev_private; + drm_sis_mem_t fb; + + if (dev_priv == NULL || dev_priv->FBHeap == NULL) + return DRM_ERR(EINVAL); + + DRM_COPY_FROM_USER_IOCTL(fb, (drm_sis_mem_t *)data, sizeof(fb)); + + if (!mmBlockInHeap(dev_priv->FBHeap, (PMemBlock)fb.free)) + return DRM_ERR(EINVAL); + + if (!del_alloc_set(fb.context, VIDEO_TYPE, fb.free)) + return DRM_ERR(EINVAL); + mmFreeMem((PMemBlock)fb.free); + + DRM_DEBUG("free fb, free = 0x%lx\n", fb.free); + + return 0; +} + +#endif + +/* agp memory management */ + +int sis_ioctl_agp_init( DRM_IOCTL_ARGS ) +{ + DRM_DEVICE; + drm_sis_private_t *dev_priv = dev->dev_private; + drm_sis_agp_t agp; + + if (dev_priv == NULL) { + dev->dev_private = DRM(calloc)(1, sizeof(drm_sis_private_t), + DRM_MEM_DRIVER); + dev_priv = dev->dev_private; + if (dev_priv == NULL) + return ENOMEM; + } + + if (dev_priv->AGPHeap != NULL) + return DRM_ERR(EINVAL); + + DRM_COPY_FROM_USER_IOCTL(agp, (drm_sis_agp_t *)data, sizeof(agp)); + + dev_priv->AGPHeap = mmInit(agp.offset, agp.size); + + DRM_DEBUG("offset = %u, size = %u", agp.offset, agp.size); + + return 0; +} + +int sis_ioctl_agp_alloc( DRM_IOCTL_ARGS ) +{ + DRM_DEVICE; + drm_sis_private_t *dev_priv = dev->dev_private; + drm_sis_mem_t agp; + PMemBlock block; + int retval = 0; + + if (dev_priv == NULL || dev_priv->AGPHeap == NULL) + return DRM_ERR(EINVAL); + + DRM_COPY_FROM_USER_IOCTL(agp, (drm_sis_mem_t *)data, sizeof(agp)); + + block = mmAllocMem(dev_priv->AGPHeap, agp.size, 0, 0); + if (block) { + /* TODO */ + agp.offset = block->ofs; + agp.free = (unsigned long)block; + if (!add_alloc_set(agp.context, AGP_TYPE, agp.free)) { + DRM_DEBUG("adding to allocation set fails\n"); + mmFreeMem((PMemBlock)agp.free); + retval = -1; + } + } else { + agp.offset = 0; + agp.size = 0; + agp.free = 0; + } + + DRM_COPY_TO_USER_IOCTL((drm_sis_mem_t *)data, agp, sizeof(agp)); + + DRM_DEBUG("alloc agp, size = %d, offset = %d\n", agp.size, agp.offset); + + return retval; +} + +int sis_ioctl_agp_free( DRM_IOCTL_ARGS ) +{ + DRM_DEVICE; + drm_sis_private_t *dev_priv = dev->dev_private; + drm_sis_mem_t agp; + + if (dev_priv == NULL || dev_priv->AGPHeap == NULL) + return DRM_ERR(EINVAL); + + DRM_COPY_FROM_USER_IOCTL(agp, (drm_sis_mem_t *)data, sizeof(agp)); + + if (!mmBlockInHeap(dev_priv->AGPHeap, (PMemBlock)agp.free)) + return DRM_ERR(EINVAL); + + mmFreeMem((PMemBlock)agp.free); + if (!del_alloc_set(agp.context, AGP_TYPE, agp.free)) + return DRM_ERR(EINVAL); + + DRM_DEBUG("free agp, free = 0x%lx\n", agp.free); + + return 0; +} + +int sis_init_context(int context) +{ + int i; + + for (i = 0; i < MAX_CONTEXT ; i++) { + if (global_ppriv[i].used && + (global_ppriv[i].context == context)) + break; + } + + if (i >= MAX_CONTEXT) { + for (i = 0; i < MAX_CONTEXT ; i++) { + if (!global_ppriv[i].used) { + global_ppriv[i].context = context; + global_ppriv[i].used = 1; + global_ppriv[i].sets[0] = setInit(); + global_ppriv[i].sets[1] = setInit(); + DRM_DEBUG("init allocation set, socket=%d, " + "context = %d\n", i, context); + break; + } + } + if ((i >= MAX_CONTEXT) || (global_ppriv[i].sets[0] == NULL) || + (global_ppriv[i].sets[1] == NULL)) + { + return 0; + } + } + + return 1; +} + +int sis_final_context(int context) +{ + int i; + + for (i=0; i