~ubuntu-branches/ubuntu/quantal/silo/quantal

« back to all changes in this revision

Viewing changes to common/prom.c

  • Committer: Bazaar Package Importer
  • Author(s): Fabio M. Di Nitto
  • Date: 2007-10-25 09:28:08 UTC
  • mfrom: (15.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20071025092808-1yhj12t7s4zqsfu5
Tags: 1.4.13a+git20070930-1ubuntu1
* Merge from debian unstable, remaining changes:
  - Build with -fno-stack-protector.
  - Change silo.postinst to automatically update the boot block without
    invoking siloconfig and keep asking questions on upgrades.
  - Convert silo.conf to use /dev/disk/by-uuid.
  - Ubuntu maintainer foobar.
  - Fix debian/rules call to dh_installdocs.
  - Drop the requirement of gcc-4.1 and start using default gcc.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* $Id: prom.c,v 1.2 2001/05/25 22:51:28 bencollins Exp $
 
2
 * init.c:  Initialize internal variables used by the PROM
 
3
 *          library functions.
 
4
 *
 
5
 * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
 
6
 * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
 
7
 */
 
8
 
 
9
#include <promlib.h>
 
10
 
 
11
struct linux_romvec *romvec;
 
12
enum prom_major_version prom_vers;
 
13
unsigned int prom_rev, prom_prev;
 
14
void (*prom_cif_handler)(long long *);
 
15
void (*prom_cif_h32)(long *);
 
16
void *prom_cif_stack;
 
17
 
 
18
/* The root node of the prom device tree. */
 
19
int prom_root_node;
 
20
 
 
21
int prom_stdin, prom_stdout;
 
22
int prom_chosen;
 
23
 
 
24
/* Pointer to the device tree operations structure. */
 
25
struct linux_nodeops *prom_nodeops;
 
26
 
 
27
/* You must call prom_init() before you attempt to use any of the
 
28
 * routines in the prom library.  It returns 0 on success, 1 on
 
29
 * failure.  It gets passed the pointer to the PROM vector.
 
30
 */
 
31
 
 
32
static long long p1275_args[23];
 
33
 
 
34
int p1275_cmd (char *service, unsigned fmt, ...)
 
35
{
 
36
        va_list list;
 
37
        int i;
 
38
        int args = fmt & 0xf;
 
39
 
 
40
        fmt >>= 8;
 
41
 
 
42
        /* This means we have a P1275 PROM on a 32-bit machine. There
 
43
         * better not be any 64-bit arguments. */
 
44
        if (prom_cif_handler == 0) {
 
45
                long *p1275_args32 = (long *)p1275_args;
 
46
 
 
47
                if (fmt)
 
48
                        prom_halt();
 
49
 
 
50
                p1275_args32[0] = (long)service;
 
51
                p1275_args32[1] = args;
 
52
                p1275_args32[2] = 1;
 
53
                va_start (list, fmt);
 
54
                for (i = 0; i < args; i++)
 
55
                        p1275_args32[i + 3] = (long) va_arg (list, char *);
 
56
                va_end (list);
 
57
                (*prom_cif_h32)(p1275_args32);
 
58
                return p1275_args32[3 + args];
 
59
        }
 
60
 
 
61
        p1275_args[0] = (unsigned long long)(unsigned long)service;
 
62
        p1275_args[1] = args;
 
63
        p1275_args[2] = 1;
 
64
        va_start (list, fmt);
 
65
        for (i = 0; i < args; i++, fmt >>= 1) {
 
66
                if (fmt & 0x1)
 
67
                        p1275_args[i + 3] = va_arg (list, unsigned long long);
 
68
                else
 
69
                        p1275_args[i + 3] = (unsigned long long)(unsigned long) va_arg (list, char *);
 
70
        }
 
71
        va_end (list);
 
72
        __asm__ __volatile__ ("\t"
 
73
                "mov    %1, %%g1\n\t"
 
74
                "mov    %2, %%g2\n\t"
 
75
                "save   %0, -0xc0, %%sp\n\t"
 
76
                "rdpr   %%pstate, %%l1\n\t"
 
77
                "andn   %%l1, 8, %%l1\n\t"
 
78
                "wrpr   %%l1, 0, %%pstate\n\t"
 
79
                "call   %%g1\n\t"
 
80
                " mov   %%g2, %%o0\n\t"
 
81
                "wrpr   %%l1, 8, %%pstate\n\t"
 
82
                "restore\n"
 
83
        : : "r" (prom_cif_stack), "r" (prom_cif_handler), "r" (p1275_args) :
 
84
        "o0", "o1", "o2", "o3", "o4", "o5", "o7", "g1", "g2", "g3", "g4",
 
85
        "g5", "g6", "g7");
 
86
        return (int) p1275_args [3 + args];
 
87
}
 
88
 
 
89
void prom_init(struct linux_romvec *rp, void *cifh, void *cifsp)
 
90
{
 
91
        if (cifh || ((int)rp & 1) != 0) {
 
92
                prom_cif_handler = cifh;
 
93
                prom_cif_h32 = (void *)((unsigned long)rp & ~1);
 
94
                prom_cif_stack = cifsp;
 
95
                prom_vers = PROM_P1275;
 
96
                prom_chosen = p1275_cmd ("finddevice", 1, "/chosen");
 
97
                if (prom_chosen == -1) prom_halt ();
 
98
                prom_stdin = prom_getint (prom_chosen, "stdin");
 
99
                prom_stdout = prom_getint (prom_chosen, "stdout");
 
100
        } else {
 
101
                romvec = rp;
 
102
 
 
103
                switch(romvec->pv_romvers) {
 
104
                case 0:
 
105
                        prom_vers = PROM_V0;
 
106
                        break;
 
107
                case 2:
 
108
                        prom_vers = PROM_V2;
 
109
                        break;
 
110
                case 3:
 
111
                        prom_vers = PROM_V3;
 
112
                        break;
 
113
                }
 
114
 
 
115
                prom_rev = romvec->pv_plugin_revision;
 
116
                prom_prev = romvec->pv_printrev;
 
117
                prom_nodeops = romvec->pv_nodeops;
 
118
                if (prom_vers != PROM_V0) {
 
119
                        prom_stdin = *romvec->pv_v2bootargs.fd_stdin;
 
120
                        prom_stdout = *romvec->pv_v2bootargs.fd_stdout;
 
121
                }
 
122
                if((((unsigned long) prom_nodeops) == 0) || 
 
123
                   (((unsigned long) prom_nodeops) == -1))
 
124
                        prom_halt();
 
125
        }
 
126
 
 
127
        prom_root_node = prom_getsibling(0);
 
128
        if((prom_root_node == 0) || (prom_root_node == -1))
 
129
                prom_halt();
 
130
 
 
131
        /* Initialization successful. */
 
132
        return;
 
133
}
 
134
 
 
135
void
 
136
prom_chain(unsigned long addr, int size, unsigned long entry, char *args, int len)
 
137
{
 
138
        p1275_cmd ("chain", 5, addr, size, entry, args, len);
 
139
}
 
140
 
 
141
void
 
142
prom_reboot(char *bcommand)
 
143
{
 
144
        p1275_cmd ("boot", 1, bcommand);
 
145
}
 
146
 
 
147
/* Drop into the prom, with the chance to continue with the 'go'
 
148
 * prom command.
 
149
 */
 
150
void
 
151
prom_cmdline(void)
 
152
{
 
153
        if (prom_vers != PROM_P1275)
 
154
                (*(romvec->pv_abort))();
 
155
        else
 
156
                p1275_cmd ("enter", 0);
 
157
}
 
158
 
 
159
/* Drop into the prom, but completely terminate the program.
 
160
 * No chance of continuing.
 
161
 */
 
162
void
 
163
prom_halt(void)
 
164
{
 
165
        if (prom_vers != PROM_P1275)
 
166
                (*(romvec->pv_halt))();
 
167
        else
 
168
                p1275_cmd ("exit", 0);
 
169
        /* Not reached */
 
170
}
 
171
 
 
172
static int mmu_ihandle_cache = 0;
 
173
 
 
174
static int prom_get_mmu_ihandle(void)
 
175
{
 
176
        int node, ret;
 
177
 
 
178
        if (mmu_ihandle_cache != 0)
 
179
                return mmu_ihandle_cache;
 
180
 
 
181
        node = prom_finddevice("/chosen");
 
182
        ret = prom_getint(node, "mmu");
 
183
        if (ret == -1 || ret == 0)
 
184
                mmu_ihandle_cache = -1;
 
185
        else
 
186
                mmu_ihandle_cache = ret;
 
187
 
 
188
        return ret;
 
189
}
 
190
 
 
191
int prom_map(int mode, unsigned long long size,
 
192
             unsigned long long vaddr,
 
193
             unsigned long long paddr)
 
194
{
 
195
        int ret = p1275_cmd("call-method",
 
196
                            P1275_ARG_64B(3) | P1275_ARG_64B(4) |
 
197
                            P1275_ARG_64B(6) | 7,
 
198
                            "map",
 
199
                            prom_get_mmu_ihandle(),
 
200
                            mode,
 
201
                            size,
 
202
                            vaddr,
 
203
                            0,
 
204
                            paddr);
 
205
 
 
206
        return ret;
 
207
}
 
208
 
 
209
void prom_unmap(unsigned long long size, unsigned long long vaddr)
 
210
{
 
211
        p1275_cmd("call-method",
 
212
                  P1275_ARG_64B(2) | P1275_ARG_64B(3) | 4,
 
213
                  "unmap",
 
214
                  prom_get_mmu_ihandle(),
 
215
                  size,
 
216
                  vaddr);
 
217
}