Ok. I didn't make 2.4.0 in 2000. Tough. I tried, but we had some
[davej-history.git] / arch / sparc64 / prom / misc.c
blob3ac73f8e2c22d491f766d323029a650532514730
1 /* $Id: misc.c,v 1.19 2000/06/30 10:18:38 davem Exp $
2 * misc.c: Miscellaneous prom functions that don't belong
3 * anywhere else.
5 * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
6 * Copyright (C) 1996,1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
7 */
9 #include <linux/config.h>
10 #include <linux/types.h>
11 #include <linux/kernel.h>
12 #include <linux/sched.h>
13 #include <linux/interrupt.h>
14 #include <linux/delay.h>
15 #include <asm/openprom.h>
16 #include <asm/oplib.h>
18 /* Reset and reboot the machine with the command 'bcommand'. */
19 void
20 prom_reboot(char *bcommand)
22 p1275_cmd ("boot", P1275_ARG(0,P1275_ARG_IN_STRING)|
23 P1275_INOUT(1,0), bcommand);
26 /* Forth evaluate the expression contained in 'fstring'. */
27 void
28 prom_feval(char *fstring)
30 if(!fstring || fstring[0] == 0)
31 return;
32 p1275_cmd ("interpret", P1275_ARG(0,P1275_ARG_IN_STRING)|
33 P1275_INOUT(1,1), fstring);
36 /* We want to do this more nicely some day. */
37 #ifdef CONFIG_SUN_CONSOLE
38 extern void (*prom_palette)(int);
39 extern int serial_console;
40 #endif
42 #ifdef CONFIG_SMP
43 extern void smp_capture(void);
44 extern void smp_release(void);
45 #endif
47 /* Drop into the prom, with the chance to continue with the 'go'
48 * prom command.
50 void
51 prom_cmdline(void)
53 unsigned long flags;
55 __save_and_cli(flags);
57 #ifdef CONFIG_SUN_CONSOLE
58 if(!serial_console && prom_palette)
59 prom_palette (1);
60 #endif
62 /* We always arrive here via a serial interrupt.
63 * So in order for everything to work reliably, even
64 * on SMP, we need to drop the IRQ locks we hold.
66 #ifdef CONFIG_SMP
67 irq_exit(smp_processor_id(), 0);
68 smp_capture();
69 #else
70 local_irq_count(smp_processor_id())--;
71 #endif
73 p1275_cmd ("enter", P1275_INOUT(0,0));
75 #ifdef CONFIG_SMP
76 smp_release();
77 irq_enter(smp_processor_id(), 0);
78 spin_unlock_wait(&__br_write_locks[BR_GLOBALIRQ_LOCK].lock);
79 #else
80 local_irq_count(smp_processor_id())++;
81 #endif
83 #ifdef CONFIG_SUN_CONSOLE
84 if(!serial_console && prom_palette)
85 prom_palette (0);
86 #endif
88 __restore_flags(flags);
91 #ifdef CONFIG_SMP
92 extern void smp_promstop_others(void);
93 #endif
95 /* Drop into the prom, but completely terminate the program.
96 * No chance of continuing.
98 void
99 prom_halt(void)
101 #ifdef CONFIG_SMP
102 smp_promstop_others();
103 udelay(8000);
104 #endif
105 again:
106 p1275_cmd ("exit", P1275_INOUT(0,0));
107 goto again; /* PROM is out to get me -DaveM */
110 /* Set prom sync handler to call function 'funcp'. */
111 void
112 prom_setcallback(callback_func_t funcp)
114 if(!funcp) return;
115 p1275_cmd ("set-callback", P1275_ARG(0,P1275_ARG_IN_FUNCTION)|
116 P1275_INOUT(1,1), funcp);
119 /* Get the idprom and stuff it into buffer 'idbuf'. Returns the
120 * format type. 'num_bytes' is the number of bytes that your idbuf
121 * has space for. Returns 0xff on error.
123 unsigned char
124 prom_get_idprom(char *idbuf, int num_bytes)
126 int len;
128 len = prom_getproplen(prom_root_node, "idprom");
129 if((len>num_bytes) || (len==-1)) return 0xff;
130 if(!prom_getproperty(prom_root_node, "idprom", idbuf, num_bytes))
131 return idbuf[0];
133 return 0xff;
136 /* Get the major prom version number. */
138 prom_version(void)
140 return PROM_P1275;
143 /* Get the prom plugin-revision. */
145 prom_getrev(void)
147 return prom_rev;
150 /* Get the prom firmware print revision. */
152 prom_getprev(void)
154 return prom_prev;
157 /* Install Linux trap table so PROM uses that instead of it's own. */
158 void prom_set_trap_table(unsigned long tba)
160 p1275_cmd("SUNW,set-trap-table", P1275_INOUT(1, 0), tba);
163 int mmu_ihandle_cache = 0;
165 int prom_get_mmu_ihandle(void)
167 int node, ret;
169 if (mmu_ihandle_cache != 0)
170 return mmu_ihandle_cache;
172 node = prom_finddevice("/chosen");
173 ret = prom_getint(node, "mmu");
174 if(ret == -1 || ret == 0)
175 mmu_ihandle_cache = -1;
176 else
177 mmu_ihandle_cache = ret;
179 return ret;
182 static int prom_get_memory_ihandle(void)
184 static int memory_ihandle_cache = 0;
185 int node, ret;
187 if (memory_ihandle_cache != 0)
188 return memory_ihandle_cache;
190 node = prom_finddevice("/chosen");
191 ret = prom_getint(node, "memory");
192 if (ret == -1 || ret == 0)
193 memory_ihandle_cache = -1;
194 else
195 memory_ihandle_cache = ret;
197 return ret;
200 /* Load explicit I/D TLB entries. */
201 long prom_itlb_load(unsigned long index,
202 unsigned long tte_data,
203 unsigned long vaddr)
205 return p1275_cmd("call-method",
206 (P1275_ARG(0, P1275_ARG_IN_STRING) |
207 P1275_ARG(2, P1275_ARG_IN_64B) |
208 P1275_ARG(3, P1275_ARG_IN_64B) |
209 P1275_INOUT(5, 1)),
210 "SUNW,itlb-load",
211 prom_get_mmu_ihandle(),
212 /* And then our actual args are pushed backwards. */
213 vaddr,
214 tte_data,
215 index);
218 long prom_dtlb_load(unsigned long index,
219 unsigned long tte_data,
220 unsigned long vaddr)
222 return p1275_cmd("call-method",
223 (P1275_ARG(0, P1275_ARG_IN_STRING) |
224 P1275_ARG(2, P1275_ARG_IN_64B) |
225 P1275_ARG(3, P1275_ARG_IN_64B) |
226 P1275_INOUT(5, 1)),
227 "SUNW,dtlb-load",
228 prom_get_mmu_ihandle(),
229 /* And then our actual args are pushed backwards. */
230 vaddr,
231 tte_data,
232 index);
235 int prom_map(int mode, unsigned long size,
236 unsigned long vaddr, unsigned long paddr)
238 int ret = p1275_cmd("call-method",
239 (P1275_ARG(0, P1275_ARG_IN_STRING) |
240 P1275_ARG(3, P1275_ARG_IN_64B) |
241 P1275_ARG(4, P1275_ARG_IN_64B) |
242 P1275_ARG(6, P1275_ARG_IN_64B) |
243 P1275_INOUT(7, 1)),
244 "map",
245 prom_get_mmu_ihandle(),
246 mode,
247 size,
248 vaddr,
250 paddr);
252 if (ret == 0)
253 ret = -1;
254 return ret;
257 void prom_unmap(unsigned long size, unsigned long vaddr)
259 p1275_cmd("call-method",
260 (P1275_ARG(0, P1275_ARG_IN_STRING) |
261 P1275_ARG(2, P1275_ARG_IN_64B) |
262 P1275_ARG(3, P1275_ARG_IN_64B) |
263 P1275_INOUT(4, 0)),
264 "unmap",
265 prom_get_mmu_ihandle(),
266 size,
267 vaddr);
270 /* Set aside physical memory which is not touched or modified
271 * across soft resets.
273 unsigned long prom_retain(char *name,
274 unsigned long pa_low, unsigned long pa_high,
275 long size, long align)
277 /* XXX I don't think we return multiple values correctly.
278 * XXX OBP supposedly returns pa_low/pa_high here, how does
279 * XXX it work?
282 /* If align is zero, the pa_low/pa_high args are passed,
283 * else they are not.
285 if(align == 0)
286 return p1275_cmd("SUNW,retain",
287 (P1275_ARG(0, P1275_ARG_IN_BUF) | P1275_INOUT(5, 2)),
288 name, pa_low, pa_high, size, align);
289 else
290 return p1275_cmd("SUNW,retain",
291 (P1275_ARG(0, P1275_ARG_IN_BUF) | P1275_INOUT(3, 2)),
292 name, size, align);
295 /* Get "Unumber" string for the SIMM at the given
296 * memory address. Usually this will be of the form
297 * "Uxxxx" where xxxx is a decimal number which is
298 * etched into the motherboard next to the SIMM slot
299 * in question.
301 int prom_getunumber(int syndrome_code,
302 unsigned long phys_addr,
303 char *buf, int buflen)
305 return p1275_cmd("call-method",
306 (P1275_ARG(0, P1275_ARG_IN_STRING) |
307 P1275_ARG(3, P1275_ARG_OUT_BUF) |
308 P1275_ARG(6, P1275_ARG_IN_64B) |
309 P1275_INOUT(8, 2)),
310 "SUNW,get-unumber", prom_get_memory_ihandle(),
311 buflen, buf, P1275_SIZE(buflen),
312 0, phys_addr, syndrome_code);
315 /* Power management extensions. */
316 void prom_sleepself(void)
318 p1275_cmd("SUNW,sleep-self", P1275_INOUT(0, 0));
321 int prom_sleepsystem(void)
323 return p1275_cmd("SUNW,sleep-system", P1275_INOUT(0, 1));
326 int prom_wakeupsystem(void)
328 return p1275_cmd("SUNW,wakeup-system", P1275_INOUT(0, 1));
331 #ifdef CONFIG_SMP
332 void prom_startcpu(int cpunode, unsigned long pc, unsigned long o0)
334 p1275_cmd("SUNW,start-cpu", P1275_INOUT(3, 0), cpunode, pc, o0);
337 void prom_stopself(void)
339 p1275_cmd("SUNW,stop-self", P1275_INOUT(0, 0));
342 void prom_idleself(void)
344 p1275_cmd("SUNW,idle-self", P1275_INOUT(0, 0));
347 void prom_resumecpu(int cpunode)
349 p1275_cmd("SUNW,resume-cpu", P1275_INOUT(1, 0), cpunode);
351 #endif