memory.c 3.4 KB
Newer Older
1
/* memory.c: Prom routine for acquiring various bits of information
L
Linus Torvalds 已提交
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
 *           about RAM on the machine, both virtual and physical.
 *
 * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
 * Copyright (C) 1997 Michael A. Griffith (grif@acm.org)
 */

#include <linux/kernel.h>
#include <linux/init.h>

#include <asm/openprom.h>
#include <asm/sun4prom.h>
#include <asm/oplib.h>

/* This routine, for consistency, returns the ram parameters in the
 * V0 prom memory descriptor format.  I choose this format because I
 * think it was the easiest to work with.  I feel the religious
 * arguments now... ;)  Also, I return the linked lists sorted to
 * prevent paging_init() upset stomach as I have not yet written
 * the pepto-bismol kernel module yet.
 */

struct linux_prom_registers prom_reg_memlist[64];

struct linux_mlist_v0 prom_phys_avail[64];

/* Internal Prom library routine to sort a linux_mlist_v0 memory
 * list.  Used below in initialization.
 */
static void __init
prom_sortmemlist(struct linux_mlist_v0 *thislist)
{
	int swapi = 0;
	int i, mitr, tmpsize;
	char *tmpaddr;
	char *lowest;

A
Al Viro 已提交
38
	for(i=0; thislist[i].theres_more; i++) {
L
Linus Torvalds 已提交
39
		lowest = thislist[i].start_adr;
A
Al Viro 已提交
40
		for(mitr = i+1; thislist[mitr-1].theres_more; mitr++)
L
Linus Torvalds 已提交
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74
			if(thislist[mitr].start_adr < lowest) {
				lowest = thislist[mitr].start_adr;
				swapi = mitr;
			}
		if(lowest == thislist[i].start_adr) continue;
		tmpaddr = thislist[swapi].start_adr;
		tmpsize = thislist[swapi].num_bytes;
		for(mitr = swapi; mitr > i; mitr--) {
			thislist[mitr].start_adr = thislist[mitr-1].start_adr;
			thislist[mitr].num_bytes = thislist[mitr-1].num_bytes;
		}
		thislist[i].start_adr = tmpaddr;
		thislist[i].num_bytes = tmpsize;
	}

	return;
}

/* Initialize the memory lists based upon the prom version. */
void __init prom_meminit(void)
{
	int node = 0;
	unsigned int iter, num_regs;
	struct linux_mlist_v0 *mptr;  /* ptr for traversal */

	switch(prom_vers) {
	case PROM_V0:
		/* Nice, kind of easier to do in this case. */
		for(mptr = (*(romvec->pv_v0mem.v0_available)), iter=0;
		    mptr; mptr=mptr->theres_more, iter++) {
			prom_phys_avail[iter].start_adr = mptr->start_adr;
			prom_phys_avail[iter].num_bytes = mptr->num_bytes;
			prom_phys_avail[iter].theres_more = &prom_phys_avail[iter+1];
		}
A
Al Viro 已提交
75
		prom_phys_avail[iter-1].theres_more = NULL;
L
Linus Torvalds 已提交
76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94
		prom_sortmemlist(prom_phys_avail);
		break;
	case PROM_V2:
	case PROM_V3:
		/* Grrr, have to traverse the prom device tree ;( */
		node = prom_getchild(prom_root_node);
		node = prom_searchsiblings(node, "memory");
		num_regs = prom_getproperty(node, "available",
					    (char *) prom_reg_memlist,
					    sizeof(prom_reg_memlist));
		num_regs = (num_regs/sizeof(struct linux_prom_registers));
		for(iter=0; iter<num_regs; iter++) {
			prom_phys_avail[iter].start_adr =
				(char *) prom_reg_memlist[iter].phys_addr;
			prom_phys_avail[iter].num_bytes =
				(unsigned long) prom_reg_memlist[iter].reg_size;
			prom_phys_avail[iter].theres_more =
				&prom_phys_avail[iter+1];
		}
A
Al Viro 已提交
95
		prom_phys_avail[iter-1].theres_more = NULL;
L
Linus Torvalds 已提交
96 97 98 99 100 101
		prom_sortmemlist(prom_phys_avail);
		break;

	case PROM_SUN4:
#ifdef CONFIG_SUN4	
		/* how simple :) */
A
Al Viro 已提交
102
		prom_phys_avail[0].start_adr = NULL;
L
Linus Torvalds 已提交
103
		prom_phys_avail[0].num_bytes = *(sun4_romvec->memoryavail);
A
Al Viro 已提交
104
		prom_phys_avail[0].theres_more = NULL;
L
Linus Torvalds 已提交
105 106 107 108 109 110 111 112 113
#endif
		break;

	default:
		break;
	};
}

/* This returns a pointer to our libraries internal v0 format
114
 * available memory list.
L
Linus Torvalds 已提交
115
 */
116
struct linux_mlist_v0 *
L
Linus Torvalds 已提交
117 118
prom_meminfo(void)
{
119
	return prom_phys_avail;
L
Linus Torvalds 已提交
120
}