patch-1.3.4 linux/arch/sparc/kernel/probe.c
Next file: linux/arch/sparc/kernel/process.c
Previous file: linux/arch/sparc/kernel/mp.S
Back to the patch index
Back to the overall index
- Lines: 761
- Date:
Mon Jun 26 11:19:36 1995
- Orig file:
v1.3.3/linux/arch/sparc/kernel/probe.c
- Orig date:
Wed Mar 1 09:12:33 1995
diff -u --recursive --new-file v1.3.3/linux/arch/sparc/kernel/probe.c linux/arch/sparc/kernel/probe.c
@@ -1,35 +1,41 @@
/* probe.c: Preliminary device tree probing routines...
-
- Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
-*/
+ *
+ * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
+ */
#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
#include <linux/string.h>
+
+#include <asm/oplib.h>
#include <asm/vac-ops.h>
+#include <asm/idprom.h>
#include <asm/io.h>
#include <asm/vaddrs.h>
#include <asm/param.h>
-#include <asm/clock.h>
+#include <asm/timer.h>
+#include <asm/mostek.h>
+#include <asm/auxio.h>
#include <asm/system.h>
+#include <asm/mp.h>
+#include <asm/mbus.h>
/* #define DEBUG_PROBING */
-char promstr_buf[64]; /* overkill */
-unsigned int promint_buf[1];
-
-extern int prom_node_root;
-extern int num_segmaps, num_contexts;
-
-extern int node_get_sibling(int node);
-extern int node_get_child(int node);
-extern char* get_str_from_prom(int node, char* name, char* value);
-extern unsigned int* get_int_from_prom(int node, char* name, unsigned int *value);
+/* XXX Grrr, this stuff should have it's own file, only generic stuff goes
+ * XXX here. Possibly clock.c and timer.c?
+ */
+enum sparc_clock_type sp_clock_typ;
+struct mostek48t02 *mstk48t02_regs;
+struct mostek48t08 *mstk48t08_regs;
+volatile unsigned int *master_l10_limit = 0;
+struct sun4m_timer_regs *sun4m_timers;
-int first_descent;
+static char node_str[128];
/* Cpu-type information and manufacturer strings */
-
struct cpu_iu_info {
int psr_impl;
int psr_vers;
@@ -42,19 +48,24 @@
char* fp_name;
};
+/* In order to get the fpu type correct, you need to take the IDPROM's
+ * machine type value into consideration too. I will fix this.
+ */
struct cpu_fp_info linux_sparc_fpu[] = {
{ 0, 0, "Fujitsu MB86910 or Weitek WTL1164/5"},
- { 0, 1, "Fujitsu MB86911 or Weitek WTL1164/5"},
+ { 0, 1, "Fujitsu MB86911 or Weitek WTL1164/5 or LSI L64831"},
{ 0, 2, "LSI Logic L64802 or Texas Instruments ACT8847"},
+ /* SparcStation SLC, SparcStation1 */
{ 0, 3, "Weitek WTL3170/2"},
- { 0, 4, "Lsi Logic/Meiko L64804"},
+ /* SPARCstation-5 */
+ { 0, 4, "Lsi Logic/Meiko L64804 or compatible"},
{ 0, 5, "reserved"},
{ 0, 6, "reserved"},
{ 0, 7, "No FPU"},
- { 1, 0, "Lsi Logic L64812 or Texas Instruments ACT8847"},
+ { 1, 0, "ROSS HyperSparc combined IU/FPU"},
{ 1, 1, "Lsi Logic L64814"},
{ 1, 2, "Texas Instruments TMS390-C602A"},
- { 1, 3, "Weitek WTL3171"},
+ { 1, 3, "Cypress CY7C602 FPU"},
{ 1, 4, "reserved"},
{ 1, 5, "reserved"},
{ 1, 6, "reserved"},
@@ -63,10 +74,14 @@
{ 2, 1, "reserved"},
{ 2, 2, "reserved"},
{ 2, 3, "reserved"},
- { 2, 4, "reserved"},
+ { 2, 4, "reserved"},
{ 2, 5, "reserved"},
{ 2, 6, "reserved"},
{ 2, 7, "No FPU"},
+ /* SuperSparc 50 module */
+ { 4, 0, "SuperSparc on-chip FPU"},
+ /* SparcClassic */
+ { 4, 4, "TI MicroSparc on chip FPU"},
{ 5, 0, "Matsushita MN10501"},
{ 5, 1, "reserved"},
{ 5, 2, "reserved"},
@@ -77,22 +92,37 @@
{ 5, 7, "No FPU"},
};
+#define NSPARCFPU (sizeof(linux_sparc_fpu)/sizeof(struct cpu_fp_info))
+
struct cpu_iu_info linux_sparc_chips[] = {
- { 0, 0, "Fujitsu Microelectronics, Inc. - MB86900/1A"},
- { 1, 0, "Cypress CY7C601"},
- { 1, 1, "LSI Logic Corporation - L64811"},
- { 1, 3, "Cypress CY7C611"},
+ /* Sun4/100, 4/200, SLC */
+ { 0, 0, "Fujitsu MB86900/1A or LSI L64831 SparcKIT-40"},
+ /* borned STP1012PGA */
+ { 0, 4, "Fujitsu MB86904"},
+ /* SparcStation2, SparcServer 490 & 690 */
+ { 1, 0, "LSI Logic Corporation - L64811"},
+ /* SparcStation2 */
+ { 1, 1, "Cypress/ROSS CY7C601"},
+ /* Embedded controller */
+ { 1, 3, "Cypress/ROSS CY7C611"},
+ /* Ross Technologies HyperSparc */
+ { 1, 0xf, "ROSS HyperSparc RT620"},
+ { 1, 0xe, "ROSS HyperSparc RT625"},
+ /* ECL Implementation, CRAY S-MP Supercomputer... AIEEE! */
+ /* Someone please write the code to support this beast! ;) */
{ 2, 0, "Bipolar Integrated Technology - B5010"},
{ 3, 0, "LSI Logic Corporation - unknown-type"},
- { 4, 0, "Texas Instruments, Inc. - unknown"},
- { 4, 1, "Texas Instruments, Inc. - Sparc Classic"},
- { 4, 2, "Texas Instruments, Inc. - unknown"},
- { 4, 3, "Texas Instruments, Inc. - unknown"},
- { 4, 4, "Texas Instruments, Inc. - unknown"},
+ { 4, 0, "Texas Instruments, Inc. - SuperSparc 50"},
+ /* SparcClassic -- borned STP1010TAB-50*/
+ { 4, 1, "Texas Instruments, Inc. - MicroSparc"},
+ { 4, 2, "Texas Instruments, Inc. - MicroSparc II"},
+ { 4, 3, "Texas Instruments, Inc. - SuperSparc 51"},
+ { 4, 4, "Texas Instruments, Inc. - SuperSparc 61"},
{ 4, 5, "Texas Instruments, Inc. - unknown"},
{ 5, 0, "Matsushita - MN10501"},
{ 6, 0, "Philips Corporation - unknown"},
{ 7, 0, "Harvest VLSI Design Center, Inc. - unknown"},
+ /* Gallium arsenide 200MHz, BOOOOGOOOOMIPS!!! */
{ 8, 0, "Systems and Processes Engineering Corporation (SPEC)"},
{ 9, 0, "UNKNOWN CPU-VENDOR/TYPE"},
{ 0xa, 0, "UNKNOWN CPU-VENDOR/TYPE"},
@@ -103,8 +133,10 @@
{ 0xf, 0, "UNKNOWN CPU-VENDOR/TYPE"},
};
-char *sparc_cpu_type = "cpu-oops";
-char *sparc_fpu_type = "fpu-oops";
+#define NSPARCCHIPS (sizeof(linux_sparc_chips)/sizeof(struct cpu_iu_info))
+
+char *sparc_cpu_type[NCPUS] = { "cpu-oops", "cpu-oops1", "cpu-oops2", "cpu-oops3" };
+char *sparc_fpu_type[NCPUS] = { "fpu-oops", "fpu-oops1", "fpu-oops2", "fpu-oops3" };
/* various Virtual Address Cache parameters we find at boot time... */
@@ -115,82 +147,72 @@
extern int find_vac_size(void);
extern int find_vac_linesize(void);
extern int find_vac_hwflushes(void);
-extern void find_mmu_num_segmaps(void);
-extern void find_mmu_num_contexts(void);
+
+static inline int find_mmu_num_contexts(int cpu)
+{
+ return prom_getintdefault(cpu, "mmu-nctx", 0x8);
+}
+
+unsigned int fsr_storage;
void
probe_cpu(void)
{
- register int psr_impl=0;
- register int psr_vers = 0;
- register int fpu_vers = 0;
- register int i = 0;
- unsigned int tmp_fsr;
-
- &tmp_fsr; /* GCC grrr... */
-
- __asm__("rd %%psr, %0\n\t"
- "mov %0, %1\n\t"
- "srl %0, 28, %0\n\t"
- "srl %1, 24, %1\n\t"
- "and %0, 0xf, %0\n\t"
- "and %1, 0xf, %1\n\t" :
- "=r" (psr_impl),
- "=r" (psr_vers) :
- "0" (psr_impl),
- "1" (psr_vers));
-
-
- __asm__("st %%fsr, %1\n\t"
- "ld %1, %0\n\t"
- "srl %0, 17, %0\n\t"
- "and %0, 0x7, %0\n\t" :
- "=r" (fpu_vers),
- "=m" (tmp_fsr) :
- "0" (fpu_vers),
- "1" (tmp_fsr));
-
- printk("fpu_vers: %d ", fpu_vers);
- printk("psr_impl: %d ", psr_impl);
- printk("psr_vers: %d \n\n", psr_vers);
+ int psr_impl, psr_vers, fpu_vers;
+ int i, cpuid;
+
+ cpuid = get_cpuid();
+
+ psr_impl = ((get_psr()>>28)&0xf);
+ psr_vers = ((get_psr()>>24)&0xf);
+
+ fpu_vers = ((get_fsr()>>17)&0x7);
- for(i = 0; i<23; i++)
+ for(i = 0; i<NSPARCCHIPS; i++)
{
if(linux_sparc_chips[i].psr_impl == psr_impl)
if(linux_sparc_chips[i].psr_vers == psr_vers)
{
- sparc_cpu_type = linux_sparc_chips[i].cpu_name;
+ sparc_cpu_type[cpuid] = linux_sparc_chips[i].cpu_name;
break;
}
}
- if(i==23)
+ if(i==NSPARCCHIPS)
{
printk("No CPU type! You lose\n");
printk("DEBUG: psr.impl = 0x%x psr.vers = 0x%x\n", psr_impl,
psr_vers);
- return;
+ printk("Send this information and the type of SUN and CPU/FPU type you have\n");
+ printk("to davem@caip.rutgers.edu so that this can be fixed.\n");
+ printk("halting...\n\r\n");
+ /* If I don't know about this CPU, I don't want people running on it
+ * until I do.....
+ */
+ halt();
}
- for(i = 0; i<32; i++)
+ for(i = 0; i<NSPARCFPU; i++)
{
if(linux_sparc_fpu[i].psr_impl == psr_impl)
if(linux_sparc_fpu[i].fp_vers == fpu_vers)
{
- sparc_fpu_type = linux_sparc_fpu[i].fp_name;
+ sparc_fpu_type[cpuid] = linux_sparc_fpu[i].fp_name;
break;
}
}
- if(i == 32)
+ if(i == NSPARCFPU)
{
printk("No FPU type! You don't completely lose though...\n");
printk("DEBUG: psr.impl = 0x%x fsr.vers = 0x%x\n", psr_impl, fpu_vers);
- sparc_fpu_type = linux_sparc_fpu[31].fp_name;
+ printk("Send this information and the type of SUN and CPU/FPU type you have\n");
+ printk("to davem@caip.rutgers.edu so that this can be fixed.\n");
+ sparc_fpu_type[cpuid] = linux_sparc_fpu[31].fp_name;
}
- printk("CPU: %s \n", sparc_cpu_type);
- printk("FPU: %s \n", sparc_fpu_type);
+ printk("cpu%d CPU: %s \n", cpuid, sparc_cpu_type[cpuid]);
+ printk("cpu%d FPU: %s \n", cpuid, sparc_fpu_type[cpuid]);
return;
}
@@ -198,205 +220,295 @@
void
probe_vac(void)
{
- register unsigned int x,y;
-
-#ifndef CONFIG_SRMMU
- vac_size = find_vac_size();
- vac_linesize = find_vac_linesize();
- vac_do_hw_vac_flushes = find_vac_hwflushes();
-
- /* Calculate various constants that make the cache-flushing code
- * mode speedy.
- */
-
- vac_entries_per_segment = vac_entries_per_context = vac_size >> 12;
-
- for(x=0,y=vac_linesize; ((1<<x)<y); x++);
- if((1<<x) != vac_linesize) printk("Warning BOGUS VAC linesize 0x%x",
- vac_size);
-
- vac_entries_per_page = x;
+ unsigned int x,y;
- printk("Sparc VAC cache: Size=%d bytes Line-Size=%d bytes ... ", vac_size,
- vac_linesize);
-
- /* Here we want to 'invalidate' all the software VAC "tags"
- * just in case there is garbage in there. Then we enable it.
- */
-
- for(x=0x80000000, y=(x+vac_size); x<y; x+=vac_linesize)
- __asm__("sta %0, [%1] %2" : : "r" (0), "r" (x), "n" (0x2));
-
- x=enable_vac();
- printk("ENABLED\n");
-#endif
-
- return;
+ vac_size = find_vac_size();
+ vac_linesize = find_vac_linesize();
+ vac_do_hw_vac_flushes = find_vac_hwflushes();
+
+ /* Calculate various constants that make the cache-flushing code
+ * mode speedy.
+ */
+
+ vac_entries_per_segment = vac_entries_per_context = vac_size >> 12;
+ for(x=0,y=vac_linesize; ((1<<x)<y); x++);
+ if((1<<x) != vac_linesize) printk("Warning BOGUS VAC linesize 0x%x",
+ vac_size);
+ vac_entries_per_page = x;
+
+ /* Here we want to 'invalidate' all the software VAC "tags"
+ * just in case there is garbage in there. Then we enable it.
+ */
+
+ /* flush flush flush */
+ for(x=AC_CACHETAGS; x<(AC_CACHETAGS+vac_size); x+=vac_linesize)
+ __asm__("sta %%g0, [%0] %1" : : "r" (x), "i" (0x2));
+ x=enable_vac();
+ return;
}
+extern int num_segmaps, num_contexts;
+
void
-probe_mmu(void)
+probe_mmu(int prom_node_cpu)
{
- find_mmu_num_segmaps();
- find_mmu_num_contexts();
+ int cpuid;
- printk("MMU segmaps: %d MMU contexts: %d\n", num_segmaps,
- num_contexts);
+ /* who are we? */
+ cpuid = get_cpuid();
+ switch(sparc_cpu_model) {
+ case sun4:
+ break;
+ case sun4c:
+ /* A sun4, sun4c. */
+ num_segmaps = prom_getintdefault(prom_node_cpu, "mmu-npmg", 128);
+ num_contexts = find_mmu_num_contexts(prom_node_cpu);
+
+ printk("cpu%d MMU segmaps: %d MMU contexts: %d\n", cpuid,
+ num_segmaps, num_contexts);
+ break;
+ case sun4m:
+ case sun4d:
+ case sun4e:
+ /* Any Reference MMU derivate should be handled here, hopefuly. */
+ num_segmaps = 0;
+ num_contexts = find_mmu_num_contexts(prom_node_cpu);
+ vac_linesize = prom_getint(prom_node_cpu, "cache-line-size");
+ vac_size = (prom_getint(prom_node_cpu, "cache-nlines")*vac_linesize);
+ printk("cpu%d MMU contexts: %d\n", cpuid, num_contexts);
+ printk("cpu%d CACHE linesize %d total size %d\n", cpuid, vac_linesize,
+ vac_size);
+ break;
+ default:
+ printk("cpu%d probe_mmu: sparc_cpu_model botch\n", cpuid);
+ break;
+ };
- return;
+ return;
}
+/* Clock probing, we probe the timers here also. */
+/* #define DEBUG_PROBE_CLOCK */
+volatile unsigned int foo_limit;
+
void
probe_clock(int fchild)
{
register int node, type;
- register char *node_str;
+ struct linux_prom_registers clk_reg[2];
/* This will basically traverse the node-tree of the prom to see
* which timer chip is on this machine.
*/
- printk("Probing timer chip... ");
-
- type = 0;
- for(node = fchild ; ; )
- {
- node_str = get_str_from_prom(node, "model", promstr_buf);
- if(strcmp(node_str, "mk48t02") == 0)
- {
- type = 2;
- break;
- }
-
- if(strcmp(node_str, "mk48t08") == 0)
- {
- type = 8;
- break;
- }
-
- node = node_get_sibling(node);
- if(node == fchild)
- {
- printk("Aieee, could not find timer chip type\n");
+ node = 0;
+ if(sparc_cpu_model == sun4) {
+ printk("probe_clock: No SUN4 Clock/Timer support yet...\n");
return;
- }
- }
-
- printk("Mostek %s\n", node_str);
- printk("At OBIO address: 0x%x Virtual address: 0x%x\n",
- (unsigned int) TIMER_PHYSADDR, (unsigned int) TIMER_STRUCT);
-
- mapioaddr((unsigned long) TIMER_PHYSADDR,
- (unsigned long) TIMER_STRUCT);
+ }
+ if(sparc_cpu_model == sun4c) node=prom_getchild(prom_root_node);
+ else
+ if(sparc_cpu_model == sun4m)
+ node=prom_getchild(prom_searchsiblings(prom_getchild(prom_root_node), "obio"));
+ type = 0;
+ sp_clock_typ = MSTK_INVALID;
+ for(;;) {
+ prom_getstring(node, "model", node_str, sizeof(node_str));
+ if(strcmp(node_str, "mk48t02") == 0) {
+ sp_clock_typ = MSTK48T02;
+ if(prom_getproperty(node, "reg", (char *) clk_reg, sizeof(clk_reg)) == -1) {
+ printk("probe_clock: FAILED!\n");
+ halt();
+ }
+ prom_apply_obio_ranges(clk_reg, 1);
+ /* Map the clock register io area read-only */
+ mstk48t02_regs = (struct mostek48t02 *)
+ sparc_alloc_io((void *) clk_reg[0].phys_addr,
+ (void *) 0, sizeof(*mstk48t02_regs),
+ "clock", 0x0, 0x1);
+ mstk48t08_regs = 0; /* To catch weirdness */
+ break;
+ }
- TIMER_STRUCT->timer_limit14=(((1000000/HZ) << 10) | 0x80000000);
+ if(strcmp(node_str, "mk48t08") == 0) {
+ sp_clock_typ = MSTK48T08;
+ if(prom_getproperty(node, "reg", (char *) clk_reg,
+ sizeof(clk_reg)) == -1) {
+ printk("probe_clock: FAILED!\n");
+ halt();
+ }
+ prom_apply_obio_ranges(clk_reg, 1);
+ /* Map the clock register io area read-only */
+ mstk48t08_regs = (struct mostek48t08 *)
+ sparc_alloc_io((void *) clk_reg[0].phys_addr,
+ (void *) 0, sizeof(*mstk48t08_regs),
+ "clock", 0x0, 0x1);
- return;
-}
+ mstk48t02_regs = &mstk48t08_regs->regs;
+ break;
+ }
+ node = prom_getsibling(node);
+ if(node == 0) {
+ printk("Aieee, could not find timer chip type\n");
+ return;
+ }
+ }
-void
-probe_esp(register int esp_node)
-{
- register int nd;
- register char* lbuf;
+ if(sparc_cpu_model == sun4c) {
- nd = node_get_child(esp_node);
+ /* Map the Timer chip, this is implemented in hardware inside
+ * the cache chip on the sun4c.
+ */
+ sparc_alloc_io ((void *) SUN4C_TIMER_PHYSADDR, (void *) TIMER_VADDR,
+ sizeof (*SUN4C_TIMER_STRUCT), "timer", 0x0, 0x0);
- printk("\nProbing ESP:\n");
- lbuf = get_str_from_prom(nd, "name", promstr_buf);
+ /* Have the level 10 timer tick at 100HZ. We don't touch the
+ * level 14 timer limit since we are letting the prom handle
+ * them until we have a real console driver so L1-A works.
+ */
+ SUN4C_TIMER_STRUCT->timer_limit10 = (((1000000/HZ) + 1) << 10);
+ master_l10_limit = &(SUN4C_TIMER_STRUCT->timer_limit10);
- if(*get_int_from_prom(nd, "name", promint_buf) != 0)
- printk("Node: 0x%x Name: %s\n", nd, lbuf);
+ } else {
+ int reg_count;
+ struct linux_prom_registers cnt_regs[PROMREG_MAX];
+ int obio_node, cnt_node;
+
+ cnt_node = 0;
+ if((obio_node =
+ prom_searchsiblings (prom_getchild(prom_root_node), "obio")) == 0 ||
+ (obio_node = prom_getchild (obio_node)) == 0 ||
+ (cnt_node = prom_searchsiblings (obio_node, "counter")) == 0) {
+ printk ("Cannot find /obio/counter node\n");
+ prom_halt ();
+ }
+ reg_count = prom_getproperty(cnt_node, "reg",
+ (void *) cnt_regs, sizeof(cnt_regs));
- while((nd = node_get_sibling(nd)) != 0) {
- lbuf = get_str_from_prom(nd, "name", promstr_buf);
- printk("Node: 0x%x Name: %s\n", nd, lbuf);
- }
+ reg_count = (reg_count/sizeof(struct linux_prom_registers));
- printk("\n");
+ /* Apply the obio ranges to the timer registers. */
+ prom_apply_obio_ranges(cnt_regs, reg_count);
- return;
-}
+ /* Map the per-cpu Counter registers. */
+ sparc_alloc_io(cnt_regs[0].phys_addr, (void *) TIMER_VADDR,
+ PAGE_SIZE*NCPUS, "counters_percpu", cnt_regs[0].which_io, 0x0);
-void
-probe_sbus(register int cpu_child_node)
-{
- register int nd, savend;
- register char* lbuf;
+ /* Map the system Counter register. */
+ sparc_alloc_io(cnt_regs[reg_count-1].phys_addr,
+ (void *) TIMER_VADDR+(NCPUS*PAGE_SIZE),
+ cnt_regs[reg_count-1].reg_size,
+ "counters_system", cnt_regs[reg_count-1].which_io, 0x0);
- nd = cpu_child_node;
- lbuf = (char *) 0;
+ sun4m_timers = (struct sun4m_timer_regs *) TIMER_VADDR;
- while((nd = node_get_sibling(nd)) != 0) {
- lbuf = get_str_from_prom(nd, "name", promstr_buf);
- if(strcmp(lbuf, "sbus") == 0)
- break;
- };
+ foo_limit = (volatile) sun4m_timers->l10_timer_limit;
- nd = node_get_child(nd);
+/* printk("Timer register dump:\n"); */
+#if 0
+ printk("cpu0: l14limit %08x l14curcount %08x\n",
+ sun4m_timers->cpu_timers[0].l14_timer_limit,
+ sun4m_timers->cpu_timers[0].l14_cur_count);
+#endif
+#if 0
+ printk("sys: l10limit %08x l10curcount %08x\n",
+ sun4m_timers->l10_timer_limit,
+ sun4m_timers->l10_cur_count);
+#endif
- printk("Node: 0x%x Name: %s\n", nd,
- get_str_from_prom(nd, "name", promstr_buf));
+ /* Must set the master pointer first or we will lose badly. */
+ master_l10_limit =
+ &(((struct sun4m_timer_regs *)TIMER_VADDR)->l10_timer_limit);
- if(strcmp(lbuf, "esp") == 0) {
- probe_esp(nd);
- };
+ ((struct sun4m_timer_regs *)TIMER_VADDR)->l10_timer_limit =
+ (((1000000/HZ) + 1) << 10); /* 0x9c4000 */
- while((nd = node_get_sibling(nd)) != 0) {
- printk("Node: 0x%x Name: %s\n", nd,
- lbuf = get_str_from_prom(nd, "name", promstr_buf));
-
- if(strcmp(lbuf, "esp") == 0) {
- savend = nd;
- probe_esp(nd);
- nd = savend;
- };
- };
+ /* We should be getting level 10 interrupts now. */
+ }
- printk("\n");
return;
}
-extern unsigned long probe_memory(void);
-extern struct sparc_phys_banks sp_banks[14];
-unsigned int phys_bytes_of_ram, end_of_phys_memory;
-
+/* Probe and map in the Auxiliaary I/O register */
void
-probe_devices(void)
+probe_auxio(void)
{
- register int nd, i;
- register char* str;
+ int node, auxio_nd;
+ struct linux_prom_registers auxregs[1];
+
+ node = prom_getchild(prom_root_node);
+ auxio_nd = prom_searchsiblings(node, "auxiliary-io");
+ if(!auxio_nd) {
+ node = prom_searchsiblings(node, "obio");
+ node = prom_getchild(node);
+ auxio_nd = prom_searchsiblings(node, "auxio");
+ if(!auxio_nd) {
+ printk("Cannot find auxio node, cannot continue...\n");
+ prom_halt();
+ }
+ }
+ prom_getproperty(auxio_nd, "reg", (char *) auxregs, sizeof(auxregs));
+ prom_apply_obio_ranges(auxregs, 0x1);
+ /* Map the register both read and write */
+ sparc_alloc_io(auxregs[0].phys_addr, (void *) AUXIO_VADDR,
+ auxregs[0].reg_size, "auxilliaryIO", auxregs[0].which_io, 0x0);
+ printk("Mapped AUXIO at paddr %08lx vaddr %08lx\n",
+ (unsigned long) auxregs[0].phys_addr,
+ (unsigned long) AUXIO_VADDR);
+ return;
+}
- nd = prom_node_root;
+extern unsigned long probe_memory(void);
+extern struct sparc_phys_banks sp_banks[SPARC_PHYS_BANKS];
+unsigned int phys_bytes_of_ram, end_of_phys_memory;
+extern unsigned long probe_sbus(int, unsigned long);
+extern void probe_mbus(void);
- printk("PROBING DEVICES:\n");
+/* #define DEBUG_PROBE_DEVICES */
+struct prom_cpuinfo linux_cpus[NCPUS];
+int linux_num_cpus;
- str = get_str_from_prom(nd, "device_type", promstr_buf);
- if(strcmp(str, "cpu") == 0) {
- printk("Found CPU root prom device tree node.\n");
+unsigned long
+probe_devices(unsigned long mem_start)
+{
+ int nd, i, prom_node_cpu, thismid;
+ int cpu_nds[NCPUS]; /* One node for each cpu */
+ int cpu_ctr = 0;
+
+ prom_getstring(prom_root_node, "device_type", node_str, sizeof(node_str));
+ if(strcmp(node_str, "cpu") == 0) {
+ cpu_nds[0] = prom_root_node;
+ cpu_ctr++;
} else {
- printk("Root node in device tree was not 'cpu' cannot continue.\n");
- halt();
+ int scan;
+ scan = prom_getchild(prom_root_node);
+ nd = 0;
+ while((scan = prom_getsibling(scan)) != 0) {
+ prom_getstring(scan, "device_type", node_str, sizeof(node_str));
+ if(strcmp(node_str, "cpu") == 0) {
+ cpu_nds[cpu_ctr] = scan;
+ linux_cpus[cpu_ctr].prom_node = scan;
+ prom_getproperty(scan, "mid", (char *) &thismid, sizeof(thismid));
+ linux_cpus[cpu_ctr].mid = thismid;
+ cpu_ctr++;
+ }
+ };
+ if(cpu_ctr == 0) {
+ printk("No CPU nodes found, cannot continue.\n");
+ /* Probably a sun4d or sun4e, Sun is trying to trick us ;-) */
+ halt();
+ }
+ printk("Found %d CPU prom device tree node(s).\n", cpu_ctr);
};
+ prom_node_cpu = cpu_nds[0];
-#ifdef DEBUG_PROBING
- printk("String address for d_type: 0x%x\n", (unsigned int) str);
- printk("str[0] = %c str[1] = %c str[2] = %c \n", str[0], str[1], str[2]);
-#endif
-
- str = get_str_from_prom(nd, "name", promstr_buf);
-
-#ifdef DEBUG_PROBING
- printk("String address for name: 0x%x\n", (unsigned int) str);
- printk("str[0] = %c str[1] = %c str[2] = %c \n", str[0], str[1], str[2]);
-#endif
-
- printk("Name: %s \n", str);
-
- first_descent = nd = node_get_child(nd);
-
+ linux_num_cpus = cpu_ctr;
+ for(i=0; i<cpu_ctr; i++) {
+ prom_getstring(cpu_nds[i], "name", node_str, sizeof(node_str));
+ printk("cpu%d: %s \n", i, node_str);
+ }
/* Ok, here will go a call to each specific device probe. We can
* call these now that we have the 'root' node and the child of
@@ -404,29 +516,11 @@
*/
probe_cpu();
- probe_vac();
- probe_mmu();
- phys_bytes_of_ram = probe_memory();
-
- printk("Physical Memory: %d bytes\n", (int) phys_bytes_of_ram);
- for(i=0; sp_banks[i].num_bytes != 0; i++) {
- printk("Bank %d: base 0x%x bytes %d\n", i,
- (unsigned int) sp_banks[i].base_addr,
- (int) sp_banks[i].num_bytes);
- end_of_phys_memory = sp_banks[i].base_addr + sp_banks[i].num_bytes;
- }
-
- printk("PROM Root Child Node: 0x%x Name: %s \n", nd,
- get_str_from_prom(nd, "name", promstr_buf));
+ probe_auxio();
+ if(sparc_cpu_model == sun4c) probe_vac();
+ if(sparc_cpu_model != sun4c) probe_mbus(); /* Are MBUS's relevant on sun4c's? */
- while((nd = node_get_sibling(nd)) != 0) {
- printk("Node: 0x%x Name: %s", nd,
- get_str_from_prom(nd, "name", promstr_buf));
- printk("\n");
- };
-
- printk("\nProbing SBUS:\n");
- probe_sbus(first_descent);
+ mem_start = probe_sbus(prom_getchild(prom_root_node), mem_start);
- return;
+ return mem_start;
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov
with Sam's (original) version of this