patch-2.1.16 linux/drivers/sbus/sbus.c
Next file: linux/drivers/scsi/Makefile
Previous file: linux/drivers/sbus/dvma.c
Back to the patch index
Back to the overall index
- Lines: 219
- Date:
Fri Dec 13 11:37:37 1996
- Orig file:
v2.1.15/linux/drivers/sbus/sbus.c
- Orig date:
Sun Apr 21 17:32:02 1996
diff -u --recursive --new-file v2.1.15/linux/drivers/sbus/sbus.c linux/drivers/sbus/sbus.c
@@ -5,6 +5,8 @@
#include <linux/kernel.h>
#include <linux/malloc.h>
+#include <linux/config.h>
+#include <linux/init.h>
#include <asm/system.h>
#include <asm/sbus.h>
@@ -19,6 +21,8 @@
static char lbuf[128];
+extern void prom_sbus_ranges_init (int, struct linux_sbus *);
+
/* Perhaps when I figure out more about the iommu we'll put a
* device registration routine here that probe_sbus() calls to
* setup the iommu for each Sbus.
@@ -30,8 +34,8 @@
*/
/* #define DEBUG_FILL */
-void
-fill_sbus_device(int nd, struct linux_sbus_device *sbus_dev)
+__initfunc(static void
+fill_sbus_device(int nd, struct linux_sbus_device *sbus_dev))
{
int grrr, len;
unsigned long dev_base_addr, base;
@@ -46,6 +50,8 @@
len = prom_getproperty(nd, "reg", (void *) sbus_dev->reg_addrs,
sizeof(sbus_dev->reg_addrs));
+ if(len == -1)
+ goto no_regs;
if(len%sizeof(struct linux_prom_registers)) {
prom_printf("WHOOPS: proplen for %s was %d, need multiple of %d\n",
sbus_dev->prom_name, len,
@@ -79,6 +85,7 @@
panic("sbus device register overflow");
}
+no_regs:
len = prom_getproperty(nd, "address", (void *) sbus_dev->sbus_vaddrs,
sizeof(sbus_dev->sbus_vaddrs));
if(len == -1) len=0;
@@ -130,12 +137,53 @@
* devices.
*/
-extern void sun_console_init(void);
+extern unsigned long sun_console_init(unsigned long);
extern unsigned long iommu_init(int iommu_node, unsigned long memstart,
unsigned long memend, struct linux_sbus *sbus);
+extern void iommu_sun4d_init(int sbi_node, struct linux_sbus *sbus);
+#ifdef CONFIG_SUN_OPENPROMIO
+extern int openprom_init(void);
+#endif
+#ifdef CONFIG_SUN_MOSTEK_RTC
+extern int rtc_init(void);
+#endif
+
+__initfunc(static unsigned long
+sbus_do_child_siblings(unsigned long memory_start, int start_node,
+ struct linux_sbus_device *child,
+ struct linux_sbus *sbus))
+{
+ struct linux_sbus_device *this_dev = child;
+ int this_node = start_node;
+
+ /* Child already filled in, just need to traverse siblings. */
+ while((this_node = prom_getsibling(this_node)) != 0) {
+ this_dev->next = (struct linux_sbus_device *) memory_start;
+ memory_start += sizeof(struct linux_sbus_device);
+ this_dev = this_dev->next;
+ this_dev->next = 0;
+
+ fill_sbus_device(this_node, this_dev);
+ this_dev->my_bus = sbus;
+
+ if(prom_getchild(this_node)) {
+ this_dev->child = (struct linux_sbus_device *) memory_start;
+ memory_start += sizeof(struct linux_sbus_device);
+ fill_sbus_device(prom_getchild(this_node), this_dev->child);
+ this_dev->child->my_bus = sbus;
+ memory_start = sbus_do_child_siblings(memory_start,
+ prom_getchild(this_node),
+ this_dev->child,
+ sbus);
+ } else {
+ this_dev->child = 0;
+ }
+ }
+ return memory_start;
+}
-unsigned long
-sbus_init(unsigned long memory_start, unsigned long memory_end)
+__initfunc(unsigned long
+sbus_init(unsigned long memory_start, unsigned long memory_end))
{
register int nd, this_sbus, sbus_devs, topnd, iommund;
unsigned int sbus_clock;
@@ -149,7 +197,13 @@
/* Finding the first sbus is a special case... */
iommund = 0;
- if((nd = prom_searchsiblings(topnd, "sbus")) == 0) {
+ if (sparc_cpu_model == sun4d) {
+ if((iommund = prom_searchsiblings(topnd, "io-unit")) == 0 ||
+ (nd = prom_getchild(iommund)) == 0 ||
+ (nd = prom_searchsiblings(nd, "sbi")) == 0) {
+ panic("sbi not found");
+ }
+ } else if((nd = prom_searchsiblings(topnd, "sbus")) == 0) {
if((iommund = prom_searchsiblings(topnd, "iommu")) == 0 ||
(nd = prom_getchild(iommund)) == 0 ||
(nd = prom_searchsiblings(nd, "sbus")) == 0) {
@@ -167,8 +221,12 @@
this_sbus=nd;
/* Have IOMMU will travel. XXX grrr - this should be per sbus... */
- if(iommund)
- memory_start = iommu_init(iommund, memory_start, memory_end, sbus);
+ if(iommund) {
+ if (sparc_cpu_model == sun4d)
+ iommu_sun4d_init(this_sbus, sbus);
+ else
+ memory_start = iommu_init(iommund, memory_start, memory_end, sbus);
+ }
/* Loop until we find no more SBUS's */
while(this_sbus) {
@@ -183,6 +241,8 @@
sbus->prom_node = this_sbus;
strcpy(sbus->prom_name, lbuf);
sbus->clock_freq = sbus_clock;
+
+ prom_sbus_ranges_init (iommund, sbus);
sbus_devs = prom_getchild(this_sbus);
@@ -196,14 +256,17 @@
this_dev->my_bus = sbus;
/* Should we traverse for children? */
- if(strcmp(this_dev->prom_name, "espdma")==0 ||
- strcmp(this_dev->prom_name, "ledma")==0) {
+ if(prom_getchild(sbus_devs)) {
/* Allocate device node */
this_dev->child = (struct linux_sbus_device *) memory_start;
memory_start += sizeof(struct linux_sbus_device);
/* Fill it */
fill_sbus_device(prom_getchild(sbus_devs), this_dev->child);
this_dev->child->my_bus = sbus;
+ memory_start = sbus_do_child_siblings(memory_start,
+ prom_getchild(sbus_devs),
+ this_dev->child,
+ sbus);
} else {
this_dev->child = 0;
}
@@ -220,8 +283,7 @@
this_dev->my_bus = sbus;
/* Is there a child node hanging off of us? */
- if(strcmp(this_dev->prom_name, "espdma")==0 ||
- strcmp(this_dev->prom_name, "ledma")==0) {
+ if(prom_getchild(sbus_devs)) {
/* Get new device struct */
this_dev->child =
(struct linux_sbus_device *) memory_start;
@@ -231,6 +293,11 @@
fill_sbus_device(prom_getchild(sbus_devs),
this_dev->child);
this_dev->child->my_bus = sbus;
+ memory_start = sbus_do_child_siblings(
+ memory_start,
+ prom_getchild(sbus_devs),
+ this_dev->child,
+ sbus);
} else {
this_dev->child = 0;
}
@@ -239,9 +306,17 @@
memory_start = dvma_init(sbus, memory_start);
num_sbus++;
- this_sbus = prom_getsibling(this_sbus);
- if(!this_sbus) break;
- this_sbus = prom_searchsiblings(this_sbus, "sbus");
+ if (sparc_cpu_model == sun4d) {
+ iommund = prom_getsibling(iommund);
+ if(!iommund) break;
+ iommund = prom_searchsiblings(iommund, "io-unit");
+ if(!iommund) break;
+ this_sbus = prom_searchsiblings(prom_getchild(iommund), "sbi");
+ } else {
+ this_sbus = prom_getsibling(this_sbus);
+ if(!this_sbus) break;
+ this_sbus = prom_searchsiblings(this_sbus, "sbus");
+ }
if(this_sbus) {
sbus->next = (struct linux_sbus *) memory_start;
memory_start += sizeof(struct linux_sbus);
@@ -251,6 +326,12 @@
break;
}
} /* while(this_sbus) */
- sun_console_init(); /* whee... */
+ memory_start = sun_console_init(memory_start); /* whee... */
+#ifdef CONFIG_SUN_OPENPROMIO
+ openprom_init();
+#endif
+#ifdef CONFIG_SUN_MOSTEK_RTC
+ rtc_init();
+#endif
return memory_start;
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov