2005-06-28 22:48:56 +10:00
/*
* 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 .
*/
# 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 <linux/pci.h>
# include <asm/io.h>
# include "via_ds.h"
extern unsigned int VIA_DEBUG ;
set_t * via_setInit ( void )
{
int i ;
set_t * set ;
set = ( set_t * ) drm_alloc ( sizeof ( set_t ) , DRM_MEM_DRIVER ) ;
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 ) , DRM_MEM_DRIVER ) ;
return 1 ;
}
# define ISFREE(bptr) ((bptr)->free)
# define fprintf(fmt, arg...) do{}while(0)
memHeap_t * via_mmInit ( int ofs , int size )
{
PMemBlock blocks ;
if ( size < = 0 )
2005-07-27 11:43:56 -07:00
return NULL ;
2005-06-28 22:48:56 +10:00
blocks = ( TMemBlock * ) drm_calloc ( 1 , sizeof ( TMemBlock ) , DRM_MEM_DRIVER ) ;
if ( blocks ) {
blocks - > ofs = ofs ;
blocks - > size = size ;
blocks - > free = 1 ;
return ( memHeap_t * ) blocks ;
} else
2005-07-27 11:43:56 -07:00
return NULL ;
2005-06-28 22:48:56 +10:00
}
static TMemBlock * SliceBlock ( TMemBlock * p ,
int startofs , int size ,
int reserved , int alignment )
{
TMemBlock * newblock ;
/* break left */
if ( startofs > p - > ofs ) {
newblock =
( TMemBlock * ) drm_calloc ( 1 , sizeof ( TMemBlock ) ,
DRM_MEM_DRIVER ) ;
newblock - > ofs = startofs ;
newblock - > size = p - > size - ( startofs - p - > ofs ) ;
newblock - > free = 1 ;
newblock - > next = p - > next ;
p - > size - = newblock - > size ;
p - > next = newblock ;
p = newblock ;
}
/* break right */
if ( size < p - > size ) {
newblock =
( TMemBlock * ) drm_calloc ( 1 , sizeof ( TMemBlock ) ,
DRM_MEM_DRIVER ) ;
newblock - > ofs = startofs + size ;
newblock - > size = p - > size - size ;
newblock - > free = 1 ;
newblock - > next = p - > next ;
p - > size = size ;
p - > next = newblock ;
}
/* p = middle block */
p - > align = alignment ;
p - > free = 0 ;
p - > reserved = reserved ;
return p ;
}
PMemBlock 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 ;
drm_free ( q , sizeof ( TMemBlock ) , DRM_MEM_DRIVER ) ;
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 ;
}