/*
* Procedures for interfacing to the Open Firmware PROM on
* Power Macintosh computers.
*
* In particular, we are interested in the device tree
* and in using some of its services (exit, write to stdout).
*
* Paul Mackerras August 1996.
* Copyright (C) 1996 Paul Mackerras.
*/
#include <stdarg.h>
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/init.h>
#include <linux/threads.h>
#include <linux/spinlock.h>
#include <linux/ioport.h>
#include <linux/pci.h>
#include <linux/slab.h>
#include <linux/bitops.h>
#include <asm/sections.h>
#include <asm/prom.h>
#include <asm/page.h>
#include <asm/processor.h>
#include <asm/irq.h>
#include <asm/io.h>
#include <asm/smp.h>
#include <asm/bootx.h>
#include <asm/system.h>
#include <asm/mmu.h>
#include <asm/pgtable.h>
#include <asm/bootinfo.h>
#include <asm/btext.h>
#include <asm/pci-bridge.h>
#include <asm/open_pic.h>
struct pci_address {
unsigned a_hi;
unsigned a_mid;
unsigned a_lo;
};
struct pci_reg_property {
struct pci_address addr;
unsigned size_hi;
unsigned size_lo;
};
struct isa_reg_property {
unsigned space;
unsigned address;
unsigned size;
};
typedef unsigned long interpret_func(struct device_node *, unsigned long,
int, int);
static interpret_func interpret_pci_props;
static interpret_func interpret_dbdma_props;
static interpret_func interpret_isa_props;
static interpret_func interpret_macio_props;
static interpret_func interpret_root_props;
extern char *klimit;
/* Set for a newworld or CHRP machine */
int use_of_interrupt_tree;
struct device_node *dflt_interrupt_controller;
int num_interrupt_controllers;
extern unsigned int rtas_entry; /* physical pointer */
extern struct device_node *allnodes;
static unsigned long finish_node(struct device_node *, unsigned long,
interpret_func *, int, int);
static unsigned long finish_node_interrupts(struct device_node *, unsigned long);
static struct device_node *find_phandle(phandle);
extern void enter_rtas(void *);
void phys_call_rtas(int, int, int, ...);
extern char cmd_line[512]; /* XXX */
extern boot_infos_t *boot_infos;
unsigned long dev_tree_size;
void
phys_call_rtas(int service, int nargs, int nret, ...)
{
va_list list;
union {
unsigned long words[16];
double align;
} u;
void (*rtas)(void *, unsigned long);
int i;
u.words[0] = service;
u.words[1] = nargs;
u.words[2] = nret;
va_start(list, nret);
for (i = 0; i < nargs; ++i)
u.words[i+3] = va_arg(list, unsigned long);
va_end(list);
rtas = (void (*)(void *, unsigned long)) rtas_entry;
rtas(&u, rtas_data);
}
/*
* finish_device_tree is called once things are running normally
* (i.e. with text and data mapped to the address they were linked at).
* It traverses the device tree and fills in the name, type,
* {n_}addrs and {n_}intrs fields of each node.
*/
void __init
finish_device_tree(void)
{
unsigned long mem = (unsigned long) klimit;
struct device_node *np;
/* All CHRPs now use the interrupt tree */
for (np = allnodes; np != NULL; np = np->allnext) {
if (get_property(np, "interrupt-parent", NULL)) {
use_of_interrupt_tree = 1;
break;
}
}
if (use_of_interrupt_tree) {
/*
* We want to find out here how many interrupt-controller
* nodes there are, and if we are booted from BootX,
* we need a pointer to the first (and hopefully only)
* such node. But we can't use find_devices here since
* np->name
|