2008-05-01 21:28:59 -07:00
/* memory.c: Prom routine for acquiring various bits of information
2005-04-16 15:20:36 -07:00
* about RAM on the machine , both virtual and physical .
*
2008-05-01 22:28:17 -07:00
* Copyright ( C ) 1995 , 2008 David S . Miller ( davem @ davemloft . net )
2005-04-16 15:20:36 -07:00
* Copyright ( C ) 1997 Michael A . Griffith ( grif @ acm . org )
*/
# include <linux/kernel.h>
2008-05-01 22:28:17 -07:00
# include <linux/sort.h>
2005-04-16 15:20:36 -07:00
# include <linux/init.h>
# include <asm/openprom.h>
# include <asm/oplib.h>
2008-05-01 22:28:17 -07:00
# include <asm/page.h>
2005-04-16 15:20:36 -07:00
2008-05-01 22:28:17 -07:00
static int __init prom_meminit_v0 ( void )
{
struct linux_mlist_v0 * p ;
int index ;
2005-04-16 15:20:36 -07:00
2008-05-01 22:28:17 -07:00
index = 0 ;
for ( p = * ( romvec - > pv_v0mem . v0_available ) ; p ; p = p - > theres_more ) {
sp_banks [ index ] . base_addr = ( unsigned long ) p - > start_adr ;
sp_banks [ index ] . num_bytes = p - > num_bytes ;
index + + ;
}
2005-04-16 15:20:36 -07:00
2008-05-01 22:28:17 -07:00
return index ;
}
2005-04-16 15:20:36 -07:00
2008-05-01 22:28:17 -07:00
static int __init prom_meminit_v2 ( void )
2005-04-16 15:20:36 -07:00
{
2008-05-01 22:28:17 -07:00
struct linux_prom_registers reg [ 64 ] ;
int node , size , num_ents , i ;
node = prom_searchsiblings ( prom_getchild ( prom_root_node ) , " memory " ) ;
size = prom_getproperty ( node , " available " , ( char * ) reg , sizeof ( reg ) ) ;
num_ents = size / sizeof ( struct linux_prom_registers ) ;
for ( i = 0 ; i < num_ents ; i + + ) {
sp_banks [ i ] . base_addr = reg [ i ] . phys_addr ;
sp_banks [ i ] . num_bytes = reg [ i ] . reg_size ;
2005-04-16 15:20:36 -07:00
}
2008-05-01 22:28:17 -07:00
return num_ents ;
}
static int sp_banks_cmp ( const void * a , const void * b )
{
const struct sparc_phys_banks * x = a , * y = b ;
if ( x - > base_addr > y - > base_addr )
return 1 ;
if ( x - > base_addr < y - > base_addr )
return - 1 ;
return 0 ;
2005-04-16 15:20:36 -07:00
}
/* Initialize the memory lists based upon the prom version. */
void __init prom_meminit ( void )
{
2008-05-01 22:28:17 -07:00
int i , num_ents = 0 ;
2005-04-16 15:20:36 -07:00
2008-05-01 22:28:17 -07:00
switch ( prom_vers ) {
2005-04-16 15:20:36 -07:00
case PROM_V0 :
2008-05-01 22:28:17 -07:00
num_ents = prom_meminit_v0 ( ) ;
2005-04-16 15:20:36 -07:00
break ;
2008-05-01 22:28:17 -07:00
2005-04-16 15:20:36 -07:00
case PROM_V2 :
case PROM_V3 :
2008-05-01 22:28:17 -07:00
num_ents = prom_meminit_v2 ( ) ;
2005-04-16 15:20:36 -07:00
break ;
default :
break ;
2008-05-01 22:28:17 -07:00
}
sort ( sp_banks , num_ents , sizeof ( struct sparc_phys_banks ) ,
sp_banks_cmp , NULL ) ;
2005-04-16 15:20:36 -07:00
2008-05-01 22:28:17 -07:00
/* Sentinel. */
sp_banks [ num_ents ] . base_addr = 0xdeadbeef ;
sp_banks [ num_ents ] . num_bytes = 0 ;
for ( i = 0 ; i < num_ents ; i + + )
sp_banks [ i ] . num_bytes & = PAGE_MASK ;
2005-04-16 15:20:36 -07:00
}