Пример #1
0
void __init auxio_power_probe(void)
{
	struct linux_prom_registers regs;
	int node;
	struct resource r;

	/* Attempt to find the sun4m power control node. */
	node = prom_getchild(prom_root_node);
	node = prom_searchsiblings(node, "obio");
	node = prom_getchild(node);
	node = prom_searchsiblings(node, "power");
	if (node == 0 || node == -1)
		return;

	/* Map the power control register. */
	if (prom_getproperty(node, "reg", (char *)&regs, sizeof(regs)) <= 0)
		return;
	prom_apply_obio_ranges(&regs, 1);
	memset(&r, 0, sizeof(r));
	r.flags = regs.which_io & 0xF;
	r.start = regs.phys_addr;
	r.end = regs.phys_addr + regs.reg_size - 1;
	auxio_power_register = (unsigned char *) of_ioremap(&r, 0,
	    regs.reg_size, "auxpower");

	/* Display a quick message on the console. */
	if (auxio_power_register)
		printk(KERN_INFO "Power off control detected.\n");
}
void __init auxio_power_probe(void)
{
	struct linux_prom_registers regs;
	phandle node;
	struct resource r;

	
	node = prom_getchild(prom_root_node);
	node = prom_searchsiblings(node, "obio");
	node = prom_getchild(node);
	node = prom_searchsiblings(node, "power");
	if (node == 0 || (s32)node == -1)
		return;

	
	if (prom_getproperty(node, "reg", (char *)&regs, sizeof(regs)) <= 0)
		return;
	prom_apply_obio_ranges(&regs, 1);
	memset(&r, 0, sizeof(r));
	r.flags = regs.which_io & 0xF;
	r.start = regs.phys_addr;
	r.end = regs.phys_addr + regs.reg_size - 1;
	auxio_power_register = (unsigned char *) of_ioremap(&r, 0,
	    regs.reg_size, "auxpower");

	
	if (auxio_power_register)
		printk(KERN_INFO "Power off control detected.\n");
}
Пример #3
0
static int __init ts102_uctrl_init(void)
{
	struct uctrl_driver *driver = &drv;
	int len, i;
	struct linux_prom_irqs tmp_irq[2];
        unsigned int vaddr[2] = { 0, 0 };
	int tmpnode, uctrlnode = prom_getchild(prom_root_node);
	int err;

	tmpnode = prom_searchsiblings(uctrlnode, "obio");

	if (tmpnode)
	  uctrlnode = prom_getchild(tmpnode);

	uctrlnode = prom_searchsiblings(uctrlnode, "uctrl");

	if (!uctrlnode)
		return -ENODEV;

	/* the prom mapped it for us */
	len = prom_getproperty(uctrlnode, "address", (void *) vaddr,
			       sizeof(vaddr));
	driver->regs = (struct uctrl_regs *)vaddr[0];

	len = prom_getproperty(uctrlnode, "intr", (char *) tmp_irq,
			       sizeof(tmp_irq));

	/* Flush device */
	READUCTLDATA(len);

	if(!driver->irq) 
		driver->irq = tmp_irq[0].pri;

	err = request_irq(driver->irq, uctrl_interrupt, 0, "uctrl", driver);
	if (err) {
		printk("%s: unable to register irq %d\n",
		       __FUNCTION__, driver->irq);
		return err;
	}

	if (misc_register(&uctrl_dev)) {
		printk("%s: unable to get misc minor %d\n",
		       __FUNCTION__, uctrl_dev.minor);
		free_irq(driver->irq, driver);
		return -ENODEV;
	}

	driver->regs->uctrl_intr = UCTRL_INTR_RXNE_REQ|UCTRL_INTR_RXNE_MSK;
	printk("uctrl: 0x%p (irq %d)\n", driver->regs, driver->irq);
	uctrl_get_event_status();
	uctrl_get_external_status();
        return 0;
}
Пример #4
0
void __init auxio_probe(void)
{
	int node, auxio_nd;
	struct linux_prom_registers auxregs[1];
	struct resource r;

	switch (sparc_cpu_model) {
	case sun4d:
	case sun4:
		auxio_register = 0;
		return;
	default:
		break;
	}
	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) {
#ifdef CONFIG_PCI
			/* There may be auxio on Ebus */
			auxio_register = 0;
			return;
#else
			if(prom_searchsiblings(node, "leds")) {
				/* VME chassis sun4m machine, no auxio exists. */
				auxio_register = 0;
				return;
			}
			prom_printf("Cannot find auxio node, cannot continue...\n");
			prom_halt();
#endif
		}
	}
	prom_getproperty(auxio_nd, "reg", (char *) auxregs, sizeof(auxregs));
	prom_apply_obio_ranges(auxregs, 0x1);
	/* Map the register both read and write */
	r.flags = auxregs[0].which_io & 0xF;
	r.start = auxregs[0].phys_addr;
	r.end = auxregs[0].phys_addr + auxregs[0].reg_size - 1;
	auxio_register = (unsigned char *) sbus_ioremap(&r, 0,
	    auxregs[0].reg_size, "auxio");
	/* Fix the address on sun4m and sun4c. */
	if((((unsigned long) auxregs[0].phys_addr) & 3) == 3 ||
	   sparc_cpu_model == sun4c)
		auxio_register = (unsigned char *) ((int)auxio_register | 3);

	TURN_ON_LED;
}
void __init auxio_probe(void)
{
	phandle node, auxio_nd;
	struct linux_prom_registers auxregs[1];
	struct resource r;

	switch (sparc_cpu_model) {
	case sparc_leon:
	case sun4d:
	case sun4:
		return;
	default:
		break;
	}
	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) {
#ifdef CONFIG_PCI
			
			return;
#else
			if(prom_searchsiblings(node, "leds")) {
				
				return;
			}
			prom_printf("Cannot find auxio node, cannot continue...\n");
			prom_halt();
#endif
		}
	}
	if(prom_getproperty(auxio_nd, "reg", (char *) auxregs, sizeof(auxregs)) <= 0)
		return;
	prom_apply_obio_ranges(auxregs, 0x1);
	
	r.flags = auxregs[0].which_io & 0xF;
	r.start = auxregs[0].phys_addr;
	r.end = auxregs[0].phys_addr + auxregs[0].reg_size - 1;
	auxio_register = of_ioremap(&r, 0, auxregs[0].reg_size, "auxio");
	
	if((((unsigned long) auxregs[0].phys_addr) & 3) == 3 ||
	   sparc_cpu_model == sun4c)
		auxio_register += (3 - ((unsigned long)auxio_register & 3));

	set_auxio(AUXIO_LED, 0);
}
Пример #6
0
static int pci_controller_scan(int (*handler)(char *, int, int))
{
	char namebuf[64];
	int node;
	int count = 0;

	node = prom_getchild(prom_root_node);
	while ((node = prom_searchsiblings(node, "pci")) != 0) {
		int len;

		if ((len = prom_getproperty(node, "model", namebuf, sizeof(namebuf))) > 0 ||
		    (len = prom_getproperty(node, "compatible", namebuf, sizeof(namebuf))) > 0) {
			int item_len = 0;

			/* Our value may be a multi-valued string in the
			 * case of some compatible properties. For sanity,
			 * only try the first one. */

			while (namebuf[item_len] && len) {
				len--;
				item_len++;
			}

			if (handler(namebuf, item_len, node))
				count++;
		}

		node = prom_getsibling(node);
		if (!node)
			break;
	}

	return count;
}
Пример #7
0
Файл: pci.c Проект: nhanh0/hah
/* Find each controller in the system, attach and initialize
 * software state structure for each and link into the
 * pci_controller_root.  Setup the controller enough such
 * that bus scanning can be done.
 */
