prom.c 3.7 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166
/* Prom access routines for the sun3x */

#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/tty.h>
#include <linux/console.h>
#include <linux/init.h>
#include <linux/mm.h>
#include <linux/string.h>

#include <asm/page.h>
#include <asm/pgtable.h>
#include <asm/bootinfo.h>
#include <asm/setup.h>
#include <asm/traps.h>
#include <asm/sun3xprom.h>
#include <asm/idprom.h>
#include <asm/segment.h>
#include <asm/sun3ints.h>
#include <asm/openprom.h>
#include <asm/machines.h>

void (*sun3x_putchar)(int);
int (*sun3x_getchar)(void);
int (*sun3x_mayget)(void);
int (*sun3x_mayput)(int);
void (*sun3x_prom_reboot)(void);
e_vector sun3x_prom_abort;
struct linux_romvec *romvec;

/* prom vector table */
e_vector *sun3x_prom_vbr;

/* Handle returning to the prom */
void sun3x_halt(void)
{
    unsigned long flags;

    /* Disable interrupts while we mess with things */
    local_irq_save(flags);

    /* Restore prom vbr */
    __asm__ volatile ("movec %0,%%vbr" : : "r" ((void*)sun3x_prom_vbr));

    /* Restore prom NMI clock */
//    sun3x_disable_intreg(5);
    sun3_enable_irq(7);

    /* Let 'er rip */
    __asm__ volatile ("trap #14" : : );

    /* Restore everything */
    sun3_disable_irq(7);
    sun3_enable_irq(5);

    __asm__ volatile ("movec %0,%%vbr" : : "r" ((void*)vectors));
    local_irq_restore(flags);
}

void sun3x_reboot(void)
{
    /* This never returns, don't bother saving things */
    local_irq_disable();

    /* Restore prom vbr */
    __asm__ volatile ("movec %0,%%vbr" : : "r" ((void*)sun3x_prom_vbr));

    /* Restore prom NMI clock */
    sun3_disable_irq(5);
    sun3_enable_irq(7);

    /* Let 'er rip */
    (*romvec->pv_reboot)("vmlinux");
}

extern char m68k_debug_device[];

static void sun3x_prom_write(struct console *co, const char *s,
                             unsigned int count)
{
    while (count--) {
        if (*s == '\n')
            sun3x_putchar('\r');
        sun3x_putchar(*s++);
    }
}

/* debug console - write-only */

static struct console sun3x_debug = {
	.name  =	"debug",
	.write =	sun3x_prom_write,
	.flags =	CON_PRINTBUFFER,
	.index =	-1,
};

void sun3x_prom_init(void)
{
    /* Read the vector table */

    sun3x_putchar = *(void (**)(int)) (SUN3X_P_PUTCHAR);
    sun3x_getchar = *(int (**)(void)) (SUN3X_P_GETCHAR);
    sun3x_mayget = *(int (**)(void))  (SUN3X_P_MAYGET);
    sun3x_mayput = *(int (**)(int))   (SUN3X_P_MAYPUT);
    sun3x_prom_reboot = *(void (**)(void)) (SUN3X_P_REBOOT);
    sun3x_prom_abort = *(e_vector *)  (SUN3X_P_ABORT);
    romvec = (struct linux_romvec *)SUN3X_PROM_BASE;

    idprom_init();

    if(!((idprom->id_machtype & SM_ARCH_MASK) == SM_SUN3X)) {
	    printk("Warning: machine reports strange type %02x\n",
		   idprom->id_machtype);
	    printk("Pretending it's a 3/80, but very afraid...\n");
	    idprom->id_machtype = SM_SUN3X | SM_3_80;
    }

    /* point trap #14 at abort.
     * XXX this is futile since we restore the vbr first - oops
     */
    vectors[VEC_TRAP14] = sun3x_prom_abort;

    /* If debug=prom was specified, start the debug console */

    if (!strcmp(m68k_debug_device, "prom"))
        register_console(&sun3x_debug);


}

/* some prom functions to export */
int prom_getintdefault(int node, char *property, int deflt)
{
	return deflt;
}

int prom_getbool (int node, char *prop)
{
	return 1;
}

void prom_printf(char *fmt, ...)
{

}

void prom_halt (void)
{
	sun3x_halt();
}

/* 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;

	/* make a copy of the idprom structure */
	for(i = 0; i < num_bytes; i++)
		idbuf[i] = ((char *)SUN3X_IDPROM)[i];

        return idbuf[0];
}