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 "briq/briq.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( vfd_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 	char *s = malloc( len + 1 );
74 
75 	strncpy_nopad( s, addr, len );
76 	s[len]=0;
77 
78 	printk( "%s", s );
79 	//vfd_draw_str( s );
80 	free( s );
81 
82 	PUSH( len );
83 }
84 
85 NODE_METHODS( vfd_stdout ) = {
86 	{ "write",	stdout_write	},
87 };
88 
89 
90 /************************************************************************/
91 /*	tty								*/
92 /************************************************************************/
93 
94 DECLARE_NODE( tty, INSTALL_OPEN, 0, "/packages/terminal-emulator" );
95 
96 /* ( addr len -- actual ) */
97 static void
tty_read(void)98 tty_read( void )
99 {
100 	int ch, len = POP();
101 	char *p = (char*)POP();
102 	int ret=0;
103 
104 	if( len > 0 ) {
105 		ret = 1;
106 		ch = getchar();
107 		if( ch >= 0 ) {
108 			*p = ch;
109 		} else {
110 			ret = 0;
111 		}
112 	}
113 	PUSH( ret );
114 }
115 
116 /* ( addr len -- actual ) */
117 static void
tty_write(void)118 tty_write( void )
119 {
120 	int i, len = POP();
121 	char *p = (char*)POP();
122 	for( i=0; i<len; i++ )
123 		putchar( *p++ );
124 	RET( len );
125 }
126 
127 NODE_METHODS( tty ) = {
128 	{ "read",	tty_read	},
129 	{ "write",	tty_write	},
130 };
131 
132 /************************************************************************/
133 /*	client interface 'quiesce'					*/
134 /************************************************************************/
135 
136 DECLARE_NODE( ciface, 0, 0, "/packages/client-iface" );
137 
138 /* ( -- ) */
139 static void
ciface_quiesce(unsigned long args[],unsigned long ret[])140 ciface_quiesce( unsigned long args[], unsigned long ret[] )
141 {
142 #if 0
143 	unsigned long msr;
144 	/* This seems to be the correct thing to do - but I'm not sure */
145 	asm volatile("mfmsr %0" : "=r" (msr) : );
146 	msr &= ~(MSR_IR | MSR_DR);
147 	asm volatile("mtmsr %0" :: "r" (msr) );
148 #endif
149 	printk("=============================================================\n\n");
150 }
151 
152 /* ( -- ms ) */
153 static void
ciface_milliseconds(unsigned long args[],unsigned long ret[])154 ciface_milliseconds( unsigned long args[], unsigned long ret[] )
155 {
156 	extern unsigned long get_timer_freq();
157 	static unsigned long mticks=0, usecs=0;
158 	unsigned long t;
159 
160 	asm volatile("mftb %0" : "=r" (t) : );
161 	if( mticks )
162 		usecs += get_timer_freq() / 1000000 * ( t-mticks );
163 	mticks = t;
164 
165 	PUSH( usecs/1000 );
166 }
167 
168 
169 NODE_METHODS( ciface ) = {
170 	{ "quiesce",		ciface_quiesce		},
171 	{ "milliseconds",	ciface_milliseconds	},
172 };
173 
174 
175 /************************************************************************/
176 /*	MMU/memory methods						*/
177 /************************************************************************/
178 
179 DECLARE_NODE( memory, INSTALL_OPEN, 0, "/memory" );
180 DECLARE_NODE( mmu, INSTALL_OPEN, 0, "/cpu@0" );
181 DECLARE_NODE( mmu_ciface, 0, 0, "/packages/client-iface" );
182 
183 
184 /* ( phys size align --- base ) */
185 static void
mem_claim(void)186 mem_claim( void )
187 {
188 	int align = POP();
189 	int size = POP();
190 	int phys = POP();
191 	int ret = ofmem_claim_phys( phys, size, align );
192 
193 	if( ret == -1 ) {
194 		printk("MEM: claim failure\n");
195 		throw( -13 );
196 		return;
197 	}
198 	PUSH( ret );
199 }
200 
201 /* ( phys size --- ) */
202 static void
mem_release(void)203 mem_release( void )
204 {
205 	POP(); POP();
206 }
207 
208 /* ( phys size align --- base ) */
209 static void
mmu_claim(void)210 mmu_claim( void )
211 {
212 	int align = POP();
213 	int size = POP();
214 	int phys = POP();
215 	int ret = ofmem_claim_virt( phys, size, align );
216 
217 	if( ret == -1 ) {
218 		printk("MMU: CLAIM failure\n");
219 		throw( -13 );
220 		return;
221 	}
222 	PUSH( ret );
223 }
224 
225 /* ( phys size --- ) */
226 static void
mmu_release(void)227 mmu_release( void )
228 {
229 	POP(); POP();
230 }
231 
232 /* ( phys virt size mode -- [ret???] ) */
233 static void
mmu_map(void)234 mmu_map( void )
235 {
236 	int mode = POP();
237 	int size = POP();
238 	int virt = POP();
239 	int phys = POP();
240 	int ret;
241 
242 	/* printk("mmu_map: %x %x %x %x\n", phys, virt, size, mode ); */
243 	ret = ofmem_map( phys, virt, size, mode );
244 
245 	if( ret ) {
246 		printk("MMU: map failure\n");
247 		throw( -13 );
248 		return;
249 	}
250 }
251 
252 /* ( virt size -- ) */
253 static void
mmu_unmap(void)254 mmu_unmap( void )
255 {
256 	POP(); POP();
257 }
258 
259 /* ( virt -- false | phys mode true ) */
260 static void
mmu_translate(void)261 mmu_translate( void )
262 {
263 	ucell mode;
264 	ucell virt = POP();
265 	ucell phys = ofmem_translate( virt, &mode );
266 
267 	if( phys == -1 ) {
268 		PUSH( 0 );
269 	} else {
270 		PUSH( phys );
271 		PUSH( mode );
272 		PUSH( -1 );
273 	}
274 }
275 
276 /* ( virt size align -- baseaddr|-1 ) */
277 static void
ciface_claim(void)278 ciface_claim( void )
279 {
280 	int align = POP();
281 	int size = POP();
282 	int virt = POP();
283 	int ret = ofmem_claim( virt, size, align );
284 
285 	/* printk("ciface_claim: %08x %08x %x\n", virt, size, align ); */
286 	PUSH( ret );
287 }
288 
289 /* ( virt size -- ) */
290 static void
ciface_release(void)291 ciface_release( void )
292 {
293 	POP();
294 	POP();
295 }
296 
297 
298 NODE_METHODS( memory ) = {
299 	{ "claim",		mem_claim		},
300 	{ "release",		mem_release		},
301 };
302 
303 NODE_METHODS( mmu ) = {
304 	{ "claim",		mmu_claim		},
305 	{ "release",		mmu_release		},
306 	{ "map",		mmu_map			},
307 	{ "unmap",		mmu_unmap		},
308 	{ "translate",		mmu_translate		},
309 };
310 
311 NODE_METHODS( mmu_ciface ) = {
312 	{ "cif-claim",		ciface_claim		},
313 	{ "cif-release",	ciface_release		},
314 };
315 
316 
317 /************************************************************************/
318 /*	init								*/
319 /************************************************************************/
320 
321 void
node_methods_init(void)322 node_methods_init( void )
323 {
324 #ifdef CONFIG_RTAS
325 	REGISTER_NODE( rtas );
326 #endif
327 	REGISTER_NODE( vfd_stdout );
328 	REGISTER_NODE( ciface );
329 	REGISTER_NODE( memory );
330 	REGISTER_NODE( mmu );
331 	REGISTER_NODE( mmu_ciface );
332 	REGISTER_NODE( tty );
333 }
334