static void pci_controller_probe(void)
{
	char namebuf[16];
	int node;

	printk("PCI: Probing for controllers.\n");
	node = prom_getchild(prom_root_node);
	while ((node = prom_searchsiblings(node, "pci")) != 0) {
		int len;

		len = prom_getproperty(node, "model",
				       namebuf, sizeof(namebuf));
		if (len > 0)
			pci_controller_init(namebuf, len, node);
		else {
			len = prom_getproperty(node, "compatible",
					       namebuf, sizeof(namebuf));
			if (len > 0)
				pci_controller_init(namebuf, len, node);
		}
		node = prom_getsibling(node);
		if (!node)
			break;
	}
}
Пример #8
0
int prom_finddevice(char *name)
{
	char nbuf[128];
	char *s = name, *d;
	int node = prom_root_node, node2;
	unsigned int which_io, phys_addr;
	struct linux_prom_registers reg[PROMREG_MAX];

	while (*s++) {
		if (!*s) return node; /* path '.../' is legal */
		node = prom_getchild(node);

		for (d = nbuf; *s != 0 && *s != '@' && *s != '/';)
			*d++ = *s++;
		*d = 0;
		
		node = prom_searchsiblings(node, nbuf);
		if (!node)
			return 0;

		if (*s == '@') {
			if (isxdigit(s[1]) && s[2] == ',') {
				which_io = simple_strtoul(s+1, NULL, 16);
				phys_addr = simple_strtoul(s+3, &d, 16);
				if (d != s + 3 && (!*d || *d == '/')
				    && d <= s + 3 + 8) {
					node2 = node;
					while (node2 && node2 != -1) {
						if (prom_getproperty (node2, "reg", (char *)reg, sizeof (reg)) > 0) {
							if (which_io == reg[0].which_io && phys_addr == reg[0].phys_addr) {
								node = node2;
								break;
							}
						}
						node2 = prom_getsibling(node2);
						if (!node2 || node2 == -1)
							break;
						node2 = prom_searchsiblings(prom_getsibling(node2), nbuf);
					}
				}
			}
			while (*s != 0 && *s != '/') s++;
		}
	}
	return node;
}
Пример #9
0
static inline int d7s_obpflipped(void)
{
	int opt_node;

	opt_node = prom_getchild(prom_root_node);
	opt_node = prom_searchsiblings(opt_node, "options");
	return ((-1 != prom_getintdefault(opt_node, "d7s-flipped?", -1)) ? 0 : 1);
}
Пример #10
0
void
prom_ranges_init(void)
{
	int node, obio_node, sbus_node;
	int success;

	num_obio_ranges = 0;
	num_sbus_ranges = 0;

	/* Check for obio and sbus ranges. */
	node = prom_getchild(prom_root_node);
	obio_node = prom_searchsiblings(node, "obio");
	sbus_node = prom_searchsiblings(node, "iommu");
	if(sbus_node) {
		sbus_node = prom_getchild(sbus_node);
		sbus_node = prom_searchsiblings(sbus_node, "sbus");
	}

	if(obio_node) {
		success = prom_getproperty(obio_node, "ranges",
					   (char *) promlib_obio_ranges,
					   sizeof(promlib_obio_ranges));
		if(success != -1)
			num_obio_ranges = (success/sizeof(struct linux_prom_ranges));
	}

	if(sbus_node) {
		success = prom_getproperty(sbus_node, "ranges",
					   (char *) promlib_sbus_ranges,
					   sizeof(promlib_sbus_ranges));
		if(success != -1)
			num_sbus_ranges = (success/sizeof(struct linux_prom_ranges));
	}

	if(num_obio_ranges || num_sbus_ranges)
		prom_printf("PROMLIB: obio_ranges %d sbus_ranges %d\n",
			    num_obio_ranges, num_sbus_ranges);

	return;
}
Пример #11
0
__initfunc(void auxio_power_probe(void))
{
	struct linux_prom_registers regs;
	int node;

	/* Attempt to find the sun4m power control node. */
	node = prom_getchild(prom_root_node);
	node = prom_searchsiblings(node, "obio");
	node = prom_getchild(node);
	node = prom_searchsiblings(node, "power");
	if (node == 0 || node == -1)
		return;

	/* Map the power control register. */
	prom_getproperty(node, "reg", (char *)&regs, sizeof(regs));
	prom_apply_obio_ranges(&regs, 1);
	auxio_power_register = (volatile unsigned char *)
		sparc_alloc_io(regs.phys_addr, 0, regs.reg_size,
			       "power off control", regs.which_io, 0);

	/* Display a quick message on the console. */
	if (auxio_power_register)
		printk(KERN_INFO "Power off control detected.\n");
}
Пример #12
0
static char *serial(char *buffer)
{
	int node = prom_getchild(prom_root_node);
	int len;

	node = prom_searchsiblings(node, "options");
	*buffer = 0;
	len = prom_getproperty(node, "system-board-serial#", buffer, 256);
	if(len > 0)
		buffer[len] = 0;
	if (!*buffer)
		return "4512348717234";
	else
		return buffer;
}
Пример #13
0
static int __init prom_meminit_v2(void)
{
    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;
    }

    return num_ents;
}
Пример #14
0
void __init sun4c_init_IRQ(void)
{
	struct linux_prom_registers int_regs[2];
	int ie_node;

	if (ARCH_SUN4) {
		interrupt_enable = (char *)
		    ioremap(sun4_ie_physaddr, PAGE_SIZE);
	} else {
		struct resource phyres;

		ie_node = prom_searchsiblings (prom_getchild(prom_root_node),
				       	"interrupt-enable");
		if(ie_node == 0)
			panic("Cannot find /interrupt-enable node");

		/* Depending on the "address" property is bad news... */
		prom_getproperty(ie_node, "reg", (char *) int_regs, sizeof(int_regs));
		memset(&phyres, 0, sizeof(struct resource));
		phyres.flags = int_regs[0].which_io;
		phyres.start = int_regs[0].phys_addr;
		interrupt_enable = (char *) sbus_ioremap(&phyres, 0,
		    int_regs[0].reg_size, "sun4c_intr");
	}

	BTFIXUPSET_CALL(sbint_to_irq, sun4c_sbint_to_irq, BTFIXUPCALL_NORM);
	BTFIXUPSET_CALL(enable_irq, sun4c_enable_irq, BTFIXUPCALL_NORM);
	BTFIXUPSET_CALL(disable_irq, sun4c_disable_irq, BTFIXUPCALL_NORM);
	BTFIXUPSET_CALL(enable_pil_irq, sun4c_enable_irq, BTFIXUPCALL_NORM);
	BTFIXUPSET_CALL(disable_pil_irq, sun4c_disable_irq, BTFIXUPCALL_NORM);
	BTFIXUPSET_CALL(clear_clock_irq, sun4c_clear_clock_irq, BTFIXUPCALL_NORM);
	BTFIXUPSET_CALL(clear_profile_irq, sun4c_clear_profile_irq, BTFIXUPCALL_NOP);
	BTFIXUPSET_CALL(load_profile_irq, sun4c_load_profile_irq, BTFIXUPCALL_NOP);
	BTFIXUPSET_CALL(__irq_itoa, sun4m_irq_itoa, BTFIXUPCALL_NORM);
	sparc_init_timers = sun4c_init_timers;
#ifdef CONFIG_SMP
	BTFIXUPSET_CALL(set_cpu_int, sun4c_nop, BTFIXUPCALL_NOP);
	BTFIXUPSET_CALL(clear_cpu_int, sun4c_nop, BTFIXUPCALL_NOP);
	BTFIXUPSET_CALL(set_irq_udt, sun4c_nop, BTFIXUPCALL_NOP);
#endif
	*interrupt_enable = (SUN4C_INT_ENABLE);
	/* Cannot enable interrupts until OBP ticker is disabled. */
}
Пример #15
0
static int __init openprom_init(void)
{
	int error;

	error = misc_register(&openprom_dev);
	if (error) {
		printk(KERN_ERR "openprom: unable to get misc minor\n");
		return error;
	}

	options_node = prom_getchild(prom_root_node);
	options_node = prom_searchsiblings(options_node,"options");

	if (options_node == 0 || options_node == -1) {
		printk(KERN_ERR "openprom: unable to find options node\n");
		misc_deregister(&openprom_dev);
		return -EIO;
	}

	return 0;
}
Пример #16
0
const char *promcon_startup(void)
{
	const char *display_desc = "PROM";
	int node;
	char buf[40];
	
	node = prom_getchild(prom_root_node);
	node = prom_searchsiblings(node, "options");
	if (prom_getproperty(node,  "screen-#columns", buf, 40) != -1) {
		pw = simple_strtoul(buf, NULL, 0);
		if (pw < 10 || pw > 256)
			pw = 80;
		pw--;
	}
	if (prom_getproperty(node,  "screen-#rows", buf, 40) != -1) {
		ph = simple_strtoul(buf, NULL, 0);
		if (ph < 10 || ph > 256)
			ph = 34;
		ph--;
	}
	promcon_puts("\033[H\033[J", 6);
	return display_desc;
}
Пример #17
0
__initfunc(int sun_kbd_init(void))
{
	int i, opt_node;
	struct kbd_struct kbd0;
	extern struct tty_driver console_driver;

	kbd0.ledflagstate = kbd0.default_ledflagstate = KBD_DEFLEDS;
	kbd0.ledmode = LED_SHOW_FLAGS;
	kbd0.lockstate = KBD_DEFLOCK;
	kbd0.slockstate = 0;
	kbd0.modeflags = KBD_DEFMODE;
	kbd0.kbdmode = VC_XLATE;
 
	for (i = 0 ; i < MAX_NR_CONSOLES ; i++)
		kbd_table[i] = kbd0;

	ttytab = console_driver.table;

	kd_mksound = sunkbd_kd_mksound;

	/* XXX Check keyboard-click? property in 'options' PROM node XXX */
	if(sparc_cpu_model != sun4) {
		opt_node = prom_getchild(prom_root_node);
		opt_node = prom_searchsiblings(opt_node, "options");
		i = prom_getintdefault(opt_node, "keyboard-click?", -1);
		if(i != -1)
			sunkbd_clickp = 1;
		else
			sunkbd_clickp = 0;
	} else {
		sunkbd_clickp = 0;
	}
	init_bh(KEYBOARD_BH, kbd_bh);
	mark_bh(KEYBOARD_BH);
	return 0;
}
Пример #18
0
void
sunserial_console_termios(struct console *con)
{
	char mode[16], buf[16], *s;
	char *mode_prop = "ttyX-mode";
	char *cd_prop = "ttyX-ignore-cd";
	char *dtr_prop = "ttyX-rts-dtr-off";
	int baud, bits, stop, cflag;
	char parity;
	int carrier = 0;
	int rtsdtr = 1;
	int topnd, nd;

	if (!serial_console)
		return;

	if (serial_console == 1) {
		mode_prop[3] = 'a';
		cd_prop[3] = 'a';
		dtr_prop[3] = 'a';
	} else {
		mode_prop[3] = 'b';
		cd_prop[3] = 'b';
		dtr_prop[3] = 'b';
	}

	topnd = prom_getchild(prom_root_node);
	nd = prom_searchsiblings(topnd, "options");
	if (!nd) {
		strcpy(mode, "9600,8,n,1,-");
		goto no_options;
	}

	if (!prom_node_has_property(nd, mode_prop)) {
		strcpy(mode, "9600,8,n,1,-");
		goto no_options;
	}

	memset(mode, 0, sizeof(mode));
	prom_getstring(nd, mode_prop, mode, sizeof(mode));

	if (prom_node_has_property(nd, cd_prop)) {
		memset(buf, 0, sizeof(buf));
		prom_getstring(nd, cd_prop, buf, sizeof(buf));
		if (!strcmp(buf, "false"))
			carrier = 1;

		/* XXX: this is unused below. */
	}

	if (prom_node_has_property(nd, cd_prop)) {
		memset(buf, 0, sizeof(buf));
		prom_getstring(nd, cd_prop, buf, sizeof(buf));
		if (!strcmp(buf, "false"))
			rtsdtr = 0;

		/* XXX: this is unused below. */
	}

no_options:
	cflag = CREAD | HUPCL | CLOCAL;

	s = mode;
	baud = simple_strtoul(s, 0, 0);
	s = strchr(s, ',');
	bits = simple_strtoul(++s, 0, 0);
	s = strchr(s, ',');
	parity = *(++s);
	s = strchr(s, ',');
	stop = simple_strtoul(++s, 0, 0);
	s = strchr(s, ',');
	/* XXX handshake is not handled here. */

	switch (baud) {
		case 150: cflag |= B150; break;
		case 300: cflag |= B300; break;
		case 600: cflag |= B600; break;
		case 1200: cflag |= B1200; break;
		case 2400: cflag |= B2400; break;
		case 4800: cflag |= B4800; break;
		case 9600: cflag |= B9600; break;
		case 19200: cflag |= B19200; break;
		case 38400: cflag |= B38400; break;
		default: baud = 9600; cflag |= B9600; break;
	}

	switch (bits) {
		case 5: cflag |= CS5; break;
		case 6: cflag |= CS6; break;
		case 7: cflag |= CS7; break;
		case 8: cflag |= CS8; break;
		default: cflag |= CS8; break;
	}

	switch (parity) {
		case 'o': cflag |= (PARENB | PARODD); break;
		case 'e': cflag |= PARENB; break;
		case 'n': default: break;
	}

	switch (stop) {
		case 2: cflag |= CSTOPB; break;
		case 1: default: break;
	}

	con->cflag = cflag;
}
Пример #19
0
/* Probe for the mostek real time clock chip. */
static __inline__ void clock_probe(void)
{
	struct linux_prom_registers clk_reg[2];
	char model[128];
	register int node, cpuunit, bootbus;
	struct resource r;

	cpuunit = bootbus = 0;
	memset(&r, 0, sizeof(r));

	/* Determine the correct starting PROM node for the probe. */
	node = prom_getchild(prom_root_node);
	switch (sparc_cpu_model) {
	case sun4c:
		break;
	case sun4m:
		node = prom_getchild(prom_searchsiblings(node, "obio"));
		break;
	case sun4d:
		node = prom_getchild(bootbus = prom_searchsiblings(prom_getchild(cpuunit = prom_searchsiblings(node, "cpu-unit")), "bootbus"));
		break;
	default:
		prom_printf("CLOCK: Unsupported architecture!\n");
		prom_halt();
	}

	/* Find the PROM node describing the real time clock. */
	sp_clock_typ = MSTK_INVALID;
	node = prom_searchsiblings(node,"eeprom");
	if (!node) {
		prom_printf("CLOCK: No clock found!\n");
		prom_halt();
	}

	/* Get the model name and setup everything up. */
	model[0] = '\0';
	prom_getstring(node, "model", model, sizeof(model));
	if (strcmp(model, "mk48t02") == 0) {
		sp_clock_typ = MSTK48T02;
		if (prom_getproperty(node, "reg", (char *) clk_reg, sizeof(clk_reg)) == -1) {
			prom_printf("clock_probe: FAILED!\n");
			prom_halt();
		}
		if (sparc_cpu_model == sun4d)
			prom_apply_generic_ranges (bootbus, cpuunit, clk_reg, 1);
		else
			prom_apply_obio_ranges(clk_reg, 1);
		/* Map the clock register io area read-only */
		r.flags = clk_reg[0].which_io;
		r.start = clk_reg[0].phys_addr;
		mstk48t02_regs = sbus_ioremap(&r, 0,
		    sizeof(struct mostek48t02), "mk48t02");
		mstk48t08_regs = NULL;  /* To catch weirdness */
	} else if (strcmp(model, "mk48t08") == 0) {
		sp_clock_typ = MSTK48T08;
		if(prom_getproperty(node, "reg", (char *) clk_reg,
				    sizeof(clk_reg)) == -1) {
			prom_printf("clock_probe: FAILED!\n");
			prom_halt();
		}
		if (sparc_cpu_model == sun4d)
			prom_apply_generic_ranges (bootbus, cpuunit, clk_reg, 1);
		else
			prom_apply_obio_ranges(clk_reg, 1);
		/* Map the clock register io area read-only */
		/* XXX r/o attribute is somewhere in r.flags */
		r.flags = clk_reg[0].which_io;
		r.start = clk_reg[0].phys_addr;
		mstk48t08_regs = (struct mostek48t08 *) sbus_ioremap(&r, 0,
		    sizeof(struct mostek48t08), "mk48t08");

		mstk48t02_regs = &mstk48t08_regs->regs;
	} else {
		prom_printf("CLOCK: Unknown model name '%s'\n",model);
		prom_halt();
	}

	/* Report a low battery voltage condition. */
	if (has_low_battery())
		printk(KERN_CRIT "NVRAM: Low battery voltage!\n");

	/* Kick start the clock if it is completely stopped. */
	if (mostek_read(mstk48t02_regs + MOSTEK_SEC) & MSTK_STOP)
		kick_start_clock();
}
Пример #20
0
__initfunc(static void sun4m_init_timers(void (*counter_fn)(int, void *, struct pt_regs *)))
{
	int reg_count, irq, cpu;
	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) {
		prom_printf("Cannot find /obio/counter node\n");
		prom_halt();
	}
	reg_count = prom_getproperty(cnt_node, "reg",
				     (void *) cnt_regs, sizeof(cnt_regs));
	reg_count = (reg_count/sizeof(struct linux_prom_registers));
    
	/* Apply the obio ranges to the timer registers. */
	prom_apply_obio_ranges(cnt_regs, reg_count);
    
	cnt_regs[4].phys_addr = cnt_regs[reg_count-1].phys_addr;
	cnt_regs[4].reg_size = cnt_regs[reg_count-1].reg_size;
	cnt_regs[4].which_io = cnt_regs[reg_count-1].which_io;
	for(obio_node = 1; obio_node < 4; obio_node++) {
		cnt_regs[obio_node].phys_addr =
			cnt_regs[obio_node-1].phys_addr + PAGE_SIZE;
		cnt_regs[obio_node].reg_size = cnt_regs[obio_node-1].reg_size;
		cnt_regs[obio_node].which_io = cnt_regs[obio_node-1].which_io;
	}
    
	/* Map the per-cpu Counter registers. */
	sun4m_timers = sparc_alloc_io(cnt_regs[0].phys_addr, 0,
				      PAGE_SIZE*NCPUS, "counters_percpu",
				      cnt_regs[0].which_io, 0x0);
    
	/* Map the system Counter register. */
	sparc_alloc_io(cnt_regs[4].phys_addr, 0,
		       cnt_regs[4].reg_size,
		       "counters_system",
		       cnt_regs[4].which_io, 0x0);
    
	sun4m_timers->l10_timer_limit =  (((1000000/HZ) + 1) << 10);
	master_l10_counter = &sun4m_timers->l10_cur_count;
	master_l10_limit = &sun4m_timers->l10_timer_limit;

	irq = request_irq(TIMER_IRQ,
			  counter_fn,
			  (SA_INTERRUPT | SA_STATIC_ALLOC),
			  "timer", NULL);
	if (irq) {
		prom_printf("time_init: unable to attach IRQ%d\n",TIMER_IRQ);
		prom_halt();
	}
    
	if(linux_num_cpus > 1) {
		for(cpu = 0; cpu < 4; cpu++)
			sun4m_timers->cpu_timers[cpu].l14_timer_limit = 0;
		sun4m_interrupts->set = SUN4M_INT_E14;
	} else {
		sun4m_timers->cpu_timers[0].l14_timer_limit = 0;
	}
