File: /usr/src/linux/arch/parisc/kernel/real1.c

1     /*
2      *
3      * This file is subject to the terms and conditions of the GNU General Public
4      * License.  See the file "COPYING" in the main directory of this archive
5      * for more details.
6      *
7      * Copyright (C) 2000 Hewlett Packard (Paul Bame bame@puffin.external.hp.com)
8      *
9      * most of these calls might reasonably be moved to ../kernel -PB
10      *
11      * The basic principle is to construct a stack frame in C then call
12      * some assembly which adopts that stack, does some rfi magic, may
13      * switch wide/narrow mode, and calls the routine described by the
14      * 'fn' parameter WHICH IS NOT A FUNCTION POINTER!!!!!!!!!!!!!!!!
15      */
16     #include <linux/spinlock.h>
17     #include <asm/system.h>
18     #include <stdarg.h>
19     #include <asm/pgtable.h>		/* for __pa() */
20     #include <asm/pdc.h>
21     
22     static spinlock_t pdc_lock = SPIN_LOCK_UNLOCKED;
23     
24     /***************** 32-bit real-mode calls ***********/
25     /* The struct below is used
26      * to overlay real_stack (real2.S), preparing a 32-bit call frame.
27      * real32_call_asm() then uses this stack in narrow real mode
28      */
29     
30     struct narrow_stack {
31         /* use int, not long which is 64 bits */
32         unsigned int arg13;
33         unsigned int arg12;
34         unsigned int arg11;
35         unsigned int arg10;
36         unsigned int arg9;
37         unsigned int arg8;
38         unsigned int arg7;
39         unsigned int arg6;
40         unsigned int arg5;
41         unsigned int arg4;
42         unsigned int arg3;
43         unsigned int arg2;
44         unsigned int arg1;
45         unsigned int arg0;
46         unsigned int frame_marker[8];
47         unsigned int sp;
48         /* in reality, there's nearly 8k of stack after this */
49     };
50     
51     long
52     real32_call(unsigned long fn, ...)
53     {
54         unsigned long r;
55         va_list args;
56         unsigned long flags;
57         extern struct narrow_stack real_stack;
58         extern unsigned long real32_call_asm(unsigned int *,
59     				unsigned int *, unsigned int);
60         
61         va_start(args, fn);
62         real_stack.arg0 = va_arg(args, unsigned int);
63         real_stack.arg1 = va_arg(args, unsigned int);
64         real_stack.arg2 = va_arg(args, unsigned int);
65         real_stack.arg3 = va_arg(args, unsigned int);
66         real_stack.arg4 = va_arg(args, unsigned int);
67         real_stack.arg5 = va_arg(args, unsigned int);
68         real_stack.arg6 = va_arg(args, unsigned int);
69         real_stack.arg7 = va_arg(args, unsigned int);
70         real_stack.arg8 = va_arg(args, unsigned int);
71         real_stack.arg9 = va_arg(args, unsigned int);
72         real_stack.arg10 = va_arg(args, unsigned int);
73         real_stack.arg11 = va_arg(args, unsigned int);
74         real_stack.arg12 = va_arg(args, unsigned int);
75         real_stack.arg13 = va_arg(args, unsigned int);
76         va_end(args);
77     
78         if (fn == 0) {
79     	    /* mem_pdc call */
80     	    fn = PAGE0->mem_pdc;
81         }
82     
83         spin_lock_irqsave(&pdc_lock, flags);
84         r = real32_call_asm(&real_stack.sp, &real_stack.arg0, fn);
85         spin_unlock_irqrestore(&pdc_lock, flags);
86     
87         return r;
88     }
89     
90     #ifdef __LP64__
91     /***************** 64-bit real-mode calls ***********/
92     
93     struct wide_stack {
94         unsigned long arg0;
95         unsigned long arg1;
96         unsigned long arg2;
97         unsigned long arg3;
98         unsigned long arg4;
99         unsigned long arg5;
100         unsigned long arg6;
101         unsigned long arg7;
102         unsigned long arg8;
103         unsigned long arg9;
104         unsigned long arg10;
105         unsigned long arg11;
106         unsigned long arg12;
107         unsigned long arg13;
108         unsigned long frame_marker[2];	/* rp, previous sp */
109         unsigned long sp;
110         /* in reality, there's nearly 8k of stack after this */
111     };
112     
113     long
114     real64_call(unsigned long fn, ...)
115     {
116         unsigned long r;
117         va_list args;
118         unsigned long flags;
119         extern struct wide_stack real_stack;
120         extern unsigned long real64_call_asm(unsigned long *,
121     				unsigned long *, unsigned long);
122         
123         va_start(args, fn);
124         real_stack.arg0 = va_arg(args, unsigned long);
125         real_stack.arg1 = va_arg(args, unsigned long);
126         real_stack.arg2 = va_arg(args, unsigned long);
127         real_stack.arg3 = va_arg(args, unsigned long);
128         real_stack.arg4 = va_arg(args, unsigned long);
129         real_stack.arg5 = va_arg(args, unsigned long);
130         real_stack.arg6 = va_arg(args, unsigned long);
131         real_stack.arg7 = va_arg(args, unsigned long);
132         real_stack.arg8 = va_arg(args, unsigned long);
133         real_stack.arg9 = va_arg(args, unsigned long);
134         real_stack.arg10 = va_arg(args, unsigned long);
135         real_stack.arg11 = va_arg(args, unsigned long);
136         real_stack.arg12 = va_arg(args, unsigned long);
137         real_stack.arg13 = va_arg(args, unsigned long);
138         va_end(args);
139     
140         if (fn == 0) {
141     	    /* mem_pdc call */
142     	    fn = PAGE0->mem_pdc_hi;
143     	    fn <<= 32;
144     	    fn |= PAGE0->mem_pdc;
145         }
146     
147         spin_lock_irqsave(&pdc_lock, flags);
148         r = real64_call_asm(&real_stack.sp, &real_stack.arg0, fn);
149         spin_unlock_irqrestore(&pdc_lock, flags);
150     
151         return r;
152     }
153     
154     #endif
155