1 /*
2  *   Creation Date: <2004/08/28 18:38:22 greg>
3  *   Time-stamp: <2004/08/28 18:38:22 greg>
4  *
5  *	<methods.c>
6  *
7  *	Misc device node methods
8  *
9  *   Copyright (C) 2004 Greg Watson
10  *
11  *   Based on MOL specific code which is
12  *
13  *   Copyright (C) 2003, 2004 Samuel Rydh (samuel@ibrium.se)
14  *
15  *   This program is free software; you can redistribute it and/or
16  *   modify it under the terms of the GNU General Public License
17  *   version 2
18  *
19  */
20 
21 #include "config.h"
22 #include "libopenbios/bindings.h"
23 #include "libc/string.h"
24 #include "pearpc/pearpc.h"
25 #include "libopenbios/ofmem.h"
26 
27 /************************************************************************/
28 /*	RTAS (run-time abstraction services)				*/
29 /************************************************************************/
30 
31 #ifdef CONFIG_RTAS
32 DECLARE_NODE( rtas, INSTALL_OPEN, 0, "+/rtas" );
33 
34 /* ( physbase -- rtas_callback ) */
35 static void
rtas_instantiate(void)36 rtas_instantiate( void )
37 {
38 	int physbase = POP();
39 	int s=0x1000, size = (int)of_rtas_end - (int)of_rtas_start;
40 	unsigned long virt;
41 
42 	while( s < size )
43 		s += 0x1000;
44 	virt = ofmem_claim_virt( 0, s, 0x1000 );
45 	ofmem_map( physbase, virt, s, -1 );
46 	memcpy( (char*)virt, of_rtas_start, size );
47 
48 	printk("RTAS instantiated at %08x\n", physbase );
49 	flush_icache_range( (char*)virt, (char*)virt + size );
50 
51 	PUSH( physbase );
52 }
53 
54 NODE_METHODS( rtas ) = {
55 	{ "instantiate",	rtas_instantiate },
56 	{ "instantiate-rtas",	rtas_instantiate },
57 };
58 #endif
59 
60 
61 /************************************************************************/
62 /*	stdout								*/
63 /************************************************************************/
64 
65 DECLARE_NODE( video_stdout, INSTALL_OPEN, 0, "Tdisplay" );
66 
67 /* ( addr len -- actual ) */
68 static void
stdout_write(void)69 stdout_write( void )
70 {
71 	int len = POP();
72 	char *addr = (char*)POP();
73 
74 	printk( "%s", s );
75 	//vfd_draw_str( s );
76         console_draw_fstr(addr, len);
77 
78 	PUSH( len );
79 }
80 
81 NODE_METHODS( video_stdout ) = {
82 	{ "write",	stdout_write	},
83 };
84 
85 
86 /************************************************************************/
87 /*	tty								*/
88 /************************************************************************/
89 
90 DECLARE_NODE( tty, INSTALL_OPEN, 0, "/packages/terminal-emulator" );
91 
92 /* ( addr len -- actual ) */
93 static void
tty_read(void)94 tty_read( void )
95 {
96 	int ch, len = POP();
97 	char *p = (char*)POP();
98 	int ret=0;
99 
100 	if( len > 0 ) {
101 		ret = 1;
102 		ch = getchar();
103 		if( ch >= 0 ) {
104 			*p = ch;
105 		} else {
106 			ret = 0;
107 		}
108 	}
109 	PUSH( ret );
110 }
111 
112 /* ( addr len -- actual ) */
113 static void
tty_write(void)114 tty_write( void )
115 {
116 	int i, len = POP();
117 	char *p = (char*)POP();
118 	for( i=0; i<len; i++ )
119 		putchar( *p++ );
120 	RET( len );
121 }
122 
123 NODE_METHODS( tty ) = {
124 	{ "read",	tty_read	},
125 	{ "write",	tty_write	},
126 };
127 
128 /************************************************************************/
129 /*	client interface 'quiesce'					*/
130 /************************************************************************/
131 
132 DECLARE_NODE( ciface, 0, 0, "/packages/client-iface" );
133 
134 /* ( -- ) */
135 static void
ciface_quiesce(unsigned long args[],unsigned long ret[])136 ciface_quiesce( unsigned long args[], unsigned long ret[] )
137 {
138 #if 0
139 	unsigned long msr;
140 	/* This seems to be the correct thing to do - but I'm not sure */
141 	asm volatile("mfmsr %0" : "=r" (msr) : );
142 	msr &= ~(MSR_IR | MSR_DR);
143 	asm volatile("mtmsr %0" :: "r" (msr) );
144 #endif
145 	printk("=============================================================\n\n");
146 }
147 
148 /* ( -- ms ) */
149 static void
ciface_milliseconds(unsigned long args[],unsigned long ret[])150 ciface_milliseconds( unsigned long args[], unsigned long ret[] )
151 {
152 	extern unsigned long get_timer_freq();
153 	static unsigned long mticks=0, usecs=0;
154 	unsigned long t;
155 
156 	asm volatile("mftb %0" : "=r" (t) : );
157 	if( mticks )
158 		usecs += get_timer_freq() / 1000000 * ( t-mticks );
159 	mticks = t;
160 
161 	PUSH( usecs/1000 );
162 }
163 
164 
165 NODE_METHODS( ciface ) = {
166 	{ "quiesce",		ciface_quiesce		},
167 	{ "milliseconds",	ciface_milliseconds	},
168 };
169 
170 
171 /************************************************************************/
172 /*	MMU/memory methods						*/
173 /************************************************************************/
174 
175 DECLARE_NODE( memory, INSTALL_OPEN, 0, "/memory" );
176 DECLARE_NODE( mmu, INSTALL_OPEN, 0, "/cpu@0" );
177 DECLARE_NODE( mmu_ciface, 0, 0, "/packages/client-iface" );
178 
179 
180 /* ( phys size align --- base ) */
181 static void
mem_claim(void)182 mem_claim( void )
183 {
184 	ucell align = POP();
185 	ucell size = POP();
186 	ucell phys = POP();
187 	ucell ret = ofmem_claim_phys( phys, size, align );
188 
189 	if( ret == (ucell)-1 ) {
190 		printk("MEM: claim failure\n");
191 		throw( -13 );
192 		return;
193 	}
194 	PUSH( ret );
195 }
196 
197 /* ( phys size --- ) */
198 static void
mem_release(void)199 mem_release( void )
200 {
201 	POP(); POP();
202 }
203 
204 /* ( phys size align --- base ) */
205 static void
mmu_claim(void)206 mmu_claim( void )
207 {
208 	ucell align = POP();
209 	ucell size = POP();
210 	ucell phys = POP();
211 	ucell ret = ofmem_claim_virt( phys, size, align );
212 
213 	if( ret == -1 ) {
214 		printk("MMU: CLAIM failure\n");
215 		throw( -13 );
216 		return;
217 	}
218 	PUSH( ret );
219 }
220 
221 /* ( phys size --- ) */
222 static void
mmu_release(void)223 mmu_release( void )
224 {
225 	POP(); POP();
226 }
227 
228 /* ( phys virt size mode -- [ret???] ) */
229 static void
mmu_map(void)230 mmu_map( void )
231 {
232 	ucell mode = POP();
233 	ucell size = POP();
234 	ucell virt = POP();
235 	ucell phys = POP();
236 	ucell ret;
237 
238 	/* printk("mmu_map: %x %x %x %x\n", phys, virt, size, mode ); */
239 	ret = ofmem_map( phys, virt, size, mode );
240 
241 	if( ret ) {
242 		printk("MMU: map failure\n");
243 		throw( -13 );
244 		return;
245 	}
246 }
247 
248 /* ( virt size -- ) */
249 static void
mmu_unmap(void)250 mmu_unmap( void )
251 {
252 	POP(); POP();
253 }
254 
255 /* ( virt -- false | phys mode true ) */
256 static void
mmu_translate(void)257 mmu_translate( void )
258 {
259 	ucell mode;
260 	ucell virt = POP();
261 	ucell phys = ofmem_translate( virt, &mode );
262 
263 	if( phys == -1 ) {
264 		PUSH( 0 );
265 	} else {
266 		PUSH( phys );
267 		PUSH( mode );
268 		PUSH( -1 );
269 	}
270 }
271 
272 /* ( virt size align -- baseaddr|-1 ) */
273 static void
ciface_claim(void)274 ciface_claim( void )
275 {
276 	ucell align = POP();
277 	ucell size = POP();
278 	ucell virt = POP();
279 	ucell ret = ofmem_claim( virt, size, align );
280 
281 	/* printk("ciface_claim: %08x %08x %x\n", virt, size, align ); */
282 	PUSH( ret );
283 }
284 
285 /* ( virt size -- ) */
286 static void
ciface_release(void)287 ciface_release( void )
288 {
289 	POP();
290 	POP();
291 }
292 
293 
294 NODE_METHODS( memory ) = {
295 	{ "claim",		mem_claim		},
296 	{ "release",		mem_release		},
297 };
298 
299 NODE_METHODS( mmu ) = {
300 	{ "claim",		mmu_claim		},
301 	{ "release",		mmu_release		},
302 	{ "map",		mmu_map			},
303 	{ "unmap",		mmu_unmap		},
304 	{ "translate",		mmu_translate		},
305 };
306 
307 NODE_METHODS( mmu_ciface ) = {
308 	{ "cif-claim",		ciface_claim		},
309 	{ "cif-release",	ciface_release		},
310 };
311 
312 
313 /************************************************************************/
314 /*	init								*/
315 /************************************************************************/
316 
317 void
node_methods_init(void)318 node_methods_init( void )
319 {
320 #ifdef CONFIG_RTAS
321 	REGISTER_NODE( rtas );
322 #endif
323 	REGISTER_NODE( video_stdout );
324 	REGISTER_NODE( ciface );
325 	REGISTER_NODE( memory );
326 	REGISTER_NODE( mmu );
327 	REGISTER_NODE( mmu_ciface );
328 	REGISTER_NODE( tty );
329 }
330