#ifdef __SMP__
	{
		unsigned long flags;
		extern unsigned long lvl14_save[4];
		struct tt_entry *trap_table = &sparc_ttable[SP_TRAP_IRQ1 + (14 - 1)];

		/* For SMP we use the level 14 ticker, however the bootup code
		 * has copied the firmwares level 14 vector into boot cpu's
		 * trap table, we must fix this now or we get squashed.
		 */
		__save_and_cli(flags);
		trap_table->inst_one = lvl14_save[0];
		trap_table->inst_two = lvl14_save[1];
		trap_table->inst_three = lvl14_save[2];
		trap_table->inst_four = lvl14_save[3];
		local_flush_cache_all();
		__restore_flags(flags);
	}
#endif
}
Пример #21
0
static void __init sun4m_init_timers(irqreturn_t (*counter_fn)(int, void *, struct pt_regs *))
{
	int reg_count, irq, cpu;
	struct linux_prom_registers cnt_regs[PROMREG_MAX];
	int obio_node, cnt_node;
	struct resource r;

	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) {
		prom_printf("Cannot find /obio/counter node\n");
		prom_halt();
	}
	reg_count = prom_getproperty(cnt_node, "reg",
				     (void *) cnt_regs, sizeof(cnt_regs));
	reg_count = (reg_count/sizeof(struct linux_prom_registers));
    
	/* Apply the obio ranges to the timer registers. */
	prom_apply_obio_ranges(cnt_regs, reg_count);
    
	cnt_regs[4].phys_addr = cnt_regs[reg_count-1].phys_addr;
	cnt_regs[4].reg_size = cnt_regs[reg_count-1].reg_size;
	cnt_regs[4].which_io = cnt_regs[reg_count-1].which_io;
	for(obio_node = 1; obio_node < 4; obio_node++) {
		cnt_regs[obio_node].phys_addr =
			cnt_regs[obio_node-1].phys_addr + PAGE_SIZE;
		cnt_regs[obio_node].reg_size = cnt_regs[obio_node-1].reg_size;
		cnt_regs[obio_node].which_io = cnt_regs[obio_node-1].which_io;
	}

	memset((char*)&r, 0, sizeof(struct resource));
	/* Map the per-cpu Counter registers. */
	r.flags = cnt_regs[0].which_io;
	r.start = cnt_regs[0].phys_addr;
	sun4m_timers = (struct sun4m_timer_regs *) sbus_ioremap(&r, 0,
	    PAGE_SIZE*SUN4M_NCPUS, "sun4m_cpu_cnt");
	/* Map the system Counter register. */
	/* XXX Here we expect consequent calls to yeld adjusent maps. */
	r.flags = cnt_regs[4].which_io;
	r.start = cnt_regs[4].phys_addr;
	sbus_ioremap(&r, 0, cnt_regs[4].reg_size, "sun4m_sys_cnt");

	sun4m_timers->l10_timer_limit =  (((1000000/HZ) + 1) << 10);
	master_l10_counter = &sun4m_timers->l10_cur_count;
	master_l10_limit = &sun4m_timers->l10_timer_limit;

	irq = request_irq(TIMER_IRQ,
			  counter_fn,
			  (IRQF_DISABLED | SA_STATIC_ALLOC),
			  "timer", NULL);
	if (irq) {
		prom_printf("time_init: unable to attach IRQ%d\n",TIMER_IRQ);
		prom_halt();
	}
   
	if (!cpu_find_by_instance(1, NULL, NULL)) {
		for(cpu = 0; cpu < 4; cpu++)
			sun4m_timers->cpu_timers[cpu].l14_timer_limit = 0;
		sun4m_interrupts->set = SUN4M_INT_E14;
	} else {
		sun4m_timers->cpu_timers[0].l14_timer_limit = 0;
	}
