summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoranholt <anholt@FreeBSD.org>2003-09-09 00:24:31 +0000
committeranholt <anholt@FreeBSD.org>2003-09-09 00:24:31 +0000
commit6b432655804f704cb7d1fa3e6317548be1cfc164 (patch)
treedcab6440d210d4a1026afdd0cbbd73f19c8c6dd3
parent9eac29c0b915eec97e0a9539816cae19448bd20d (diff)
downloadFreeBSD-src-6b432655804f704cb7d1fa3e6317548be1cfc164.zip
FreeBSD-src-6b432655804f704cb7d1fa3e6317548be1cfc164.tar.gz
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
-rw-r--r--sys/dev/drm/drmP.h1
-rw-r--r--sys/dev/drm/drm_context.h8
-rw-r--r--sys/dev/drm/drm_memory.h5
-rw-r--r--sys/dev/drm/radeon.h8
-rw-r--r--sys/dev/drm/radeon_cp.c65
-rw-r--r--sys/dev/drm/radeon_drm.h20
-rw-r--r--sys/dev/drm/radeon_drv.c8
-rw-r--r--sys/dev/drm/radeon_drv.h12
-rw-r--r--sys/dev/drm/radeon_mem.c8
-rw-r--r--sys/dev/drm/radeon_state.c18
-rw-r--r--sys/dev/drm/sis.h79
-rw-r--r--sys/dev/drm/sis_drm.h36
-rw-r--r--sys/dev/drm/sis_drv.c60
-rw-r--r--sys/dev/drm/sis_drv.h48
-rw-r--r--sys/dev/drm/sis_ds.c387
-rw-r--r--sys/dev/drm/sis_ds.h165
-rw-r--r--sys/dev/drm/sis_mm.c404
17 files changed, 1261 insertions, 71 deletions
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 <sclin@sis.com.tw>
+ *
+ * $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 <sclin@sis.com.tw>
+ *
+ * $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 <sclin@sis.com.tw>
+ *
+ * $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 <linux/sisfb.h>
+#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<MAX_CONTEXT; i++) {
+ if (global_ppriv[i].used &&
+ (global_ppriv[i].context == context))
+ break;
+ }
+
+ if (i < MAX_CONTEXT) {
+ set_t *set;
+ unsigned int item;
+ int retval;
+
+ DRM_DEBUG("find socket %d, context = %d\n", i, context);
+
+ /* Video Memory */
+ set = global_ppriv[i].sets[0];
+ retval = setFirst(set, &item);
+ while (retval) {
+ DRM_DEBUG("free video memory 0x%x\n", item);
+#if defined(__linux__) && defined(CONFIG_FB_SIS)
+ sis_free(item);
+#else
+ mmFreeMem((PMemBlock)item);
+#endif
+ retval = setNext(set, &item);
+ }
+ setDestroy(set);
+
+ /* AGP Memory */
+ set = global_ppriv[i].sets[1];
+ retval = setFirst(set, &item);
+ while (retval) {
+ DRM_DEBUG("free agp memory 0x%x\n", item);
+ mmFreeMem((PMemBlock)item);
+ retval = setNext(set, &item);
+ }
+ setDestroy(set);
+
+ global_ppriv[i].used = 0;
+ }
+
+ return 1;
+}
OpenPOWER on IntegriCloud