Merge branches 'release', 'asus', 'sony-laptop' and 'thinkpad' into release
[linux-2.6] / arch / sh / kernel / sh_bios.c
1 /*
2  *  linux/arch/sh/kernel/sh_bios.c
3  *  C interface for trapping into the standard LinuxSH BIOS.
4  *
5  *  Copyright (C) 2000 Greg Banks, Mitch Davis
6  *
7  */
8 #include <linux/module.h>
9 #include <asm/sh_bios.h>
10
11 #define BIOS_CALL_CONSOLE_WRITE         0
12 #define BIOS_CALL_READ_BLOCK            1
13 #define BIOS_CALL_ETH_NODE_ADDR         10
14 #define BIOS_CALL_SHUTDOWN              11
15 #define BIOS_CALL_CHAR_OUT              0x1f    /* TODO: hack */
16 #define BIOS_CALL_GDB_GET_MODE_PTR      0xfe
17 #define BIOS_CALL_GDB_DETACH            0xff
18
19 static __inline__ long sh_bios_call(long func, long arg0, long arg1, long arg2, long arg3)
20 {
21     register long r0 __asm__("r0") = func;
22     register long r4 __asm__("r4") = arg0;
23     register long r5 __asm__("r5") = arg1;
24     register long r6 __asm__("r6") = arg2;
25     register long r7 __asm__("r7") = arg3;
26     __asm__ __volatile__("trapa #0x3f"
27          : "=z" (r0)
28          : "0" (r0), "r" (r4), "r" (r5), "r" (r6), "r" (r7)
29          : "memory");
30     return r0;
31 }
32
33
34 void sh_bios_console_write(const char *buf, unsigned int len)
35 {
36     sh_bios_call(BIOS_CALL_CONSOLE_WRITE, (long)buf, (long)len, 0, 0);
37 }
38
39
40 void sh_bios_char_out(char ch)
41 {
42     sh_bios_call(BIOS_CALL_CHAR_OUT, ch, 0, 0, 0);
43 }
44
45
46 int sh_bios_in_gdb_mode(void)
47 {
48     static char queried = 0;
49     static char *gdb_mode_p = 0;
50
51     if (!queried)
52     {
53         /* Query the gdb stub for address of its gdb mode variable */
54         long r = sh_bios_call(BIOS_CALL_GDB_GET_MODE_PTR, 0, 0, 0, 0);
55         if (r != ~0)    /* BIOS returns -1 for unknown function */
56             gdb_mode_p = (char *)r;
57         queried = 1;
58     }
59     return (gdb_mode_p != 0 ? *gdb_mode_p : 0);
60 }
61
62 void sh_bios_gdb_detach(void)
63 {
64     sh_bios_call(BIOS_CALL_GDB_DETACH, 0, 0, 0, 0);
65 }
66 EXPORT_SYMBOL(sh_bios_gdb_detach);
67
68 void sh_bios_get_node_addr (unsigned char *node_addr)
69 {
70     sh_bios_call(BIOS_CALL_ETH_NODE_ADDR, 0, (long)node_addr, 0, 0);
71 }
72
73 void sh_bios_shutdown(unsigned int how)
74 {
75     sh_bios_call(BIOS_CALL_SHUTDOWN, how, 0, 0, 0);
76 }