aboutsummaryrefslogtreecommitdiffstats
path: root/arch/m68k/sun3/prom
diff options
context:
space:
mode:
Diffstat (limited to 'arch/m68k/sun3/prom')
-rw-r--r--arch/m68k/sun3/prom/Makefile7
-rw-r--r--arch/m68k/sun3/prom/console.c174
-rw-r--r--arch/m68k/sun3/prom/init.c89
-rw-r--r--arch/m68k/sun3/prom/misc.c94
-rw-r--r--arch/m68k/sun3/prom/printf.c61
5 files changed, 425 insertions, 0 deletions
diff --git a/arch/m68k/sun3/prom/Makefile b/arch/m68k/sun3/prom/Makefile
new file mode 100644
index 0000000..6e48ae2
--- /dev/null
+++ b/arch/m68k/sun3/prom/Makefile
@@ -0,0 +1,7 @@
+# $Id: Makefile,v 1.5 1995/11/25 00:59:48 davem Exp $
+# Makefile for the Sun Boot PROM interface library under
+# Linux.
+#
+
+obj-y := init.o console.o printf.o misc.o
+#bootstr.o init.o misc.o segment.o console.o printf.o
diff --git a/arch/m68k/sun3/prom/console.c b/arch/m68k/sun3/prom/console.c
new file mode 100644
index 0000000..52c1427
--- /dev/null
+++ b/arch/m68k/sun3/prom/console.c
@@ -0,0 +1,174 @@
+/* $Id: console.c,v 1.10 1996/12/18 06:46:54 tridge Exp $
+ * console.c: Routines that deal with sending and receiving IO
+ * to/from the current console device using the PROM.
+ *
+ * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
+ */
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <asm/openprom.h>
+#include <asm/oplib.h>
+#include <asm/system.h>
+#include <linux/string.h>
+
+/* Non blocking get character from console input device, returns -1
+ * if no input was taken. This can be used for polling.
+ */
+int
+prom_nbgetchar(void)
+{
+ int i = -1;
+ unsigned long flags;
+
+ local_irq_save(flags);
+ i = (*(romvec->pv_nbgetchar))();
+ local_irq_restore(flags);
+ return i; /* Ugh, we could spin forever on unsupported proms ;( */
+}
+
+/* Non blocking put character to console device, returns -1 if
+ * unsuccessful.
+ */
+int
+prom_nbputchar(char c)
+{
+ unsigned long flags;
+ int i = -1;
+
+ local_irq_save(flags);
+ i = (*(romvec->pv_nbputchar))(c);
+ local_irq_restore(flags);
+ return i; /* Ugh, we could spin forever on unsupported proms ;( */
+}
+
+/* Blocking version of get character routine above. */
+char
+prom_getchar(void)
+{
+ int character;
+ while((character = prom_nbgetchar()) == -1) ;
+ return (char) character;
+}
+
+/* Blocking version of put character routine above. */
+void
+prom_putchar(char c)
+{
+ while(prom_nbputchar(c) == -1) ;
+ return;
+}
+
+/* Query for input device type */
+#if 0
+enum prom_input_device
+prom_query_input_device()
+{
+ unsigned long flags;
+ int st_p;
+ char propb[64];
+ char *p;
+
+ switch(prom_vers) {
+ case PROM_V0:
+ case PROM_V2:
+ default:
+ switch(*romvec->pv_stdin) {
+ case PROMDEV_KBD: return PROMDEV_IKBD;
+ case PROMDEV_TTYA: return PROMDEV_ITTYA;
+ case PROMDEV_TTYB: return PROMDEV_ITTYB;
+ default:
+ return PROMDEV_I_UNK;
+ };
+ case PROM_V3:
+ case PROM_P1275:
+ local_irq_save(flags);
+ st_p = (*romvec->pv_v2devops.v2_inst2pkg)(*romvec->pv_v2bootargs.fd_stdin);
+ __asm__ __volatile__("ld [%0], %%g6\n\t" : :
+ "r" (&current_set[smp_processor_id()]) :
+ "memory");
+ local_irq_restore(flags);
+ if(prom_node_has_property(st_p, "keyboard"))
+ return PROMDEV_IKBD;
+ prom_getproperty(st_p, "device_type", propb, sizeof(propb));
+ if(strncmp(propb, "serial", sizeof("serial")))
+ return PROMDEV_I_UNK;
+ prom_getproperty(prom_root_node, "stdin-path", propb, sizeof(propb));
+ p = propb;
+ while(*p) p++; p -= 2;
+ if(p[0] == ':') {
+ if(p[1] == 'a')
+ return PROMDEV_ITTYA;
+ else if(p[1] == 'b')
+ return PROMDEV_ITTYB;
+ }
+ return PROMDEV_I_UNK;
+ case PROM_AP1000:
+ return PROMDEV_I_UNK;
+ };
+}
+#endif
+
+/* Query for output device type */
+
+#if 0
+enum prom_output_device
+prom_query_output_device()
+{
+ unsigned long flags;
+ int st_p;
+ char propb[64];
+ char *p;
+ int propl;
+
+ switch(prom_vers) {
+ case PROM_V0:
+ switch(*romvec->pv_stdin) {
+ case PROMDEV_SCREEN: return PROMDEV_OSCREEN;
+ case PROMDEV_TTYA: return PROMDEV_OTTYA;
+ case PROMDEV_TTYB: return PROMDEV_OTTYB;
+ };
+ break;
+ case PROM_V2:
+ case PROM_V3:
+ case PROM_P1275:
+ local_irq_save(flags);
+ st_p = (*romvec->pv_v2devops.v2_inst2pkg)(*romvec->pv_v2bootargs.fd_stdout);
+ __asm__ __volatile__("ld [%0], %%g6\n\t" : :
+ "r" (&current_set[smp_processor_id()]) :
+ "memory");
+ local_irq_restore(flags);
+ propl = prom_getproperty(st_p, "device_type", propb, sizeof(propb));
+ if (propl >= 0 && propl == sizeof("display") &&
+ strncmp("display", propb, sizeof("display")) == 0)
+ {
+ return PROMDEV_OSCREEN;
+ }
+ if(prom_vers == PROM_V3) {
+ if(strncmp("serial", propb, sizeof("serial")))
+ return PROMDEV_O_UNK;
+ prom_getproperty(prom_root_node, "stdout-path", propb, sizeof(propb));
+ p = propb;
+ while(*p) p++; p -= 2;
+ if(p[0]==':') {
+ if(p[1] == 'a')
+ return PROMDEV_OTTYA;
+ else if(p[1] == 'b')
+ return PROMDEV_OTTYB;
+ }
+ return PROMDEV_O_UNK;
+ } else {
+ /* This works on SS-2 (an early OpenFirmware) still. */
+ switch(*romvec->pv_stdin) {
+ case PROMDEV_TTYA: return PROMDEV_OTTYA;
+ case PROMDEV_TTYB: return PROMDEV_OTTYB;
+ };
+ }
+ break;
+ case PROM_AP1000:
+ return PROMDEV_I_UNK;
+ };
+ return PROMDEV_O_UNK;
+}
+#endif
diff --git a/arch/m68k/sun3/prom/init.c b/arch/m68k/sun3/prom/init.c
new file mode 100644
index 0000000..2e6ae56
--- /dev/null
+++ b/arch/m68k/sun3/prom/init.c
@@ -0,0 +1,89 @@
+/* $Id: init.c,v 1.9 1996/12/18 06:46:55 tridge Exp $
+ * init.c: Initialize internal variables used by the PROM
+ * library functions.
+ *
+ * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+
+#include <asm/openprom.h>
+#include <asm/oplib.h>
+
+struct linux_romvec *romvec;
+enum prom_major_version prom_vers;
+unsigned int prom_rev, prom_prev;
+
+/* The root node of the prom device tree. */
+int prom_root_node;
+
+/* Pointer to the device tree operations structure. */
+struct linux_nodeops *prom_nodeops;
+
+/* You must call prom_init() before you attempt to use any of the
+ * routines in the prom library. It returns 0 on success, 1 on
+ * failure. It gets passed the pointer to the PROM vector.
+ */
+
+extern void prom_meminit(void);
+extern void prom_ranges_init(void);
+
+void __init prom_init(struct linux_romvec *rp)
+{
+#ifdef CONFIG_AP1000
+ extern struct linux_romvec *ap_prom_init(void);
+ rp = ap_prom_init();
+#endif
+
+ romvec = rp;
+#ifndef CONFIG_SUN3
+ switch(romvec->pv_romvers) {
+ case 0:
+ prom_vers = PROM_V0;
+ break;
+ case 2:
+ prom_vers = PROM_V2;
+ break;
+ case 3:
+ prom_vers = PROM_V3;
+ break;
+ case 4:
+ prom_vers = PROM_P1275;
+ prom_printf("PROMLIB: Sun IEEE Prom not supported yet\n");
+ prom_halt();
+ break;
+ case 42: /* why not :-) */
+ prom_vers = PROM_AP1000;
+ break;
+
+ default:
+ prom_printf("PROMLIB: Bad PROM version %d\n",
+ romvec->pv_romvers);
+ prom_halt();
+ break;
+ };
+
+ prom_rev = romvec->pv_plugin_revision;
+ prom_prev = romvec->pv_printrev;
+ prom_nodeops = romvec->pv_nodeops;
+
+ prom_root_node = prom_getsibling(0);
+ if((prom_root_node == 0) || (prom_root_node == -1))
+ prom_halt();
+
+ if((((unsigned long) prom_nodeops) == 0) ||
+ (((unsigned long) prom_nodeops) == -1))
+ prom_halt();
+
+ prom_meminit();
+
+ prom_ranges_init();
+#endif
+// printk("PROMLIB: Sun Boot Prom Version %d Revision %d\n",
+// romvec->pv_romvers, prom_rev);
+
+ /* Initialization successful. */
+ return;
+}
diff --git a/arch/m68k/sun3/prom/misc.c b/arch/m68k/sun3/prom/misc.c
new file mode 100644
index 0000000..b88716f
--- /dev/null
+++ b/arch/m68k/sun3/prom/misc.c
@@ -0,0 +1,94 @@
+/* $Id: misc.c,v 1.15 1997/05/14 20:45:00 davem Exp $
+ * misc.c: Miscellaneous prom functions that don't belong
+ * anywhere else.
+ *
+ * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
+ */
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <asm/sun3-head.h>
+#include <asm/idprom.h>
+#include <asm/openprom.h>
+#include <asm/oplib.h>
+#include <asm/movs.h>
+
+/* Reset and reboot the machine with the command 'bcommand'. */
+void
+prom_reboot(char *bcommand)
+{
+ unsigned long flags;
+ local_irq_save(flags);
+ (*(romvec->pv_reboot))(bcommand);
+ local_irq_restore(flags);
+}
+
+/* Drop into the prom, with the chance to continue with the 'go'
+ * prom command.
+ */
+void
+prom_cmdline(void)
+{
+}
+
+/* Drop into the prom, but completely terminate the program.
+ * No chance of continuing.
+ */
+void
+prom_halt(void)
+{
+ unsigned long flags;
+again:
+ local_irq_save(flags);
+ (*(romvec->pv_halt))();
+ local_irq_restore(flags);
+ goto again; /* PROM is out to get me -DaveM */
+}
+
+typedef void (*sfunc_t)(void);
+
+/* Get the idprom and stuff it into buffer 'idbuf'. Returns the
+ * format type. 'num_bytes' is the number of bytes that your idbuf
+ * has space for. Returns 0xff on error.
+ */
+unsigned char
+prom_get_idprom(char *idbuf, int num_bytes)
+{
+ int i, oldsfc;
+ GET_SFC(oldsfc);
+ SET_SFC(FC_CONTROL);
+ for(i=0;i<num_bytes; i++)
+ {
+ /* There is a problem with the GET_CONTROL_BYTE
+ macro; defining the extra variable
+ gets around it.
+ */
+ int c;
+ GET_CONTROL_BYTE(SUN3_IDPROM_BASE + i, c);
+ idbuf[i] = c;
+ }
+ SET_SFC(oldsfc);
+ return idbuf[0];
+}
+
+/* Get the major prom version number. */
+int
+prom_version(void)
+{
+ return romvec->pv_romvers;
+}
+
+/* Get the prom plugin-revision. */
+int
+prom_getrev(void)
+{
+ return prom_rev;
+}
+
+/* Get the prom firmware print revision. */
+int
+prom_getprev(void)
+{
+ return prom_prev;
+}
diff --git a/arch/m68k/sun3/prom/printf.c b/arch/m68k/sun3/prom/printf.c
new file mode 100644
index 0000000..e6ee100
--- /dev/null
+++ b/arch/m68k/sun3/prom/printf.c
@@ -0,0 +1,61 @@
+/* $Id: printf.c,v 1.5 1996/04/04 16:31:07 tridge Exp $
+ * printf.c: Internal prom library printf facility.
+ *
+ * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
+ */
+
+/* This routine is internal to the prom library, no one else should know
+ * about or use it! It's simple and smelly anyway....
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+
+#include <asm/openprom.h>
+#include <asm/oplib.h>
+
+#ifdef CONFIG_KGDB
+extern int kgdb_initialized;
+#endif
+
+static char ppbuf[1024];
+
+void
+prom_printf(char *fmt, ...)
+{
+ va_list args;
+ char ch, *bptr;
+ int i;
+
+ va_start(args, fmt);
+
+#ifdef CONFIG_KGDB
+ ppbuf[0] = 'O';
+ i = vsprintf(ppbuf + 1, fmt, args) + 1;
+#else
+ i = vsprintf(ppbuf, fmt, args);
+#endif
+
+ bptr = ppbuf;
+
+#ifdef CONFIG_AP1000
+ ap_write(1,bptr,strlen(bptr));
+#else
+
+#ifdef CONFIG_KGDB
+ if (kgdb_initialized) {
+ printk("kgdb_initialized = %d\n", kgdb_initialized);
+ putpacket(bptr, 1);
+ } else
+#else
+ while((ch = *(bptr++)) != 0) {
+ if(ch == '\n')
+ prom_putchar('\r');
+
+ prom_putchar(ch);
+ }
+#endif
+#endif
+ va_end(args);
+ return;
+}