diff -ruN kernel131/sis.h kernel/sis.h --- kernel131/sis.h Thu Sep 25 23:51:45 2003 +++ kernel/sis.h Thu Sep 25 23:51:56 2003 @@ -33,7 +33,11 @@ * 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: */ @@ -42,20 +46,21 @@ #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 "20010503" -#define DRIVER_MAJOR 1 -#define DRIVER_MINOR 0 -#define DRIVER_PATCHLEVEL 0 +#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_agp_init, 1, 0 }, \ - [DRM_IOCTL_NR(DRM_IOCTL_SIS_AGP_ALLOC)] = { sis_agp_alloc, 1, 0 }, \ - [DRM_IOCTL_NR(DRM_IOCTL_SIS_AGP_FREE)] = { sis_agp_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 diff -ruN kernel131/sis_drm.h kernel/sis_drm.h --- kernel131/sis_drm.h Thu Sep 25 23:51:45 2003 +++ kernel/sis_drm.h Thu Sep 25 23:51:56 2003 @@ -8,6 +8,7 @@ #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) @@ -18,7 +19,7 @@ int context; unsigned int offset; unsigned int size; - unsigned int free; + unsigned long free; } drm_sis_mem_t; typedef struct { @@ -26,7 +27,7 @@ } drm_sis_agp_t; typedef struct { - unsigned int left, right; -} drm_sis_flip_t; + unsigned int offset, size; +} drm_sis_fb_t; #endif /* __SIS_DRM_H__ */ diff -ruN kernel131/sis_drv.h kernel/sis_drv.h --- kernel131/sis_drv.h Thu Sep 25 23:51:45 2003 +++ kernel/sis_drv.h Thu Sep 25 23:51:56 2003 @@ -28,14 +28,20 @@ #ifndef _SIS_DRV_H_ #define _SIS_DRV_H_ +#include "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_agp_init( DRM_IOCTL_ARGS ); -extern int sis_agp_alloc( DRM_IOCTL_ARGS ); -extern int sis_agp_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 -ruN kernel131/sis_ds.c kernel/sis_ds.c --- kernel131/sis_ds.c Thu Sep 25 23:51:45 2003 +++ kernel/sis_ds.c Thu Sep 25 23:51:56 2003 @@ -177,6 +177,24 @@ 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, diff -ruN kernel131/sis_ds.h kernel/sis_ds.h --- kernel131/sis_ds.h Thu Sep 25 23:51:45 2003 +++ kernel/sis_ds.h Thu Sep 25 23:51:56 2003 @@ -132,6 +132,11 @@ 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 diff -ruN kernel131/sis_mm.c kernel/sis_mm.c --- kernel131/sis_mm.c Thu Sep 25 23:51:45 2003 +++ kernel/sis_mm.c Thu Sep 25 23:51:56 2003 @@ -49,6 +49,7 @@ static sis_context_t global_ppriv[MAX_CONTEXT]; + static int add_alloc_set(int context, int type, unsigned int val) { int i, retval = 0; @@ -79,6 +80,12 @@ /* 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; @@ -121,9 +128,9 @@ if (!fb.free) return DRM_ERR(EINVAL); - sis_free(fb.free); 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); @@ -132,48 +139,145 @@ #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 ) { - return DRM_ERR(EINVAL); + 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 = %d\n", fb.free); + return 0; } #endif /* agp memory management */ -#if 1 - -static memHeap_t *AgpHeap = NULL; -int sis_agp_init( DRM_IOCTL_ARGS ) +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)); - AgpHeap = mmInit(agp.offset, agp.size); + dev_priv->AGPHeap = mmInit(agp.offset, agp.size); DRM_DEBUG("offset = %u, size = %u", agp.offset, agp.size); return 0; } -int sis_agp_alloc( DRM_IOCTL_ARGS ) +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 (AgpHeap == NULL) + 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(AgpHeap, agp.size, 0, 0); + block = mmAllocMem(dev_priv->AGPHeap, agp.size, 0, 0); if (block) { /* TODO */ agp.offset = block->ofs; @@ -196,30 +300,28 @@ return retval; } -int sis_agp_free( DRM_IOCTL_ARGS ) +int sis_ioctl_agp_free( DRM_IOCTL_ARGS ) { + DRM_DEVICE; + drm_sis_private_t *dev_priv = dev->dev_private; drm_sis_mem_t agp; - int retval = 0; - if (AgpHeap == NULL) + 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 (!agp.free) { - return -1; - } + + 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)) - retval = -1; + return DRM_ERR(EINVAL); DRM_DEBUG("free agp, free = %d\n", agp.free); - return retval; + return 0; } - -#endif int sis_init_context(int context) {