#ifdef CONFIG_SMP
	{
		unsigned long flags;
		extern unsigned long lvl14_save[4];
		struct tt_entry *trap_table = &sparc_ttable[SP_TRAP_IRQ1 + (14 - 1)];

		/* For SMP we use the level 14 ticker, however the bootup code
		 * has copied the firmwares level 14 vector into boot cpu's
		 * trap table, we must fix this now or we get squashed.
		 */
		local_irq_save(flags);
		trap_table->inst_one = lvl14_save[0];
		trap_table->inst_two = lvl14_save[1];
		trap_table->inst_three = lvl14_save[2];
		trap_table->inst_four = lvl14_save[3];
		local_flush_cache_all();
		local_irq_restore(flags);
	}
#endif
}
Пример #22
0
void __init sun4m_init_IRQ(void)
{
	int ie_node,i;
	struct linux_prom_registers int_regs[PROMREG_MAX];
	int num_regs;
	struct resource r;
	int mid;
    
	local_irq_disable();
	if((ie_node = prom_searchsiblings(prom_getchild(prom_root_node), "obio")) == 0 ||
	   (ie_node = prom_getchild (ie_node)) == 0 ||
	   (ie_node = prom_searchsiblings (ie_node, "interrupt")) == 0) {
		prom_printf("Cannot find /obio/interrupt node\n");
		prom_halt();
	}
	num_regs = prom_getproperty(ie_node, "reg", (char *) int_regs,
				    sizeof(int_regs));
	num_regs = (num_regs/sizeof(struct linux_prom_registers));
    
	/* Apply the obio ranges to these registers. */
	prom_apply_obio_ranges(int_regs, num_regs);
    
	int_regs[4].phys_addr = int_regs[num_regs-1].phys_addr;
	int_regs[4].reg_size = int_regs[num_regs-1].reg_size;
	int_regs[4].which_io = int_regs[num_regs-1].which_io;
	for(ie_node = 1; ie_node < 4; ie_node++) {
		int_regs[ie_node].phys_addr = int_regs[ie_node-1].phys_addr + PAGE_SIZE;
		int_regs[ie_node].reg_size = int_regs[ie_node-1].reg_size;
		int_regs[ie_node].which_io = int_regs[ie_node-1].which_io;
	}

	memset((char *)&r, 0, sizeof(struct resource));
	/* Map the interrupt registers for all possible cpus. */
	r.flags = int_regs[0].which_io;
	r.start = int_regs[0].phys_addr;
	sun4m_interrupts = (struct sun4m_intregs *) sbus_ioremap(&r, 0,
	    PAGE_SIZE*SUN4M_NCPUS, "interrupts_percpu");

	/* Map the system interrupt control registers. */
	r.flags = int_regs[4].which_io;
	r.start = int_regs[4].phys_addr;
	sbus_ioremap(&r, 0, int_regs[4].reg_size, "interrupts_system");

	sun4m_interrupts->set = ~SUN4M_INT_MASKALL;
	for (i = 0; !cpu_find_by_instance(i, NULL, &mid); i++)
		sun4m_interrupts->cpu_intregs[mid].clear = ~0x17fff;

	if (!cpu_find_by_instance(1, NULL, NULL)) {
		/* system wide interrupts go to cpu 0, this should always
		 * be safe because it is guaranteed to be fitted or OBP doesn't
		 * come up
		 *
		 * Not sure, but writing here on SLAVIO systems may puke
		 * so I don't do it unless there is more than 1 cpu.
		 */
		irq_rcvreg = (unsigned long *)
				&sun4m_interrupts->undirected_target;
		sun4m_interrupts->undirected_target = 0;
	}
	BTFIXUPSET_CALL(sbint_to_irq, sun4m_sbint_to_irq, BTFIXUPCALL_NORM);
	BTFIXUPSET_CALL(enable_irq, sun4m_enable_irq, BTFIXUPCALL_NORM);
	BTFIXUPSET_CALL(disable_irq, sun4m_disable_irq, BTFIXUPCALL_NORM);
	BTFIXUPSET_CALL(enable_pil_irq, sun4m_enable_pil_irq, BTFIXUPCALL_NORM);
	BTFIXUPSET_CALL(disable_pil_irq, sun4m_disable_pil_irq, BTFIXUPCALL_NORM);
	BTFIXUPSET_CALL(clear_clock_irq, sun4m_clear_clock_irq, BTFIXUPCALL_NORM);
	BTFIXUPSET_CALL(clear_profile_irq, sun4m_clear_profile_irq, BTFIXUPCALL_NORM);
	BTFIXUPSET_CALL(load_profile_irq, sun4m_load_profile_irq, BTFIXUPCALL_NORM);
	sparc_init_timers = sun4m_init_timers;
#ifdef CONFIG_SMP
	BTFIXUPSET_CALL(set_cpu_int, sun4m_send_ipi, BTFIXUPCALL_NORM);
	BTFIXUPSET_CALL(clear_cpu_int, sun4m_clear_ipi, BTFIXUPCALL_NORM);
	BTFIXUPSET_CALL(set_irq_udt, sun4m_set_udt, BTFIXUPCALL_NORM);
#endif
	/* Cannot enable interrupts until OBP ticker is disabled. */
}
Пример #23
0
/* Initialize the memory lists based upon the prom version. */
__initfunc(void 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. */
		/* First, the total physical descriptors. */
		for(mptr = (*(romvec->pv_v0mem.v0_totphys)), iter=0;
		    mptr; mptr=mptr->theres_more, iter++) {
			prom_phys_total[iter].start_adr = mptr->start_adr;
			prom_phys_total[iter].num_bytes = mptr->num_bytes;
			prom_phys_total[iter].theres_more = &prom_phys_total[iter+1];
		}
		prom_phys_total[iter-1].theres_more = 0x0;
		/* Second, the total prom taken descriptors. */
		for(mptr = (*(romvec->pv_v0mem.v0_prommap)), iter=0;
		    mptr; mptr=mptr->theres_more, iter++) {
			prom_prom_taken[iter].start_adr = mptr->start_adr;
			prom_prom_taken[iter].num_bytes = mptr->num_bytes;
			prom_prom_taken[iter].theres_more = &prom_prom_taken[iter+1];
		}
		prom_prom_taken[iter-1].theres_more = 0x0;
		/* Last, the available physical descriptors. */
		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];
		}
		prom_phys_avail[iter-1].theres_more = 0x0;
		/* Sort all the lists. */
		prom_sortmemlist(prom_phys_total);
		prom_sortmemlist(prom_prom_taken);
		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];
		}
		prom_phys_avail[iter-1].theres_more = 0x0;

		num_regs = prom_getproperty(node, "reg",
					    (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_total[iter].start_adr =
				(char *) prom_reg_memlist[iter].phys_addr;
			prom_phys_total[iter].num_bytes =
				(unsigned long) prom_reg_memlist[iter].reg_size;
			prom_phys_total[iter].theres_more =
				&prom_phys_total[iter+1];
		}
		prom_phys_total[iter-1].theres_more = 0x0;

		node = prom_getchild(prom_root_node);
		node = prom_searchsiblings(node, "virtual-memory");
		num_regs = prom_getproperty(node, "available",
					    (char *) prom_reg_memlist,
					    sizeof(prom_reg_memlist));
		num_regs = (num_regs/sizeof(struct linux_prom_registers));

		/* Convert available virtual areas to taken virtual
		 * areas.  First sort, then convert.
		 */
		for(iter=0; iter<num_regs; iter++) {
			prom_prom_taken[iter].start_adr =
				(char *) prom_reg_memlist[iter].phys_addr;
			prom_prom_taken[iter].num_bytes =
				(unsigned long) prom_reg_memlist[iter].reg_size;
			prom_prom_taken[iter].theres_more =
				&prom_phys_total[iter+1];
		}
		prom_prom_taken[iter-1].theres_more = 0x0;

		prom_sortmemlist(prom_prom_taken);

		/* Finally, convert. */
		for(iter=0; iter<num_regs; iter++) {
			prom_prom_taken[iter].start_adr =
				prom_prom_taken[iter].start_adr +
					prom_prom_taken[iter].num_bytes;
			prom_prom_taken[iter].num_bytes =
				prom_prom_taken[iter+1].start_adr -
					prom_prom_taken[iter].start_adr;
		}
		prom_prom_taken[iter-1].num_bytes =
			0xffffffff - (unsigned long) prom_prom_taken[iter-1].start_adr;

		/* Sort the other two lists. */
		prom_sortmemlist(prom_phys_total);
		prom_sortmemlist(prom_phys_avail);
		break;

	case PROM_SUN4:
#ifdef CONFIG_SUN4	
		/* how simple :) */
		prom_phys_total[0].start_adr = 0x0;
		prom_phys_total[0].num_bytes = *(sun4_romvec->memorysize);
		prom_phys_total[0].theres_more = 0x0;
		prom_prom_taken[0].start_adr = 0x0; 
		prom_prom_taken[0].num_bytes = 0x0;
		prom_prom_taken[0].theres_more = 0x0;
		prom_phys_avail[0].start_adr = 0x0;
		prom_phys_avail[0].num_bytes = *(sun4_romvec->memoryavail);
		prom_phys_avail[0].theres_more = 0x0;
#endif
		break;

        case PROM_AP1000:
#if CONFIG_AP1000
		/* really simple memory map */
		prom_phys_total[0].start_adr = 0x00000000;
		prom_phys_total[0].num_bytes = ap_memory_size();
		prom_phys_total[0].theres_more = 0x0;
		prom_prom_taken[0].start_adr = 0x00000000; 
		prom_prom_taken[0].num_bytes = 0x00000000;
		prom_prom_taken[0].theres_more = 0x0;
		prom_phys_avail[0].start_adr = 0x00000000;
		prom_phys_avail[0].num_bytes = prom_phys_total[0].num_bytes;
		prom_phys_avail[0].theres_more = 0x0;
#endif
	default:
		break;
	};

	/* Link all the lists into the top-level descriptor. */
	prom_memlist.v0_totphys=&prom_ptot_ptr;
	prom_memlist.v0_prommap=&prom_ptak_ptr;
	prom_memlist.v0_available=&prom_pavl_ptr;

	return;
}
Пример #24
0
__initfunc(void pcic_probe(void))
{
	struct linux_prom_registers regs[PROMREG_MAX];
	struct linux_pbm_info* pbm;
	char namebuf[64];
	int node;
	int err;

	if (pcibios_present()) {
		prom_printf("PCIC: called twice!\n");
		prom_halt();
	}

	node = prom_getchild (prom_root_node);
	node = prom_searchsiblings (node, "pci");
	if (node == 0)
		return;
	/*
	 * Map in PCIC register set, config space, and IO base
	 */
	err = prom_getproperty(node, "reg", (char*)regs, sizeof(regs));
	if (err == 0 || err == -1) {
		prom_printf("PCIC: Error, cannot get PCIC registers "
			    "from PROM.\n");
		prom_halt();
	}
	
	pcic = &PCIC;

	pcic->pcic_regs = (unsigned long)sparc_alloc_io(regs[0].phys_addr, NULL,
					      regs[0].reg_size,
					      "PCIC Registers", 0, 0);
	if (!pcic->pcic_regs) {
		prom_printf("PCIC: Error, cannot map PCIC registers.\n");
		prom_halt();
	}

	pcic->pcic_io_phys = regs[1].phys_addr;
	pcic->pcic_io = (unsigned long)sparc_alloc_io(regs[1].phys_addr, NULL,
					    regs[1].reg_size,
					    "PCIC IO Base", 0, 0);
	if (pcic->pcic_io == 0UL) {
		prom_printf("PCIC: Error, cannot map PCIC IO Base.\n");
		prom_halt();
	}

	pcic->pcic_config_space_addr =
			(unsigned long)sparc_alloc_io (regs[2].phys_addr, NULL,
					     regs[2].reg_size * 2,
					     "PCI Config Space Address", 0, 0);
	if (pcic->pcic_config_space_addr == 0UL) {
		prom_printf("PCIC: Error, cannot map" 
			    "PCI Configuration Space Address.\n");
		prom_halt();
	}

	/*
	 * Docs say three least significant bits in address and data
	 * must be the same. Thus, we need adjust size of data.
	 */
	pcic->pcic_config_space_data =
			(unsigned long)sparc_alloc_io (regs[3].phys_addr, NULL,
					     regs[3].reg_size * 2,
					     "PCI Config Space Data", 0, 0);
	if (pcic->pcic_config_space_data == 0UL) {
		prom_printf("PCIC: Error, cannot map" 
			    "PCI Configuration Space Data.\n");
		prom_halt();
	}

	pbm = &pcic->pbm;
	pbm->prom_node = node;
	prom_getstring(node, "name", namebuf, sizeof(namebuf));
	strcpy(pbm->prom_name, namebuf);
}
Пример #25
0
void __init sbus_init(void)
{
	int nd, this_sbus, sbus_devs, topnd, iommund;
	unsigned int sbus_clock;
	struct sbus_bus *sbus;
	struct sbus_dev *this_dev;
	int num_sbus = 0;  /* How many did we find? */

#ifndef __sparc_v9__
	register_proc_sparc_ioport();
#endif

#ifdef CONFIG_SUN4
	return sun4_dvma_init();
#endif

	topnd = prom_getchild(prom_root_node);
	
	/* Finding the first sbus is a special case... */
	iommund = 0;
	if(sparc_cpu_model == sun4u) {
		nd = prom_searchsiblings(topnd, "sbus");
		if(nd == 0) {
#ifdef CONFIG_PCI
			if (!pcibios_present()) {	
				prom_printf("Neither SBUS nor PCI found.\n");
				prom_halt();
			} else {
#ifdef __sparc_v9__
				firetruck_init();
#endif
			}
			return;
#else
			prom_printf("YEEE, UltraSparc sbus not found\n");
			prom_halt();
#endif
		}
	} else 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) {
#ifdef CONFIG_PCI
                        if (!pcibios_present()) {       
                                prom_printf("Neither SBUS nor PCI found.\n");
                                prom_halt();
                        }
                        return;
#else
			/* No reason to run further - the data access trap will occur. */
			panic("sbus not found");
#endif
		}
	}

	/* Ok, we've found the first one, allocate first SBus struct
	 * and place in chain.
	 */
	sbus = sbus_root = kmalloc(sizeof(struct sbus_bus), GFP_ATOMIC);
	sbus->next = NULL;
	sbus->prom_node = nd;
	this_sbus = nd;

	if(iommund && sparc_cpu_model != sun4u && sparc_cpu_model != sun4d)
		iommu_init(iommund, sbus);

	/* Loop until we find no more SBUS's */
	while(this_sbus) {
#ifdef __sparc_v9__						  
		/* IOMMU hides inside SBUS/SYSIO prom node on Ultra. */
		if(sparc_cpu_model == sun4u) {
			extern void sbus_iommu_init(int prom_node, struct sbus_bus *sbus);

			sbus_iommu_init(this_sbus, sbus);
		}
#endif
#ifndef __sparc_v9__						  
		if (sparc_cpu_model == sun4d)
			iounit_init(this_sbus, iommund, sbus);
#endif						   
		printk("sbus%d: ", num_sbus);
		sbus_clock = prom_getint(this_sbus, "clock-frequency");
		if(sbus_clock == -1)
			sbus_clock = (25*1000*1000);
		printk("Clock %d.%d MHz\n", (int) ((sbus_clock/1000)/1000),
		       (int) (((sbus_clock/1000)%1000 != 0) ? 
			      (((sbus_clock/1000)%1000) + 1000) : 0));

		prom_getstring(this_sbus, "name",
			       sbus->prom_name, sizeof(sbus->prom_name));
		sbus->clock_freq = sbus_clock;
#ifndef __sparc_v9__		
		if (sparc_cpu_model == sun4d) {
			sbus->devid = prom_getint(iommund, "device-id");
			sbus->board = prom_getint(iommund, "board#");
		}
#endif
		
		sbus_bus_ranges_init(iommund, sbus);

		sbus_devs = prom_getchild(this_sbus);
		if (!sbus_devs) {
			sbus->devices = NULL;
			goto next_bus;
		}

		sbus->devices = kmalloc(sizeof(struct sbus_dev), GFP_ATOMIC);

		this_dev = sbus->devices;
		this_dev->next = NULL;

		this_dev->bus = sbus;
		this_dev->parent = NULL;
		fill_sbus_device(sbus_devs, this_dev);

		/* Should we traverse for children? */
		if(prom_getchild(sbus_devs)) {
			/* Allocate device node */
			this_dev->child = kmalloc(sizeof(struct sbus_dev),
						  GFP_ATOMIC);
			/* Fill it */
			this_dev->child->bus = sbus;
			this_dev->child->next = 0;
			fill_sbus_device(prom_getchild(sbus_devs),
					 this_dev->child);
			sbus_do_child_siblings(prom_getchild(sbus_devs),
					       this_dev->child,
					       this_dev,
					       sbus);
		} else {
			this_dev->child = NULL;
		}

		while((sbus_devs = prom_getsibling(sbus_devs)) != 0) {
			/* Allocate device node */
			this_dev->next = kmalloc(sizeof(struct sbus_dev),
						 GFP_ATOMIC);
			this_dev = this_dev->next;
			this_dev->next = NULL;

			/* Fill it */
			this_dev->bus = sbus;
			this_dev->parent = NULL;
			fill_sbus_device(sbus_devs, this_dev);

			/* Is there a child node hanging off of us? */
			if(prom_getchild(sbus_devs)) {
				/* Get new device struct */
				this_dev->child = kmalloc(sizeof(struct sbus_dev),
							  GFP_ATOMIC);
				/* Fill it */
				this_dev->child->bus = sbus;
				this_dev->child->next = 0;
				fill_sbus_device(prom_getchild(sbus_devs),
						 this_dev->child);
				sbus_do_child_siblings(prom_getchild(sbus_devs),
						       this_dev->child,
						       this_dev,
						       sbus);
			} else {
				this_dev->child = NULL;
			}
		}

		/* Walk all devices and apply parent ranges. */
		sbus_fixup_all_regs(sbus->devices);

		dvma_init(sbus);
	next_bus:
		num_sbus++;
		if(sparc_cpu_model == sun4u) {
			this_sbus = prom_getsibling(this_sbus);
			if(!this_sbus)
				break;
			this_sbus = prom_searchsiblings(this_sbus, "sbus");
		} else 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 = kmalloc(sizeof(struct sbus_bus), GFP_ATOMIC);
			sbus = sbus->next;
			sbus->next = NULL;
			sbus->prom_node = this_sbus;
		} else {
			break;
		}
	} /* while(this_sbus) */

	if (sparc_cpu_model == sun4d) {
		extern void sun4d_init_sbi_irq(void);
		sun4d_init_sbi_irq();
	}
	
	rs_init();

#ifdef __sparc_v9__
	if (sparc_cpu_model == sun4u) {
		firetruck_init();
	}
#endif
#ifdef CONFIG_SUN_AUXIO
	if (sparc_cpu_model == sun4u)
		auxio_probe ();
#endif
#ifdef __sparc_v9__
	if (sparc_cpu_model == sun4u) {
		extern void clock_probe(void);

		clock_probe();
	}
#endif
}