diff options
Diffstat (limited to 'arch/m68k/sun3/prom')
-rw-r--r-- | arch/m68k/sun3/prom/Makefile | 7 | ||||
-rw-r--r-- | arch/m68k/sun3/prom/console.c | 174 | ||||
-rw-r--r-- | arch/m68k/sun3/prom/init.c | 89 | ||||
-rw-r--r-- | arch/m68k/sun3/prom/misc.c | 94 | ||||
-rw-r--r-- | arch/m68k/sun3/prom/printf.c | 61 |
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" (¤t_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" (¤t_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; +} |