2005-04-17 02:20:36 +04:00
/*
* * linux / amiga / chipram . c
* *
* * Modified 03 - May - 94 by Geert Uytterhoeven < geert @ linux - m68k . org >
* * - 64 - bit aligned allocations for full AGA compatibility
* *
* * Rewritten 15 / 9 / 2000 by Geert to use resource management
*/
# include <linux/types.h>
# include <linux/kernel.h>
2008-07-24 08:28:13 +04:00
# include <linux/mm.h>
2005-04-17 02:20:36 +04:00
# include <linux/init.h>
# include <linux/ioport.h>
# include <linux/slab.h>
# include <linux/string.h>
2008-02-05 09:30:25 +03:00
# include <linux/module.h>
2005-04-17 02:20:36 +04:00
# include <asm/page.h>
# include <asm/amigahw.h>
unsigned long amiga_chip_size ;
2008-02-05 09:30:25 +03:00
EXPORT_SYMBOL ( amiga_chip_size ) ;
2005-04-17 02:20:36 +04:00
static struct resource chipram_res = {
. name = " Chip RAM " , . start = CHIP_PHYSADDR
} ;
static unsigned long chipavail ;
void __init amiga_chip_init ( void )
{
if ( ! AMIGAHW_PRESENT ( CHIP_RAM ) )
return ;
/*
* Remove the first 4 pages where PPC exception handlers will be located
*/
amiga_chip_size - = 0x4000 ;
chipram_res . end = amiga_chip_size - 1 ;
request_resource ( & iomem_resource , & chipram_res ) ;
chipavail = amiga_chip_size ;
}
void * amiga_chip_alloc ( unsigned long size , const char * name )
{
struct resource * res ;
/* round up */
size = PAGE_ALIGN ( size ) ;
# ifdef DEBUG
printk ( " amiga_chip_alloc: allocate %ld bytes \n " , size ) ;
# endif
2006-12-07 07:34:51 +03:00
res = kzalloc ( sizeof ( struct resource ) , GFP_KERNEL ) ;
2005-04-17 02:20:36 +04:00
if ( ! res )
return NULL ;
res - > name = name ;
if ( allocate_resource ( & chipram_res , res , size , 0 , UINT_MAX , PAGE_SIZE , NULL , NULL ) < 0 ) {
kfree ( res ) ;
return NULL ;
}
chipavail - = size ;
# ifdef DEBUG
printk ( " amiga_chip_alloc: returning %lx \n " , res - > start ) ;
# endif
return ( void * ) ZTWO_VADDR ( res - > start ) ;
}
2008-02-05 09:30:25 +03:00
EXPORT_SYMBOL ( amiga_chip_alloc ) ;
2005-04-17 02:20:36 +04:00
/*
* Warning :
* amiga_chip_alloc_res is meant only for drivers that need to allocate
* Chip RAM before kmalloc ( ) is functional . As a consequence , those
* drivers must not free that Chip RAM afterwards .
*/
void * __init amiga_chip_alloc_res ( unsigned long size , struct resource * res )
{
unsigned long start ;
/* round up */
size = PAGE_ALIGN ( size ) ;
/* dmesg into chipmem prefers memory at the safe end */
start = CHIP_PHYSADDR + chipavail - size ;
# ifdef DEBUG
printk ( " amiga_chip_alloc_res: allocate %ld bytes \n " , size ) ;
# endif
if ( allocate_resource ( & chipram_res , res , size , start , UINT_MAX , PAGE_SIZE , NULL , NULL ) < 0 ) {
printk ( " amiga_chip_alloc_res: first alloc failed! \n " ) ;
if ( allocate_resource ( & chipram_res , res , size , 0 , UINT_MAX , PAGE_SIZE , NULL , NULL ) < 0 )
return NULL ;
}
chipavail - = size ;
# ifdef DEBUG
printk ( " amiga_chip_alloc_res: returning %lx \n " , res - > start ) ;
# endif
return ( void * ) ZTWO_VADDR ( res - > start ) ;
}
void amiga_chip_free ( void * ptr )
{
unsigned long start = ZTWO_PADDR ( ptr ) ;
struct resource * * p , * res ;
unsigned long size ;
for ( p = & chipram_res . child ; ( res = * p ) ; p = & res - > sibling ) {
if ( res - > start ! = start )
continue ;
* p = res - > sibling ;
size = res - > end - start ;
# ifdef DEBUG
printk ( " amiga_chip_free: free %ld bytes at %p \n " , size , ptr ) ;
# endif
chipavail + = size ;
kfree ( res ) ;
return ;
}
printk ( " amiga_chip_free: trying to free nonexistent region at %p \n " , ptr ) ;
}
2008-02-05 09:30:25 +03:00
EXPORT_SYMBOL ( amiga_chip_free ) ;
2005-04-17 02:20:36 +04:00
unsigned long amiga_chip_avail ( void )
{
# ifdef DEBUG
printk ( " amiga_chip_avail : %ld bytes \n " , chipavail ) ;
# endif
return chipavail ;
}
2008-02-05 09:30:25 +03:00
EXPORT_SYMBOL ( amiga_chip_avail ) ;