diff options
-rw-r--r-- | shared-core/via_drm.h | 185 | ||||
-rw-r--r-- | shared-core/via_drv.c | 67 | ||||
-rw-r--r-- | shared-core/via_drv.h | 55 | ||||
-rw-r--r-- | shared-core/via_ds.c | 400 | ||||
-rw-r--r-- | shared-core/via_ds.h | 108 | ||||
-rw-r--r-- | shared-core/via_irq.c | 162 | ||||
-rw-r--r-- | shared-core/via_map.c | 143 | ||||
-rw-r--r-- | shared-core/via_mm.c | 347 | ||||
-rw-r--r-- | shared-core/via_mm.h | 45 | ||||
-rw-r--r-- | shared/via.h | 64 | ||||
-rw-r--r-- | shared/via_drm.h | 185 | ||||
-rw-r--r-- | shared/via_drv.c | 67 | ||||
-rw-r--r-- | shared/via_drv.h | 55 | ||||
-rw-r--r-- | shared/via_ds.c | 400 | ||||
-rw-r--r-- | shared/via_ds.h | 108 | ||||
-rw-r--r-- | shared/via_irq.c | 162 | ||||
-rw-r--r-- | shared/via_map.c | 143 | ||||
-rw-r--r-- | shared/via_mm.c | 347 | ||||
-rw-r--r-- | shared/via_mm.h | 45 |
19 files changed, 3088 insertions, 0 deletions
diff --git a/shared-core/via_drm.h b/shared-core/via_drm.h new file mode 100644 index 00000000..da80aa92 --- /dev/null +++ b/shared-core/via_drm.h @@ -0,0 +1,185 @@ +/* + * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved. + * Copyright 2001-2003 S3 Graphics, Inc. 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, sub license, + * 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 NON-INFRINGEMENT. IN NO EVENT SHALL + * VIA, S3 GRAPHICS, 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. + */ +#ifndef _VIA_DRM_H_ +#define _VIA_DRM_H_ + +/* WARNING: These defines must be the same as what the Xserver uses. + * if you change them, you must change the defines in the Xserver. + */ + +#ifndef _VIA_DEFINES_ +#define _VIA_DEFINES_ + +#define VIA_DMA_BUF_ORDER 12 +#define VIA_DMA_BUF_SZ (1 << VIA_DMA_BUF_ORDER) +#define VIA_DMA_BUF_NR 256 +#define VIA_NR_SAREA_CLIPRECTS 8 +#define VIA_NR_XVMC_LOCKS 2 +#define VIA_MAX_CACHELINE_SIZE 64 +#define XVMCLOCKPTR(saPriv,lockNo) \ + ((volatile int *)(((((unsigned long) (saPriv)->XvMCLockArea) + \ + (VIA_MAX_CACHELINE_SIZE - 1)) & \ + ~(VIA_MAX_CACHELINE_SIZE - 1)) + \ + VIA_MAX_CACHELINE_SIZE*(lockNo))) + +/* Each region is a minimum of 64k, and there are at most 64 of them. + */ +#define VIA_NR_TEX_REGIONS 64 +#define VIA_LOG_MIN_TEX_REGION_SIZE 16 +#endif + +#define VIA_UPLOAD_TEX0IMAGE 0x1 /* handled clientside */ +#define VIA_UPLOAD_TEX1IMAGE 0x2 /* handled clientside */ +#define VIA_UPLOAD_CTX 0x4 +#define VIA_UPLOAD_BUFFERS 0x8 +#define VIA_UPLOAD_TEX0 0x10 +#define VIA_UPLOAD_TEX1 0x20 +#define VIA_UPLOAD_CLIPRECTS 0x40 +#define VIA_UPLOAD_ALL 0xff + +/* VIA specific ioctls */ +#define DRM_IOCTL_VIA_ALLOCMEM DRM_IOWR(0x40, drm_via_mem_t) +#define DRM_IOCTL_VIA_FREEMEM DRM_IOW(0x41, drm_via_mem_t) +#define DRM_IOCTL_VIA_AGP_INIT DRM_IOWR(0x42, drm_via_agp_t) +#define DRM_IOCTL_VIA_FB_INIT DRM_IOWR(0x43, drm_via_fb_t) +#define DRM_IOCTL_VIA_MAP_INIT DRM_IOWR(0x44, drm_via_init_t) +#define DRM_IOCTL_VIA_DEC_FUTEX DRM_IOW(0x45, drm_via_futex_t) + +/* Indices into buf.Setup where various bits of state are mirrored per + * context and per buffer. These can be fired at the card as a unit, + * or in a piecewise fashion as required. + */ + +#define VIA_TEX_SETUP_SIZE 8 + +/* Flags for clear ioctl + */ +#define VIA_FRONT 0x1 +#define VIA_BACK 0x2 +#define VIA_DEPTH 0x4 +#define VIA_STENCIL 0x8 +#define VIDEO 0 +#define AGP 1 +typedef struct { + unsigned int offset; + unsigned int size; +} drm_via_agp_t; + +typedef struct { + unsigned int offset; + unsigned int size; +} drm_via_fb_t; + +typedef struct { + unsigned int context; + unsigned int type; + unsigned int size; + unsigned long index; + unsigned long offset; +} drm_via_mem_t; + +typedef struct _drm_via_init { + enum { + VIA_INIT_MAP = 0x01, + VIA_CLEANUP_MAP = 0x02 + } func; + + unsigned long sarea_priv_offset; + unsigned long fb_offset; + unsigned long mmio_offset; + unsigned long agpAddr; +} drm_via_init_t; + +typedef struct _drm_via_futex { + enum { + VIA_FUTEX_WAIT = 0x00, + VIA_FUTEX_WAKE = 0X01 + }fut; + unsigned int op; + unsigned int ms; + unsigned int lock; + unsigned int val; +} drm_via_futex_t; + +/* Warning: If you change the SAREA structure you must change the Xserver + * structure as well */ + +typedef struct _drm_via_tex_region { + unsigned char next, prev; /* indices to form a circular LRU */ + unsigned char inUse; /* owned by a client, or free? */ + int age; /* tracked by clients to update local LRU's */ +} drm_via_tex_region_t; + +typedef struct _drm_via_sarea { + unsigned int dirty; + unsigned int nbox; + drm_clip_rect_t boxes[VIA_NR_SAREA_CLIPRECTS]; + drm_via_tex_region_t texList[VIA_NR_TEX_REGIONS + 1]; + int texAge; /* last time texture was uploaded */ + int ctxOwner; /* last context to upload state */ + int vertexPrim; + + /* + * Below is for XvMC. + */ + + unsigned int XvMCSubPicOn; /* Subpicture displaying flag */ + unsigned int XvMCDisplaying; /* Surface displaying flag */ + unsigned int XvMCCtxNoGrabbed; /* Last context to hold decoder */ + + /* + * We want the lock integers alone on, and aligned to, a cache line. + * Therefore this somewhat strange construct. + */ + + char XvMCLockArea[VIA_MAX_CACHELINE_SIZE * (VIA_NR_XVMC_LOCKS + 1)]; + +} drm_via_sarea_t; + + +typedef struct _drm_via_flush_agp { + unsigned int offset; + unsigned int size; + unsigned int index; + int discard; /* client is finished with the buffer? */ +} drm_via_flush_agp_t; + +typedef struct _drm_via_flush_sys { + unsigned int offset; + unsigned int size; + unsigned long index; + int discard; /* client is finished with the buffer? */ +} drm_via_flush_sys_t; + +#ifdef __KERNEL__ + +int via_fb_init( DRM_IOCTL_ARGS ); +int via_mem_alloc( DRM_IOCTL_ARGS ); +int via_mem_free( DRM_IOCTL_ARGS ); +int via_agp_init( DRM_IOCTL_ARGS ); +int via_map_init( DRM_IOCTL_ARGS ); +int via_decoder_futex( DRM_IOCTL_ARGS ); + +#endif +#endif /* _VIA_DRM_H_ */ diff --git a/shared-core/via_drv.c b/shared-core/via_drv.c new file mode 100644 index 00000000..65ea55a1 --- /dev/null +++ b/shared-core/via_drv.c @@ -0,0 +1,67 @@ +/* + * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved. + * Copyright 2001-2003 S3 Graphics, Inc. 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, sub license, + * 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 NON-INFRINGEMENT. IN NO EVENT SHALL + * VIA, S3 GRAPHICS, 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. + */ +#include <linux/config.h> +#include "via.h" +#include "drmP.h" +#include "via_drm.h" +#include "via_drv.h" + +#define DRIVER_AUTHOR "VIA" + +#define DRIVER_NAME "via" +#define DRIVER_DESC "VIA Unichrome" +#define DRIVER_DATE "20040317" + +#define DRIVER_MAJOR 1 +#define DRIVER_MINOR 2 +#define DRIVER_PATCHLEVEL 0 + + +#define DRIVER_IOCTLS \ + [DRM_IOCTL_NR(DRM_IOCTL_VIA_ALLOCMEM)] = { via_mem_alloc, 1, 0 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_VIA_FREEMEM)] = { via_mem_free, 1, 0 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_VIA_AGP_INIT)] = { via_agp_init, 1, 0 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_VIA_FB_INIT)] = { via_fb_init, 1, 0 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_VIA_MAP_INIT)] = { via_map_init, 1, 0 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_VIA_DEC_FUTEX)] = { via_decoder_futex, 1, 0} + + +#define __HAVE_COUNTERS 0 + +#include "drm_auth.h" +#include "drm_agpsupport.h" +#include "drm_bufs.h" +#include "drm_context.h" +#include "drm_dma.h" +#include "drm_irq.h" +#include "drm_drawable.h" +#include "drm_drv.h" +#include "drm_fops.h" +#include "drm_init.h" +#include "drm_ioctl.h" +#include "drm_lock.h" +#include "drm_memory.h" +#include "drm_proc.h" +#include "drm_vm.h" +#include "drm_stub.h" diff --git a/shared-core/via_drv.h b/shared-core/via_drv.h new file mode 100644 index 00000000..1eafc95f --- /dev/null +++ b/shared-core/via_drv.h @@ -0,0 +1,55 @@ +/* + * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved. + * Copyright 2001-2003 S3 Graphics, Inc. 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, sub license, + * 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 NON-INFRINGEMENT. IN NO EVENT SHALL + * VIA, S3 GRAPHICS, 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. + */ +#ifndef _VIA_DRV_H_ +#define _VIA_DRV_H_ + +#include "via_drm.h" + + +typedef struct drm_via_private { + drm_via_sarea_t *sarea_priv; + drm_map_t *sarea; + drm_map_t *fb; + drm_map_t *mmio; + unsigned long agpAddr; + drm_map_t *buffers; + wait_queue_head_t decoder_queue[VIA_NR_XVMC_LOCKS]; +} drm_via_private_t; + + +/* VIA MMIO register access */ +#define VIA_BASE ((dev_priv->mmio)) + +#define VIA_READ(reg) DRM_READ32(VIA_BASE, reg) +#define VIA_WRITE(reg,val) DRM_WRITE32(VIA_BASE, reg, val) +#define VIA_READ8(reg) DRM_READ8(VIA_BASE, reg) +#define VIA_WRITE8(reg,val) DRM_WRITE8(VIA_BASE, reg, val) + + +extern int via_do_init_map(drm_device_t *dev, drm_via_init_t *init); +extern int via_do_cleanup_map(drm_device_t *dev); +extern int via_map_init(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg); + +#endif diff --git a/shared-core/via_ds.c b/shared-core/via_ds.c new file mode 100644 index 00000000..7fbd27aa --- /dev/null +++ b/shared-core/via_ds.c @@ -0,0 +1,400 @@ +/* + * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved. + * Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved. + * Copyright 2000 Silicon Integrated Systems Corp, Inc., HsinChu, Taiwan. + * + * 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, sub license, + * 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 NON-INFRINGEMENT. IN NO EVENT SHALL + * VIA, S3 GRAPHICS, 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. + */ +#define __NO_VERSION__ +#include <linux/module.h> +#include <linux/delay.h> +#include <linux/errno.h> +#include <linux/kernel.h> +#include <linux/slab.h> +#include <linux/poll.h> +#include <asm/io.h> +#include <linux/pci.h> + +#include "via_ds.h" +extern unsigned int VIA_DEBUG; + +set_t *via_setInit(void) +{ + int i; + set_t *set; + set = (set_t *)DRM_MALLOC(sizeof(set_t)); + 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 via_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 via_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 via_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 via_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 via_setDestroy(set_t *set) +{ + DRM_FREE(set, sizeof(set_t)); + + return 1; +} + +#define ISFREE(bptr) ((bptr)->free) + +#define PRINTF(fmt, arg...) do{}while(0) +#define fprintf(fmt, arg...) do{}while(0) + +static void *calloc(size_t nmemb, size_t size) +{ + void *addr; + addr = kmalloc(nmemb*size, GFP_KERNEL); + memset(addr, 0, nmemb*size); + return addr; +} +#define free(n) kfree(n) + +void via_mmDumpMemInfo( memHeap_t *heap ) +{ + TMemBlock *p; + + PRINTF ("Memory heap %p:\n", heap); + + if (heap == 0) + PRINTF (" heap == 0\n"); + else { + p = (TMemBlock *)heap; + + while (p) { + PRINTF (" Offset:%08x, Size:%08x, %c%c\n",p->ofs,p->size, + p->free ? '.':'U', + p->reserved ? 'R':'.'); + p = p->next; + } + } + + PRINTF ("End of memory blocks\n"); +} + +memHeap_t *via_mmInit(int ofs, + int size) +{ + PMemBlock blocks; + + if (size <= 0) + return 0; + + + blocks = (TMemBlock *)calloc(1,sizeof(TMemBlock)); + + if (blocks) { + blocks->ofs = ofs; + blocks->size = size; + blocks->free = 1; + return (memHeap_t *)blocks; + } else + return 0; +} + +memHeap_t *via_mmAddRange(memHeap_t *heap, + int ofs, + int size) +{ + PMemBlock blocks; + blocks = (TMemBlock *) calloc(2,sizeof(TMemBlock)); + + if (blocks) { + 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*)calloc(1,sizeof(TMemBlock)); + 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*) calloc(1,sizeof(TMemBlock)); + 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 via_mmAllocMem(memHeap_t *heap, int size, int align2, int startSearch) +{ + int mask,startofs,endofs; + TMemBlock *p; + + if (!heap || align2 < 0 || size <= 0) + return NULL; + + mask = (1 << align2)-1; + startofs = 0; + p = (TMemBlock *)heap; + + while (p) { + 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) + 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; + free(q); + + return 1; + } + + return 0; +} + +int via_mmFreeMem(PMemBlock b) +{ + TMemBlock *p,*prev; + + if (!b) + return 0; + + if (!b->heap) { + fprintf(stderr, "no heap\n"); + + return -1; + } + + p = b->heap; + prev = NULL; + + while (p && p != b) { + prev = p; + p = p->next; + } + + if (!p || p->free || p->reserved) { + if (!p) + fprintf(stderr, "block not found in heap\n"); + else if (p->free) + fprintf(stderr, "block already free\n"); + else + fprintf(stderr, "block is reserved\n"); + + + return -1; + } + + p->free = 1; + Join2Blocks(p); + + if (prev) + Join2Blocks(prev); + + return 0; +} + +int via_mmReserveMem(memHeap_t *heap, int offset,int size) +{ + int endofs; + TMemBlock *p; + + if (!heap || 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 via_mmFreeReserved(memHeap_t *heap, int offset) +{ + TMemBlock *p,*prev; + + if (!heap) + return -1; + + p = (TMemBlock *)heap; + prev = NULL; + + while (p && p->ofs != offset) { + prev = p; + p = p->next; + } + + if (!p || !p->reserved) + return -1; + p->free = 1; + p->reserved = 0; + Join2Blocks(p); + + if (prev) + Join2Blocks(prev); + + return 0; +} + +void via_mmDestroy(memHeap_t *heap) +{ + TMemBlock *p,*q; + + if (!heap) + return; + p = (TMemBlock *)heap; + + while (p) { + q = p->next; + free(p); + p = q; + } +} diff --git a/shared-core/via_ds.h b/shared-core/via_ds.h new file mode 100644 index 00000000..50ab3e7f --- /dev/null +++ b/shared-core/via_ds.h @@ -0,0 +1,108 @@ +/* + * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved. + * Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved. + * 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, sub license, + * 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 NON-INFRINGEMENT. IN NO EVENT SHALL + * VIA, S3 GRAPHICS, 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. + */ +#ifndef _via_ds_h_ +#define _via_ds_h_ + +#include "via.h" +#include "drmP.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 *via_setInit(void); +int via_setAdd(set_t *set, ITEM_TYPE item); +int via_setDel(set_t *set, ITEM_TYPE item); +int via_setFirst(set_t *set, ITEM_TYPE *item); +int via_setNext(set_t *set, ITEM_TYPE *item); +int via_setDestroy(set_t *set); + +#endif + + +#ifndef MM_INC +#define MM_INC + +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 *via_mmInit(int ofs, int size); + + +PMemBlock via_mmAllocMem(memHeap_t *heap, int size, int align2, int startSearch); + +/* + * Free block starts at offset + * input: pointer to a block + * return: 0 if OK, -1 if error + */ +int via_mmFreeMem(PMemBlock b); + +/* + * destroy MM + */ +void via_mmDestroy(memHeap_t *mmInit); + +/* For debugging purpose. */ +void via_mmDumpMemInfo(memHeap_t *mmInit); + +#endif diff --git a/shared-core/via_irq.c b/shared-core/via_irq.c new file mode 100644 index 00000000..835b41cd --- /dev/null +++ b/shared-core/via_irq.c @@ -0,0 +1,162 @@ +/* via_irq.c + * + * Copyright 2004 BEAM Ltd. + * Copyright 2002 Tungsten Graphics, Inc. + * 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 + * BEAM LTD, TUNGSTEN GRAPHICS 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: + * Terry Barnaby <terry1@beam.ltd.uk> + * Keith Whitwell <keith@tungstengraphics.com> + * + * + * This code provides standard DRM access to the Via CLE266's Vertical blank + * interrupt. + */ + +#include "via.h" +#include "drmP.h" +#include "drm.h" +#include "via_drm.h" +#include "via_drv.h" + +#define VIA_REG_INTERRUPT 0x200 + +/* VIA_REG_INTERRUPT */ +#define VIA_IRQ_GLOBAL (1 << 31) +#define VIA_IRQ_VBI_ENABLE (1 << 19) +#define VIA_IRQ_VBI_PENDING (1 << 3) + +irqreturn_t DRM(irq_handler)( DRM_IRQ_ARGS ) + +{ + drm_device_t* dev = (drm_device_t*)arg; + drm_via_private_t* dev_priv = (drm_via_private_t*)dev->dev_private; + u32 status; + int handled = 0; + + status = VIA_READ(VIA_REG_INTERRUPT); + DRM_DEBUG("viadrv_irq_handler Status: %x\n",status); + if(status & VIA_IRQ_VBI_PENDING){ + atomic_inc(&dev->vbl_received); + DRM_WAKEUP(&dev->vbl_queue); + DRM(vbl_send_signals)(dev); + handled = 1; + } + + /* Acknowlege interrupts ?? */ + VIA_WRITE(VIA_REG_INTERRUPT, status); + return IRQ_RETVAL(handled); +} + +static __inline__ void viadrv_acknowledge_irqs(drm_via_private_t* dev_priv) +{ + u32 status; + + if(dev_priv){ + /* Acknowlege interrupts ?? */ + status = VIA_READ(VIA_REG_INTERRUPT); + VIA_WRITE(VIA_REG_INTERRUPT, status | VIA_IRQ_VBI_PENDING); + } +} + +int DRM(vblank_wait)(drm_device_t* dev, unsigned int* sequence) +{ + drm_via_private_t* dev_priv = (drm_via_private_t*)dev->dev_private; + unsigned int cur_vblank; + int ret = 0; + + DRM_DEBUG("viadrv_vblank_wait\n"); + if(!dev_priv){ + DRM_ERROR("%s called with no initialization\n", __FUNCTION__ ); + return -EINVAL; + } + + viadrv_acknowledge_irqs(dev_priv); + + /* Assume that the user has missed the current sequence number + * by about a day rather than she wants to wait for years + * using vertical blanks... + */ + DRM_WAIT_ON(ret, dev->vbl_queue, 3*DRM_HZ, + (((cur_vblank = atomic_read(&dev->vbl_received)) - + *sequence ) <= (1<<23))); + + *sequence = cur_vblank; + return ret; +} + +/* + * drm_dma.h hooks + */ +void DRM(driver_irq_preinstall)(drm_device_t* dev){ + drm_via_private_t* dev_priv = (drm_via_private_t *)dev->dev_private; + u32 status; + + DRM_DEBUG("driver_irq_preinstall: dev_priv: %p\n", dev_priv); + if(dev_priv){ + DRM_DEBUG("mmio: %p\n", dev_priv->mmio); + status = VIA_READ(VIA_REG_INTERRUPT); + DRM_DEBUG("intreg: %x\n", status & VIA_IRQ_VBI_ENABLE); + + // Clear VSync interrupt regs + VIA_WRITE(VIA_REG_INTERRUPT, status & ~VIA_IRQ_VBI_ENABLE); + + /* Clear bits if they're already high */ + viadrv_acknowledge_irqs(dev_priv); + } +} + +void DRM(driver_irq_postinstall)(drm_device_t* dev){ + drm_via_private_t* dev_priv = (drm_via_private_t *)dev->dev_private; + u32 status; + + DRM_DEBUG("via_driver_irq_postinstall\n"); + if(dev_priv){ + status = VIA_READ(VIA_REG_INTERRUPT); + VIA_WRITE(VIA_REG_INTERRUPT, status | VIA_IRQ_GLOBAL + | VIA_IRQ_VBI_ENABLE); + /* Some magic, oh for some data sheets ! */ + + VIA_WRITE8(0x83d4, 0x11); + VIA_WRITE8(0x83d5, VIA_READ8(0x83d5) | 0x30); + + } +} + +void DRM(driver_irq_uninstall)(drm_device_t* dev){ + drm_via_private_t* dev_priv = (drm_via_private_t *)dev->dev_private; + u32 status; + + DRM_DEBUG("driver_irq_uninstall)\n"); + if(dev_priv){ + + /* Some more magic, oh for some data sheets ! */ + + VIA_WRITE8(0x83d4, 0x11); + VIA_WRITE8(0x83d5, VIA_READ8(0x83d5) & ~0x30); + + status = VIA_READ(VIA_REG_INTERRUPT); + VIA_WRITE(VIA_REG_INTERRUPT, status & ~VIA_IRQ_VBI_ENABLE); + } +} + diff --git a/shared-core/via_map.c b/shared-core/via_map.c new file mode 100644 index 00000000..53260927 --- /dev/null +++ b/shared-core/via_map.c @@ -0,0 +1,143 @@ +/* + * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved. + * Copyright 2001-2003 S3 Graphics, Inc. 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, sub license, + * 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 NON-INFRINGEMENT. IN NO EVENT SHALL + * VIA, S3 GRAPHICS, 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. + */ +#define __NO_VERSION__ +#include "via.h" +#include "drmP.h" +#include "via_drv.h" + +int via_do_init_map(drm_device_t *dev, drm_via_init_t *init) +{ + drm_via_private_t *dev_priv; + unsigned int i; + + DRM_DEBUG("%s\n", __FUNCTION__); + + dev_priv = DRM(alloc)(sizeof(drm_via_private_t), DRM_MEM_DRIVER); + if (dev_priv == NULL) + return -ENOMEM; + + memset(dev_priv, 0, sizeof(drm_via_private_t)); + + DRM_GETSAREA(); + if (!dev_priv->sarea) { + DRM_ERROR("could not find sarea!\n"); + dev->dev_private = (void *)dev_priv; + via_do_cleanup_map(dev); + return -EINVAL; + } + + DRM_FIND_MAP(dev_priv->fb, init->fb_offset); + if (!dev_priv->fb) { + DRM_ERROR("could not find framebuffer!\n"); + dev->dev_private = (void *)dev_priv; + via_do_cleanup_map(dev); + return -EINVAL; + } + DRM_FIND_MAP(dev_priv->mmio, init->mmio_offset); + if (!dev_priv->mmio) { + DRM_ERROR("could not find mmio region!\n"); + dev->dev_private = (void *)dev_priv; + via_do_cleanup_map(dev); + return -EINVAL; + } + + dev_priv->sarea_priv = + (drm_via_sarea_t *)((u8 *)dev_priv->sarea->handle + + init->sarea_priv_offset); + + dev_priv->agpAddr = init->agpAddr; + + + for (i=0; i<VIA_NR_XVMC_LOCKS; ++i) + DRM_INIT_WAITQUEUE( &(dev_priv->decoder_queue[i]) ); + + dev->dev_private = (void *)dev_priv; + + return 0; +} + +int via_do_cleanup_map(drm_device_t *dev) +{ + if (dev->dev_private) { + + drm_via_private_t *dev_priv = dev->dev_private; + + DRM(free)(dev_priv, sizeof(drm_via_private_t), + DRM_MEM_DRIVER); + dev->dev_private = NULL; + } + + return 0; +} + +int via_map_init( DRM_IOCTL_ARGS ) +{ + DRM_DEVICE; + drm_via_init_t init; + + DRM_DEBUG("%s\n", __FUNCTION__); + + DRM_COPY_FROM_USER_IOCTL(init, (drm_via_init_t *)data, sizeof(init)); + + switch (init.func) { + case VIA_INIT_MAP: + return via_do_init_map(dev, &init); + case VIA_CLEANUP_MAP: + return via_do_cleanup_map(dev); + } + + return -EINVAL; +} + +int via_decoder_futex( DRM_IOCTL_ARGS ) +{ + DRM_DEVICE; + drm_via_futex_t fx; + volatile int *lock; + drm_via_private_t *dev_priv = (drm_via_private_t*) dev->dev_private; + drm_via_sarea_t *sAPriv = dev_priv->sarea_priv; + int ret = 0; + + DRM_COPY_FROM_USER_IOCTL(fx, (drm_via_futex_t *) data, sizeof(fx)); + + if (fx.lock > VIA_NR_XVMC_LOCKS) + return -EFAULT; + + lock = XVMCLOCKPTR(sAPriv,fx.lock); + + switch(fx.op) { + case VIA_FUTEX_WAIT: + DRM_WAIT_ON(ret, dev_priv->decoder_queue[fx.lock], + (fx.ms / 10)*(DRM_HZ/100), + *lock != fx.val); + return ret; + case VIA_FUTEX_WAKE: + DRM_WAKEUP( &(dev_priv->decoder_queue[fx.lock]) ); + return 0; + } + return 0; +} + + + diff --git a/shared-core/via_mm.c b/shared-core/via_mm.c new file mode 100644 index 00000000..1bf04fe0 --- /dev/null +++ b/shared-core/via_mm.c @@ -0,0 +1,347 @@ +/* + * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved. + * Copyright 2001-2003 S3 Graphics, Inc. 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, sub license, + * 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 NON-INFRINGEMENT. IN NO EVENT SHALL + * VIA, S3 GRAPHICS, 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. + */ +#define __NO_VERSION__ +#include "via.h" +#include "drmP.h" +#include "via_drm.h" +#include "via_drv.h" +#include "via_ds.h" +#include "via_mm.h" + +#define MAX_CONTEXT 100 + +unsigned int VIA_DEBUG = 1; + +typedef struct { + int used; + int context; + set_t *sets[2]; /* 0 for frame buffer, 1 for AGP , 2 for System*/ +} via_context_t; + +static via_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 = via_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 = via_setDel(global_ppriv[i].sets[type], val); + break; + } + + return retval; +} + +/* agp memory management */ +static memHeap_t *AgpHeap = NULL; + +int via_agp_init( DRM_IOCTL_ARGS ) +{ + drm_via_agp_t agp; + + DRM_COPY_FROM_USER_IOCTL(agp, (drm_via_agp_t *)data, sizeof(agp)); + + AgpHeap = via_mmInit(agp.offset, agp.size); + + DRM_DEBUG("offset = %u, size = %u", agp.offset, agp.size); + + return 0; +} + +/* fb memory management */ +static memHeap_t *FBHeap = NULL; + +int via_fb_init( DRM_IOCTL_ARGS ) +{ + drm_via_fb_t fb; + + + DRM_COPY_FROM_USER_IOCTL(fb, (drm_via_fb_t *)data, sizeof(fb)); + + FBHeap = via_mmInit(fb.offset, fb.size); + + DRM_DEBUG("offset = %u, size = %u", fb.offset, fb.size); + + return 0; +} + +int via_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] = via_setInit(); + global_ppriv[i].sets[1] = via_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 via_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 = via_setFirst(set, &item); + while (retval) { + DRM_DEBUG("free video memory 0x%x\n", item); + via_mmFreeMem((PMemBlock)item); + retval = via_setNext(set, &item); + } + via_setDestroy(set); + + /* AGP Memory */ + set = global_ppriv[i].sets[1]; + retval = via_setFirst(set, &item); + while (retval) { + DRM_DEBUG("free agp memory 0x%x\n", item); + via_mmFreeMem((PMemBlock)item); + retval = via_setNext(set, &item); + } + via_setDestroy(set); + + global_ppriv[i].used = 0; + } + + return 1; +} +int via_mem_alloc( DRM_IOCTL_ARGS) +{ + drm_via_mem_t mem; + + DRM_COPY_FROM_USER_IOCTL(mem, (drm_via_mem_t *)data, sizeof(mem)); + switch (mem.type) { + case VIDEO : + if (via_fb_alloc(&mem) < 0) + return -EFAULT; + DRM_COPY_TO_USER_IOCTL((drm_via_mem_t *)data, mem, + sizeof(mem)); + return 0; + case AGP : + if (via_agp_alloc(&mem) < 0) + return -EFAULT; + DRM_COPY_TO_USER_IOCTL((drm_via_mem_t *)data, mem, + sizeof(mem)); + return 0; + } + + return -EFAULT; +} + +int via_fb_alloc(drm_via_mem_t* mem) +{ + drm_via_mm_t fb; + PMemBlock block; + int retval = 0; + + if (!FBHeap) + return -1; + + fb.size = mem->size; + fb.context = mem->context; + + block = via_mmAllocMem(FBHeap, fb.size, 5, 0); + if (block) { + fb.offset = block->ofs; + fb.free = (unsigned int)block; + if (!add_alloc_set(fb.context, VIDEO, fb.free)) { + DRM_DEBUG("adding to allocation set fails\n"); + via_mmFreeMem((PMemBlock)fb.free); + retval = -1; + } + } + else { + fb.offset = 0; + fb.size = 0; + fb.free = 0; + retval = -1; + } + + mem->offset = fb.offset; + mem->index = fb.free; + + DRM_DEBUG("alloc fb, size = %d, offset = %d\n", fb.size, + (int)fb.offset); + + return retval; +} +int via_agp_alloc(drm_via_mem_t* mem) +{ + drm_via_mm_t agp; + PMemBlock block; + int retval = 0; + + if (!AgpHeap) + return -1; + + agp.size = mem->size; + agp.context = mem->context; + + block = via_mmAllocMem(AgpHeap, agp.size, 5, 0); + if (block) { + agp.offset = block->ofs; + agp.free = (unsigned int)block; + if (!add_alloc_set(agp.context, AGP, agp.free)) { + DRM_DEBUG("adding to allocation set fails\n"); + via_mmFreeMem((PMemBlock)agp.free); + retval = -1; + } + } + else { + agp.offset = 0; + agp.size = 0; + agp.free = 0; + } + + mem->offset = agp.offset; + mem->index = agp.free; + + DRM_DEBUG("alloc agp, size = %d, offset = %d\n", agp.size, + (unsigned int)agp.offset); + return retval; +} + +int via_mem_free( DRM_IOCTL_ARGS ) +{ + drm_via_mem_t mem; + + DRM_COPY_FROM_USER_IOCTL(mem, (drm_via_mem_t *)data, sizeof(mem)); + + switch (mem.type) { + + case VIDEO : + if (via_fb_free(&mem) == 0) + return 0; + break; + case AGP : + if (via_agp_free(&mem) == 0) + return 0; + break; + } + + return -EFAULT; +} +int via_fb_free(drm_via_mem_t* mem) +{ + drm_via_mm_t fb; + int retval = 0; + + + if (!FBHeap) { + return -1; + } + + fb.free = mem->index; + fb.context = mem->context; + + if (!fb.free) + { + return -1; + + } + + via_mmFreeMem((PMemBlock)fb.free); + + if (!del_alloc_set(fb.context, VIDEO, fb.free)) + { + retval = -1; + } + + DRM_DEBUG("free fb, free = %d\n", fb.free); + + return retval; +} +int via_agp_free(drm_via_mem_t* mem) +{ + drm_via_mm_t agp; + + int retval = 0; + + agp.free = mem->index; + agp.context = mem->context; + + if (!agp.free) + return -1; + + via_mmFreeMem((PMemBlock)agp.free); + + if (!del_alloc_set(agp.context, AGP, agp.free)) { + retval = -1; + } + + DRM_DEBUG("free agp, free = %d\n", agp.free); + + return retval; +} + +EXPORT_SYMBOL(via_fb_alloc); +EXPORT_SYMBOL(via_fb_free); diff --git a/shared-core/via_mm.h b/shared-core/via_mm.h new file mode 100644 index 00000000..c476ac6a --- /dev/null +++ b/shared-core/via_mm.h @@ -0,0 +1,45 @@ +/* + * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved. + * Copyright 2001-2003 S3 Graphics, Inc. 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, sub license, + * 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 NON-INFRINGEMENT. IN NO EVENT SHALL + * VIA, S3 GRAPHICS, 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. + */ +#ifndef _via_drm_mm_h_ +#define _via_drm_mm_h_ + +typedef struct { + unsigned int context; + unsigned int size; + unsigned long offset; + unsigned int free; +} drm_via_mm_t; + +typedef struct { + unsigned int size; + unsigned long handle; + void *virtual; +} drm_via_dma_t; + +int via_fb_alloc(drm_via_mem_t *mem); +int via_fb_free(drm_via_mem_t *mem); +int via_agp_alloc(drm_via_mem_t *mem); +int via_agp_free(drm_via_mem_t *mem); + +#endif diff --git a/shared/via.h b/shared/via.h new file mode 100644 index 00000000..f7fabd7e --- /dev/null +++ b/shared/via.h @@ -0,0 +1,64 @@ +/* + * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved. + * Copyright 2001-2003 S3 Graphics, Inc. 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, sub license, + * 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 NON-INFRINGEMENT. IN NO EVENT SHALL + * VIA, S3 GRAPHICS, 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. + */ +#ifndef __VIA_H__ +#define __VIA_H__ + + +#define DRM(x) viadrv_##x + + +#define __HAVE_AGP 1 +#define __MUST_HAVE_AGP 0 +#define __HAVE_MTRR 1 +#define __HAVE_CTX_BITMAP 1 + +/* BEAM: Have enabled DMA,DMA_IRQ and VBL_IRQ needed to do this to get standard + * support for VBL_IRQ. + */ + +#define __HAVE_IRQ 1 +#define __HAVE_SHARED_IRQ 1 +#define __HAVE_VBL_IRQ 1 + + + +#define DRIVER_AGP_BUFFERS_MAP( dev ) \ + ((drm_via_private_t *)((dev)->dev_private))->buffers + +extern int via_init_context(int context); +extern int via_final_context(int context); + +#define DRIVER_CTX_CTOR via_init_context +#define DRIVER_CTX_DTOR via_final_context + +#define DRIVER_PCI_IDS \ + {0x1106, 0x3122, 0, "Via CLE3122"}, \ + {0x1106, 0x3022, 0, "Via CLE3022"}, \ + {0x1106, 0x3205, 0, "Via VT3205"}, \ + {0x1106, 0x7205, 0, "Via VT7205"}, \ + {0x1106, 0x3204, 0, "Via VT3204"}, \ + {0x1106, 0x7204, 0, "Via VT7204"}, \ + {0, 0, 0, NULL} + +#endif diff --git a/shared/via_drm.h b/shared/via_drm.h new file mode 100644 index 00000000..da80aa92 --- /dev/null +++ b/shared/via_drm.h @@ -0,0 +1,185 @@ +/* + * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved. + * Copyright 2001-2003 S3 Graphics, Inc. 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, sub license, + * 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 NON-INFRINGEMENT. IN NO EVENT SHALL + * VIA, S3 GRAPHICS, 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. + */ +#ifndef _VIA_DRM_H_ +#define _VIA_DRM_H_ + +/* WARNING: These defines must be the same as what the Xserver uses. + * if you change them, you must change the defines in the Xserver. + */ + +#ifndef _VIA_DEFINES_ +#define _VIA_DEFINES_ + +#define VIA_DMA_BUF_ORDER 12 +#define VIA_DMA_BUF_SZ (1 << VIA_DMA_BUF_ORDER) +#define VIA_DMA_BUF_NR 256 +#define VIA_NR_SAREA_CLIPRECTS 8 +#define VIA_NR_XVMC_LOCKS 2 +#define VIA_MAX_CACHELINE_SIZE 64 +#define XVMCLOCKPTR(saPriv,lockNo) \ + ((volatile int *)(((((unsigned long) (saPriv)->XvMCLockArea) + \ + (VIA_MAX_CACHELINE_SIZE - 1)) & \ + ~(VIA_MAX_CACHELINE_SIZE - 1)) + \ + VIA_MAX_CACHELINE_SIZE*(lockNo))) + +/* Each region is a minimum of 64k, and there are at most 64 of them. + */ +#define VIA_NR_TEX_REGIONS 64 +#define VIA_LOG_MIN_TEX_REGION_SIZE 16 +#endif + +#define VIA_UPLOAD_TEX0IMAGE 0x1 /* handled clientside */ +#define VIA_UPLOAD_TEX1IMAGE 0x2 /* handled clientside */ +#define VIA_UPLOAD_CTX 0x4 +#define VIA_UPLOAD_BUFFERS 0x8 +#define VIA_UPLOAD_TEX0 0x10 +#define VIA_UPLOAD_TEX1 0x20 +#define VIA_UPLOAD_CLIPRECTS 0x40 +#define VIA_UPLOAD_ALL 0xff + +/* VIA specific ioctls */ +#define DRM_IOCTL_VIA_ALLOCMEM DRM_IOWR(0x40, drm_via_mem_t) +#define DRM_IOCTL_VIA_FREEMEM DRM_IOW(0x41, drm_via_mem_t) +#define DRM_IOCTL_VIA_AGP_INIT DRM_IOWR(0x42, drm_via_agp_t) +#define DRM_IOCTL_VIA_FB_INIT DRM_IOWR(0x43, drm_via_fb_t) +#define DRM_IOCTL_VIA_MAP_INIT DRM_IOWR(0x44, drm_via_init_t) +#define DRM_IOCTL_VIA_DEC_FUTEX DRM_IOW(0x45, drm_via_futex_t) + +/* Indices into buf.Setup where various bits of state are mirrored per + * context and per buffer. These can be fired at the card as a unit, + * or in a piecewise fashion as required. + */ + +#define VIA_TEX_SETUP_SIZE 8 + +/* Flags for clear ioctl + */ +#define VIA_FRONT 0x1 +#define VIA_BACK 0x2 +#define VIA_DEPTH 0x4 +#define VIA_STENCIL 0x8 +#define VIDEO 0 +#define AGP 1 +typedef struct { + unsigned int offset; + unsigned int size; +} drm_via_agp_t; + +typedef struct { + unsigned int offset; + unsigned int size; +} drm_via_fb_t; + +typedef struct { + unsigned int context; + unsigned int type; + unsigned int size; + unsigned long index; + unsigned long offset; +} drm_via_mem_t; + +typedef struct _drm_via_init { + enum { + VIA_INIT_MAP = 0x01, + VIA_CLEANUP_MAP = 0x02 + } func; + + unsigned long sarea_priv_offset; + unsigned long fb_offset; + unsigned long mmio_offset; + unsigned long agpAddr; +} drm_via_init_t; + +typedef struct _drm_via_futex { + enum { + VIA_FUTEX_WAIT = 0x00, + VIA_FUTEX_WAKE = 0X01 + }fut; + unsigned int op; + unsigned int ms; + unsigned int lock; + unsigned int val; +} drm_via_futex_t; + +/* Warning: If you change the SAREA structure you must change the Xserver + * structure as well */ + +typedef struct _drm_via_tex_region { + unsigned char next, prev; /* indices to form a circular LRU */ + unsigned char inUse; /* owned by a client, or free? */ + int age; /* tracked by clients to update local LRU's */ +} drm_via_tex_region_t; + +typedef struct _drm_via_sarea { + unsigned int dirty; + unsigned int nbox; + drm_clip_rect_t boxes[VIA_NR_SAREA_CLIPRECTS]; + drm_via_tex_region_t texList[VIA_NR_TEX_REGIONS + 1]; + int texAge; /* last time texture was uploaded */ + int ctxOwner; /* last context to upload state */ + int vertexPrim; + + /* + * Below is for XvMC. + */ + + unsigned int XvMCSubPicOn; /* Subpicture displaying flag */ + unsigned int XvMCDisplaying; /* Surface displaying flag */ + unsigned int XvMCCtxNoGrabbed; /* Last context to hold decoder */ + + /* + * We want the lock integers alone on, and aligned to, a cache line. + * Therefore this somewhat strange construct. + */ + + char XvMCLockArea[VIA_MAX_CACHELINE_SIZE * (VIA_NR_XVMC_LOCKS + 1)]; + +} drm_via_sarea_t; + + +typedef struct _drm_via_flush_agp { + unsigned int offset; + unsigned int size; + unsigned int index; + int discard; /* client is finished with the buffer? */ +} drm_via_flush_agp_t; + +typedef struct _drm_via_flush_sys { + unsigned int offset; + unsigned int size; + unsigned long index; + int discard; /* client is finished with the buffer? */ +} drm_via_flush_sys_t; + +#ifdef __KERNEL__ + +int via_fb_init( DRM_IOCTL_ARGS ); +int via_mem_alloc( DRM_IOCTL_ARGS ); +int via_mem_free( DRM_IOCTL_ARGS ); +int via_agp_init( DRM_IOCTL_ARGS ); +int via_map_init( DRM_IOCTL_ARGS ); +int via_decoder_futex( DRM_IOCTL_ARGS ); + +#endif +#endif /* _VIA_DRM_H_ */ diff --git a/shared/via_drv.c b/shared/via_drv.c new file mode 100644 index 00000000..65ea55a1 --- /dev/null +++ b/shared/via_drv.c @@ -0,0 +1,67 @@ +/* + * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved. + * Copyright 2001-2003 S3 Graphics, Inc. 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, sub license, + * 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 NON-INFRINGEMENT. IN NO EVENT SHALL + * VIA, S3 GRAPHICS, 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. + */ +#include <linux/config.h> +#include "via.h" +#include "drmP.h" +#include "via_drm.h" +#include "via_drv.h" + +#define DRIVER_AUTHOR "VIA" + +#define DRIVER_NAME "via" +#define DRIVER_DESC "VIA Unichrome" +#define DRIVER_DATE "20040317" + +#define DRIVER_MAJOR 1 +#define DRIVER_MINOR 2 +#define DRIVER_PATCHLEVEL 0 + + +#define DRIVER_IOCTLS \ + [DRM_IOCTL_NR(DRM_IOCTL_VIA_ALLOCMEM)] = { via_mem_alloc, 1, 0 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_VIA_FREEMEM)] = { via_mem_free, 1, 0 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_VIA_AGP_INIT)] = { via_agp_init, 1, 0 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_VIA_FB_INIT)] = { via_fb_init, 1, 0 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_VIA_MAP_INIT)] = { via_map_init, 1, 0 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_VIA_DEC_FUTEX)] = { via_decoder_futex, 1, 0} + + +#define __HAVE_COUNTERS 0 + +#include "drm_auth.h" +#include "drm_agpsupport.h" +#include "drm_bufs.h" +#include "drm_context.h" +#include "drm_dma.h" +#include "drm_irq.h" +#include "drm_drawable.h" +#include "drm_drv.h" +#include "drm_fops.h" +#include "drm_init.h" +#include "drm_ioctl.h" +#include "drm_lock.h" +#include "drm_memory.h" +#include "drm_proc.h" +#include "drm_vm.h" +#include "drm_stub.h" diff --git a/shared/via_drv.h b/shared/via_drv.h new file mode 100644 index 00000000..1eafc95f --- /dev/null +++ b/shared/via_drv.h @@ -0,0 +1,55 @@ +/* + * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved. + * Copyright 2001-2003 S3 Graphics, Inc. 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, sub license, + * 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 NON-INFRINGEMENT. IN NO EVENT SHALL + * VIA, S3 GRAPHICS, 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. + */ +#ifndef _VIA_DRV_H_ +#define _VIA_DRV_H_ + +#include "via_drm.h" + + +typedef struct drm_via_private { + drm_via_sarea_t *sarea_priv; + drm_map_t *sarea; + drm_map_t *fb; + drm_map_t *mmio; + unsigned long agpAddr; + drm_map_t *buffers; + wait_queue_head_t decoder_queue[VIA_NR_XVMC_LOCKS]; +} drm_via_private_t; + + +/* VIA MMIO register access */ +#define VIA_BASE ((dev_priv->mmio)) + +#define VIA_READ(reg) DRM_READ32(VIA_BASE, reg) +#define VIA_WRITE(reg,val) DRM_WRITE32(VIA_BASE, reg, val) +#define VIA_READ8(reg) DRM_READ8(VIA_BASE, reg) +#define VIA_WRITE8(reg,val) DRM_WRITE8(VIA_BASE, reg, val) + + +extern int via_do_init_map(drm_device_t *dev, drm_via_init_t *init); +extern int via_do_cleanup_map(drm_device_t *dev); +extern int via_map_init(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg); + +#endif diff --git a/shared/via_ds.c b/shared/via_ds.c new file mode 100644 index 00000000..7fbd27aa --- /dev/null +++ b/shared/via_ds.c @@ -0,0 +1,400 @@ +/* + * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved. + * Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved. + * Copyright 2000 Silicon Integrated Systems Corp, Inc., HsinChu, Taiwan. + * + * 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, sub license, + * 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 NON-INFRINGEMENT. IN NO EVENT SHALL + * VIA, S3 GRAPHICS, 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. + */ +#define __NO_VERSION__ +#include <linux/module.h> +#include <linux/delay.h> +#include <linux/errno.h> +#include <linux/kernel.h> +#include <linux/slab.h> +#include <linux/poll.h> +#include <asm/io.h> +#include <linux/pci.h> + +#include "via_ds.h" +extern unsigned int VIA_DEBUG; + +set_t *via_setInit(void) +{ + int i; + set_t *set; + set = (set_t *)DRM_MALLOC(sizeof(set_t)); + 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 via_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 via_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 via_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 via_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 via_setDestroy(set_t *set) +{ + DRM_FREE(set, sizeof(set_t)); + + return 1; +} + +#define ISFREE(bptr) ((bptr)->free) + +#define PRINTF(fmt, arg...) do{}while(0) +#define fprintf(fmt, arg...) do{}while(0) + +static void *calloc(size_t nmemb, size_t size) +{ + void *addr; + addr = kmalloc(nmemb*size, GFP_KERNEL); + memset(addr, 0, nmemb*size); + return addr; +} +#define free(n) kfree(n) + +void via_mmDumpMemInfo( memHeap_t *heap ) +{ + TMemBlock *p; + + PRINTF ("Memory heap %p:\n", heap); + + if (heap == 0) + PRINTF (" heap == 0\n"); + else { + p = (TMemBlock *)heap; + + while (p) { + PRINTF (" Offset:%08x, Size:%08x, %c%c\n",p->ofs,p->size, + p->free ? '.':'U', + p->reserved ? 'R':'.'); + p = p->next; + } + } + + PRINTF ("End of memory blocks\n"); +} + +memHeap_t *via_mmInit(int ofs, + int size) +{ + PMemBlock blocks; + + if (size <= 0) + return 0; + + + blocks = (TMemBlock *)calloc(1,sizeof(TMemBlock)); + + if (blocks) { + blocks->ofs = ofs; + blocks->size = size; + blocks->free = 1; + return (memHeap_t *)blocks; + } else + return 0; +} + +memHeap_t *via_mmAddRange(memHeap_t *heap, + int ofs, + int size) +{ + PMemBlock blocks; + blocks = (TMemBlock *) calloc(2,sizeof(TMemBlock)); + + if (blocks) { + 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*)calloc(1,sizeof(TMemBlock)); + 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*) calloc(1,sizeof(TMemBlock)); + 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 via_mmAllocMem(memHeap_t *heap, int size, int align2, int startSearch) +{ + int mask,startofs,endofs; + TMemBlock *p; + + if (!heap || align2 < 0 || size <= 0) + return NULL; + + mask = (1 << align2)-1; + startofs = 0; + p = (TMemBlock *)heap; + + while (p) { + 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) + 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; + free(q); + + return 1; + } + + return 0; +} + +int via_mmFreeMem(PMemBlock b) +{ + TMemBlock *p,*prev; + + if (!b) + return 0; + + if (!b->heap) { + fprintf(stderr, "no heap\n"); + + return -1; + } + + p = b->heap; + prev = NULL; + + while (p && p != b) { + prev = p; + p = p->next; + } + + if (!p || p->free || p->reserved) { + if (!p) + fprintf(stderr, "block not found in heap\n"); + else if (p->free) + fprintf(stderr, "block already free\n"); + else + fprintf(stderr, "block is reserved\n"); + + + return -1; + } + + p->free = 1; + Join2Blocks(p); + + if (prev) + Join2Blocks(prev); + + return 0; +} + +int via_mmReserveMem(memHeap_t *heap, int offset,int size) +{ + int endofs; + TMemBlock *p; + + if (!heap || 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 via_mmFreeReserved(memHeap_t *heap, int offset) +{ + TMemBlock *p,*prev; + + if (!heap) + return -1; + + p = (TMemBlock *)heap; + prev = NULL; + + while (p && p->ofs != offset) { + prev = p; + p = p->next; + } + + if (!p || !p->reserved) + return -1; + p->free = 1; + p->reserved = 0; + Join2Blocks(p); + + if (prev) + Join2Blocks(prev); + + return 0; +} + +void via_mmDestroy(memHeap_t *heap) +{ + TMemBlock *p,*q; + + if (!heap) + return; + p = (TMemBlock *)heap; + + while (p) { + q = p->next; + free(p); + p = q; + } +} diff --git a/shared/via_ds.h b/shared/via_ds.h new file mode 100644 index 00000000..50ab3e7f --- /dev/null +++ b/shared/via_ds.h @@ -0,0 +1,108 @@ +/* + * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved. + * Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved. + * 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, sub license, + * 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 NON-INFRINGEMENT. IN NO EVENT SHALL + * VIA, S3 GRAPHICS, 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. + */ +#ifndef _via_ds_h_ +#define _via_ds_h_ + +#include "via.h" +#include "drmP.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 *via_setInit(void); +int via_setAdd(set_t *set, ITEM_TYPE item); +int via_setDel(set_t *set, ITEM_TYPE item); +int via_setFirst(set_t *set, ITEM_TYPE *item); +int via_setNext(set_t *set, ITEM_TYPE *item); +int via_setDestroy(set_t *set); + +#endif + + +#ifndef MM_INC +#define MM_INC + +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 *via_mmInit(int ofs, int size); + + +PMemBlock via_mmAllocMem(memHeap_t *heap, int size, int align2, int startSearch); + +/* + * Free block starts at offset + * input: pointer to a block + * return: 0 if OK, -1 if error + */ +int via_mmFreeMem(PMemBlock b); + +/* + * destroy MM + */ +void via_mmDestroy(memHeap_t *mmInit); + +/* For debugging purpose. */ +void via_mmDumpMemInfo(memHeap_t *mmInit); + +#endif diff --git a/shared/via_irq.c b/shared/via_irq.c new file mode 100644 index 00000000..835b41cd --- /dev/null +++ b/shared/via_irq.c @@ -0,0 +1,162 @@ +/* via_irq.c + * + * Copyright 2004 BEAM Ltd. + * Copyright 2002 Tungsten Graphics, Inc. + * 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 + * BEAM LTD, TUNGSTEN GRAPHICS 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: + * Terry Barnaby <terry1@beam.ltd.uk> + * Keith Whitwell <keith@tungstengraphics.com> + * + * + * This code provides standard DRM access to the Via CLE266's Vertical blank + * interrupt. + */ + +#include "via.h" +#include "drmP.h" +#include "drm.h" +#include "via_drm.h" +#include "via_drv.h" + +#define VIA_REG_INTERRUPT 0x200 + +/* VIA_REG_INTERRUPT */ +#define VIA_IRQ_GLOBAL (1 << 31) +#define VIA_IRQ_VBI_ENABLE (1 << 19) +#define VIA_IRQ_VBI_PENDING (1 << 3) + +irqreturn_t DRM(irq_handler)( DRM_IRQ_ARGS ) + +{ + drm_device_t* dev = (drm_device_t*)arg; + drm_via_private_t* dev_priv = (drm_via_private_t*)dev->dev_private; + u32 status; + int handled = 0; + + status = VIA_READ(VIA_REG_INTERRUPT); + DRM_DEBUG("viadrv_irq_handler Status: %x\n",status); + if(status & VIA_IRQ_VBI_PENDING){ + atomic_inc(&dev->vbl_received); + DRM_WAKEUP(&dev->vbl_queue); + DRM(vbl_send_signals)(dev); + handled = 1; + } + + /* Acknowlege interrupts ?? */ + VIA_WRITE(VIA_REG_INTERRUPT, status); + return IRQ_RETVAL(handled); +} + +static __inline__ void viadrv_acknowledge_irqs(drm_via_private_t* dev_priv) +{ + u32 status; + + if(dev_priv){ + /* Acknowlege interrupts ?? */ + status = VIA_READ(VIA_REG_INTERRUPT); + VIA_WRITE(VIA_REG_INTERRUPT, status | VIA_IRQ_VBI_PENDING); + } +} + +int DRM(vblank_wait)(drm_device_t* dev, unsigned int* sequence) +{ + drm_via_private_t* dev_priv = (drm_via_private_t*)dev->dev_private; + unsigned int cur_vblank; + int ret = 0; + + DRM_DEBUG("viadrv_vblank_wait\n"); + if(!dev_priv){ + DRM_ERROR("%s called with no initialization\n", __FUNCTION__ ); + return -EINVAL; + } + + viadrv_acknowledge_irqs(dev_priv); + + /* Assume that the user has missed the current sequence number + * by about a day rather than she wants to wait for years + * using vertical blanks... + */ + DRM_WAIT_ON(ret, dev->vbl_queue, 3*DRM_HZ, + (((cur_vblank = atomic_read(&dev->vbl_received)) - + *sequence ) <= (1<<23))); + + *sequence = cur_vblank; + return ret; +} + +/* + * drm_dma.h hooks + */ +void DRM(driver_irq_preinstall)(drm_device_t* dev){ + drm_via_private_t* dev_priv = (drm_via_private_t *)dev->dev_private; + u32 status; + + DRM_DEBUG("driver_irq_preinstall: dev_priv: %p\n", dev_priv); + if(dev_priv){ + DRM_DEBUG("mmio: %p\n", dev_priv->mmio); + status = VIA_READ(VIA_REG_INTERRUPT); + DRM_DEBUG("intreg: %x\n", status & VIA_IRQ_VBI_ENABLE); + + // Clear VSync interrupt regs + VIA_WRITE(VIA_REG_INTERRUPT, status & ~VIA_IRQ_VBI_ENABLE); + + /* Clear bits if they're already high */ + viadrv_acknowledge_irqs(dev_priv); + } +} + +void DRM(driver_irq_postinstall)(drm_device_t* dev){ + drm_via_private_t* dev_priv = (drm_via_private_t *)dev->dev_private; + u32 status; + + DRM_DEBUG("via_driver_irq_postinstall\n"); + if(dev_priv){ + status = VIA_READ(VIA_REG_INTERRUPT); + VIA_WRITE(VIA_REG_INTERRUPT, status | VIA_IRQ_GLOBAL + | VIA_IRQ_VBI_ENABLE); + /* Some magic, oh for some data sheets ! */ + + VIA_WRITE8(0x83d4, 0x11); + VIA_WRITE8(0x83d5, VIA_READ8(0x83d5) | 0x30); + + } +} + +void DRM(driver_irq_uninstall)(drm_device_t* dev){ + drm_via_private_t* dev_priv = (drm_via_private_t *)dev->dev_private; + u32 status; + + DRM_DEBUG("driver_irq_uninstall)\n"); + if(dev_priv){ + + /* Some more magic, oh for some data sheets ! */ + + VIA_WRITE8(0x83d4, 0x11); + VIA_WRITE8(0x83d5, VIA_READ8(0x83d5) & ~0x30); + + status = VIA_READ(VIA_REG_INTERRUPT); + VIA_WRITE(VIA_REG_INTERRUPT, status & ~VIA_IRQ_VBI_ENABLE); + } +} + diff --git a/shared/via_map.c b/shared/via_map.c new file mode 100644 index 00000000..53260927 --- /dev/null +++ b/shared/via_map.c @@ -0,0 +1,143 @@ +/* + * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved. + * Copyright 2001-2003 S3 Graphics, Inc. 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, sub license, + * 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 NON-INFRINGEMENT. IN NO EVENT SHALL + * VIA, S3 GRAPHICS, 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. + */ +#define __NO_VERSION__ +#include "via.h" +#include "drmP.h" +#include "via_drv.h" + +int via_do_init_map(drm_device_t *dev, drm_via_init_t *init) +{ + drm_via_private_t *dev_priv; + unsigned int i; + + DRM_DEBUG("%s\n", __FUNCTION__); + + dev_priv = DRM(alloc)(sizeof(drm_via_private_t), DRM_MEM_DRIVER); + if (dev_priv == NULL) + return -ENOMEM; + + memset(dev_priv, 0, sizeof(drm_via_private_t)); + + DRM_GETSAREA(); + if (!dev_priv->sarea) { + DRM_ERROR("could not find sarea!\n"); + dev->dev_private = (void *)dev_priv; + via_do_cleanup_map(dev); + return -EINVAL; + } + + DRM_FIND_MAP(dev_priv->fb, init->fb_offset); + if (!dev_priv->fb) { + DRM_ERROR("could not find framebuffer!\n"); + dev->dev_private = (void *)dev_priv; + via_do_cleanup_map(dev); + return -EINVAL; + } + DRM_FIND_MAP(dev_priv->mmio, init->mmio_offset); + if (!dev_priv->mmio) { + DRM_ERROR("could not find mmio region!\n"); + dev->dev_private = (void *)dev_priv; + via_do_cleanup_map(dev); + return -EINVAL; + } + + dev_priv->sarea_priv = + (drm_via_sarea_t *)((u8 *)dev_priv->sarea->handle + + init->sarea_priv_offset); + + dev_priv->agpAddr = init->agpAddr; + + + for (i=0; i<VIA_NR_XVMC_LOCKS; ++i) + DRM_INIT_WAITQUEUE( &(dev_priv->decoder_queue[i]) ); + + dev->dev_private = (void *)dev_priv; + + return 0; +} + +int via_do_cleanup_map(drm_device_t *dev) +{ + if (dev->dev_private) { + + drm_via_private_t *dev_priv = dev->dev_private; + + DRM(free)(dev_priv, sizeof(drm_via_private_t), + DRM_MEM_DRIVER); + dev->dev_private = NULL; + } + + return 0; +} + +int via_map_init( DRM_IOCTL_ARGS ) +{ + DRM_DEVICE; + drm_via_init_t init; + + DRM_DEBUG("%s\n", __FUNCTION__); + + DRM_COPY_FROM_USER_IOCTL(init, (drm_via_init_t *)data, sizeof(init)); + + switch (init.func) { + case VIA_INIT_MAP: + return via_do_init_map(dev, &init); + case VIA_CLEANUP_MAP: + return via_do_cleanup_map(dev); + } + + return -EINVAL; +} + +int via_decoder_futex( DRM_IOCTL_ARGS ) +{ + DRM_DEVICE; + drm_via_futex_t fx; + volatile int *lock; + drm_via_private_t *dev_priv = (drm_via_private_t*) dev->dev_private; + drm_via_sarea_t *sAPriv = dev_priv->sarea_priv; + int ret = 0; + + DRM_COPY_FROM_USER_IOCTL(fx, (drm_via_futex_t *) data, sizeof(fx)); + + if (fx.lock > VIA_NR_XVMC_LOCKS) + return -EFAULT; + + lock = XVMCLOCKPTR(sAPriv,fx.lock); + + switch(fx.op) { + case VIA_FUTEX_WAIT: + DRM_WAIT_ON(ret, dev_priv->decoder_queue[fx.lock], + (fx.ms / 10)*(DRM_HZ/100), + *lock != fx.val); + return ret; + case VIA_FUTEX_WAKE: + DRM_WAKEUP( &(dev_priv->decoder_queue[fx.lock]) ); + return 0; + } + return 0; +} + + + diff --git a/shared/via_mm.c b/shared/via_mm.c new file mode 100644 index 00000000..1bf04fe0 --- /dev/null +++ b/shared/via_mm.c @@ -0,0 +1,347 @@ +/* + * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved. + * Copyright 2001-2003 S3 Graphics, Inc. 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, sub license, + * 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 NON-INFRINGEMENT. IN NO EVENT SHALL + * VIA, S3 GRAPHICS, 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. + */ +#define __NO_VERSION__ +#include "via.h" +#include "drmP.h" +#include "via_drm.h" +#include "via_drv.h" +#include "via_ds.h" +#include "via_mm.h" + +#define MAX_CONTEXT 100 + +unsigned int VIA_DEBUG = 1; + +typedef struct { + int used; + int context; + set_t *sets[2]; /* 0 for frame buffer, 1 for AGP , 2 for System*/ +} via_context_t; + +static via_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 = via_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 = via_setDel(global_ppriv[i].sets[type], val); + break; + } + + return retval; +} + +/* agp memory management */ +static memHeap_t *AgpHeap = NULL; + +int via_agp_init( DRM_IOCTL_ARGS ) +{ + drm_via_agp_t agp; + + DRM_COPY_FROM_USER_IOCTL(agp, (drm_via_agp_t *)data, sizeof(agp)); + + AgpHeap = via_mmInit(agp.offset, agp.size); + + DRM_DEBUG("offset = %u, size = %u", agp.offset, agp.size); + + return 0; +} + +/* fb memory management */ +static memHeap_t *FBHeap = NULL; + +int via_fb_init( DRM_IOCTL_ARGS ) +{ + drm_via_fb_t fb; + + + DRM_COPY_FROM_USER_IOCTL(fb, (drm_via_fb_t *)data, sizeof(fb)); + + FBHeap = via_mmInit(fb.offset, fb.size); + + DRM_DEBUG("offset = %u, size = %u", fb.offset, fb.size); + + return 0; +} + +int via_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] = via_setInit(); + global_ppriv[i].sets[1] = via_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 via_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 = via_setFirst(set, &item); + while (retval) { + DRM_DEBUG("free video memory 0x%x\n", item); + via_mmFreeMem((PMemBlock)item); + retval = via_setNext(set, &item); + } + via_setDestroy(set); + + /* AGP Memory */ + set = global_ppriv[i].sets[1]; + retval = via_setFirst(set, &item); + while (retval) { + DRM_DEBUG("free agp memory 0x%x\n", item); + via_mmFreeMem((PMemBlock)item); + retval = via_setNext(set, &item); + } + via_setDestroy(set); + + global_ppriv[i].used = 0; + } + + return 1; +} +int via_mem_alloc( DRM_IOCTL_ARGS) +{ + drm_via_mem_t mem; + + DRM_COPY_FROM_USER_IOCTL(mem, (drm_via_mem_t *)data, sizeof(mem)); + switch (mem.type) { + case VIDEO : + if (via_fb_alloc(&mem) < 0) + return -EFAULT; + DRM_COPY_TO_USER_IOCTL((drm_via_mem_t *)data, mem, + sizeof(mem)); + return 0; + case AGP : + if (via_agp_alloc(&mem) < 0) + return -EFAULT; + DRM_COPY_TO_USER_IOCTL((drm_via_mem_t *)data, mem, + sizeof(mem)); + return 0; + } + + return -EFAULT; +} + +int via_fb_alloc(drm_via_mem_t* mem) +{ + drm_via_mm_t fb; + PMemBlock block; + int retval = 0; + + if (!FBHeap) + return -1; + + fb.size = mem->size; + fb.context = mem->context; + + block = via_mmAllocMem(FBHeap, fb.size, 5, 0); + if (block) { + fb.offset = block->ofs; + fb.free = (unsigned int)block; + if (!add_alloc_set(fb.context, VIDEO, fb.free)) { + DRM_DEBUG("adding to allocation set fails\n"); + via_mmFreeMem((PMemBlock)fb.free); + retval = -1; + } + } + else { + fb.offset = 0; + fb.size = 0; + fb.free = 0; + retval = -1; + } + + mem->offset = fb.offset; + mem->index = fb.free; + + DRM_DEBUG("alloc fb, size = %d, offset = %d\n", fb.size, + (int)fb.offset); + + return retval; +} +int via_agp_alloc(drm_via_mem_t* mem) +{ + drm_via_mm_t agp; + PMemBlock block; + int retval = 0; + + if (!AgpHeap) + return -1; + + agp.size = mem->size; + agp.context = mem->context; + + block = via_mmAllocMem(AgpHeap, agp.size, 5, 0); + if (block) { + agp.offset = block->ofs; + agp.free = (unsigned int)block; + if (!add_alloc_set(agp.context, AGP, agp.free)) { + DRM_DEBUG("adding to allocation set fails\n"); + via_mmFreeMem((PMemBlock)agp.free); + retval = -1; + } + } + else { + agp.offset = 0; + agp.size = 0; + agp.free = 0; + } + + mem->offset = agp.offset; + mem->index = agp.free; + + DRM_DEBUG("alloc agp, size = %d, offset = %d\n", agp.size, + (unsigned int)agp.offset); + return retval; +} + +int via_mem_free( DRM_IOCTL_ARGS ) +{ + drm_via_mem_t mem; + + DRM_COPY_FROM_USER_IOCTL(mem, (drm_via_mem_t *)data, sizeof(mem)); + + switch (mem.type) { + + case VIDEO : + if (via_fb_free(&mem) == 0) + return 0; + break; + case AGP : + if (via_agp_free(&mem) == 0) + return 0; + break; + } + + return -EFAULT; +} +int via_fb_free(drm_via_mem_t* mem) +{ + drm_via_mm_t fb; + int retval = 0; + + + if (!FBHeap) { + return -1; + } + + fb.free = mem->index; + fb.context = mem->context; + + if (!fb.free) + { + return -1; + + } + + via_mmFreeMem((PMemBlock)fb.free); + + if (!del_alloc_set(fb.context, VIDEO, fb.free)) + { + retval = -1; + } + + DRM_DEBUG("free fb, free = %d\n", fb.free); + + return retval; +} +int via_agp_free(drm_via_mem_t* mem) +{ + drm_via_mm_t agp; + + int retval = 0; + + agp.free = mem->index; + agp.context = mem->context; + + if (!agp.free) + return -1; + + via_mmFreeMem((PMemBlock)agp.free); + + if (!del_alloc_set(agp.context, AGP, agp.free)) { + retval = -1; + } + + DRM_DEBUG("free agp, free = %d\n", agp.free); + + return retval; +} + +EXPORT_SYMBOL(via_fb_alloc); +EXPORT_SYMBOL(via_fb_free); diff --git a/shared/via_mm.h b/shared/via_mm.h new file mode 100644 index 00000000..c476ac6a --- /dev/null +++ b/shared/via_mm.h @@ -0,0 +1,45 @@ +/* + * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved. + * Copyright 2001-2003 S3 Graphics, Inc. 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, sub license, + * 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 NON-INFRINGEMENT. IN NO EVENT SHALL + * VIA, S3 GRAPHICS, 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. + */ +#ifndef _via_drm_mm_h_ +#define _via_drm_mm_h_ + +typedef struct { + unsigned int context; + unsigned int size; + unsigned long offset; + unsigned int free; +} drm_via_mm_t; + +typedef struct { + unsigned int size; + unsigned long handle; + void *virtual; +} drm_via_dma_t; + +int via_fb_alloc(drm_via_mem_t *mem); +int via_fb_free(drm_via_mem_t *mem); +int via_agp_alloc(drm_via_mem_t *mem); +int via_agp_free(drm_via_mem_t *mem); + +#endif |