Add qemu 2.4.0
[kvmfornfv.git] / qemu / roms / openbios / arch / ppc / mol / methods.c
1 /*
2  *   Creation Date: <2003/10/18 13:24:29 samuel>
3  *   Time-stamp: <2004/03/27 02:00:30 samuel>
4  *
5  *      <methods.c>
6  *
7  *      Misc device node methods
8  *
9  *   Copyright (C) 2003, 2004 Samuel Rydh (samuel@ibrium.se)
10  *
11  *   This program is free software; you can redistribute it and/or
12  *   modify it under the terms of the GNU General Public License
13  *   version 2
14  *
15  */
16
17 #include "config.h"
18 #include "libopenbios/bindings.h"
19 #include "libc/string.h"
20 #include "mol/mol.h"
21 #include "libopenbios/ofmem.h"
22 #include "mol/prom.h"
23 #include "osi_calls.h"
24 #include "kbd_sh.h"
25
26 /************************************************************************/
27 /*      Power Management                                                */
28 /************************************************************************/
29
30 DECLARE_NODE( powermgt, INSTALL_OPEN, 0, "/pci/pci-bridge/mac-io/power-mgt" );
31
32 /* ( -- ) */
33 static void
34 set_hybernot_flag( void )
35 {
36 }
37
38 NODE_METHODS( powermgt ) = {
39         { "set-hybernot-flag",  set_hybernot_flag       },
40 };
41
42
43 /************************************************************************/
44 /*      RTAS (run-time abstraction services)                            */
45 /************************************************************************/
46
47 DECLARE_NODE( rtas, INSTALL_OPEN, 0, "+/rtas" );
48
49 /* ( physbase -- rtas_callback ) */
50 static void
51 rtas_instantiate( void )
52 {
53         int physbase = POP();
54         int s=0x1000, size = (int)of_rtas_end - (int)of_rtas_start;
55         unsigned long virt;
56
57         while( s < size )
58                 s += 0x1000;
59         virt = ofmem_claim_virt( 0, s, 0x1000 );
60         ofmem_map( physbase, virt, s, -1 );
61         memcpy( (char*)virt, of_rtas_start, size );
62
63         printk("RTAS instantiated at %08x\n", physbase );
64         flush_icache_range( (char*)virt, (char*)virt + size );
65
66         PUSH( physbase );
67 }
68
69 NODE_METHODS( rtas ) = {
70         { "instantiate",        rtas_instantiate },
71         { "instantiate-rtas",   rtas_instantiate },
72 };
73
74
75
76 /************************************************************************/
77 /*      stdout                                                          */
78 /************************************************************************/
79
80 DECLARE_NODE( video_stdout, INSTALL_OPEN, 0, "Tdisplay" );
81
82 /* ( addr len -- actual ) */
83 static void
84 stdout_write( void )
85 {
86         int len = POP();
87         char *addr = (char*)POP();
88
89         /* printk( "%s", s ); */
90         console_draw_fstr(addr, len);
91
92         PUSH( len );
93 }
94
95 NODE_METHODS( video_stdout ) = {
96         { "write",      stdout_write    },
97 };
98
99
100 /************************************************************************/
101 /*      tty                                                             */
102 /************************************************************************/
103
104 DECLARE_NODE( tty, INSTALL_OPEN, 0, "+/mol/mol-tty" );
105
106 /* ( addr len -- actual ) */
107 static void
108 tty_read( void )
109 {
110         int ch, len = POP();
111         char *p = (char*)POP();
112         int ret=0;
113
114         if( len > 0 ) {
115                 ret = 1;
116                 ch = OSI_TTYGetc();
117                 if( ch >= 0 ) {
118                         *p = ch;
119                 } else {
120                         ret = 0;
121                         OSI_USleep(1);
122                 }
123         }
124         PUSH( ret );
125 }
126
127 /* ( addr len -- actual ) */
128 static void
129 tty_write( void )
130 {
131         int i, len = POP();
132         char *p = (char*)POP();
133         for( i=0; i<len; i++ )
134                 OSI_TTYPutc( *p++ );
135         RET( len );
136 }
137
138 NODE_METHODS( tty ) = {
139         { "read",       tty_read        },
140         { "write",      tty_write       },
141 };
142
143
144 /************************************************************************/
145 /*      keyboard                                                        */
146 /************************************************************************/
147
148 typedef struct {
149         int     cntrl;
150         int     shift;
151         int     meta;
152         int     alt;
153         int     save_key;
154         char    keytable[32];
155 } kbd_state_t;
156
157 static const unsigned char adb_ascii_table[128] =
158         /* 0x00 */      "asdfhgzxcv`bqwer"
159         /* 0x10 */      "yt123465=97-80]o"
160         /* 0x20 */      "u[ip\nlj'k;\\,/nm."
161         /* 0x30 */      "\t <\b \e          "
162         /* 0x40 */      " . * +     /  - "
163         /* 0x50 */      " =01234567 89   "
164         /* 0x60 */      "                "
165         /* 0x70 */      "                ";
166
167 static const unsigned char adb_shift_table[128] =
168         /* 0x00 */      "ASDFHGZXCV~BQWER"
169         /* 0x10 */      "YT!@#$^%+(&_*)}O"
170         /* 0x20 */      "U{IP\nLJ\"K:|<?NM>"
171         /* 0x30 */      "\t <\b \e          "
172         /* 0x40 */      " . * +     /  - "
173         /* 0x50 */      " =01234567 89   "
174         /* 0x60 */      "                "
175         /* 0x70 */      "                ";
176
177 DECLARE_NODE( kbd, INSTALL_OPEN, sizeof(kbd_state_t),
178       "/psuedo-hid/keyboard",
179       "/mol/mol-keyboard",
180       "/mol/keyboard"
181 );
182
183 /* ( -- keymap ) (?) */
184 /* should return a pointer to an array with 32 bytes (256 bits) */
185 static void
186 kbd_get_key_map( kbd_state_t *ks )
187 {
188         /* printk("met_kbd_get_key_map\n"); */
189
190         /* keytable[5] = 0x40; */
191         PUSH( (int)ks->keytable );
192 }
193
194 /* ( buf len --- actlen ) */
195 static void
196 kbd_read( kbd_state_t *ks )
197 {
198         int ret=0, len = POP();
199         char *p = (char*)POP();
200         int key;
201
202         if( !p || !len ) {
203                 PUSH( -1 );
204                 return;
205         }
206
207         if( ks->save_key ) {
208                 *p = ks->save_key;
209                 ks->save_key = 0;
210                 RET( 1 );
211         }
212         OSI_USleep(1);  /* be nice */
213
214         for( ; (key=OSI_GetAdbKey()) >= 0 ; ) {
215                 int code = (key & 0x7f);
216                 int down = !(key & 0x80);
217
218                 if( code == 0x36 /* ctrl */ ) {
219                         ks->cntrl = down;
220                         continue;
221                 }
222                 if( code == 0x38 /* shift */ || code == 0x7b) {
223                         ks->shift = down;
224                         continue;
225                 }
226                 if( code == 0x37 /* command */ ) {
227                         ks->meta = down;
228                         continue;
229                 }
230                 if( code == 0x3a /* alt */ ) {
231                         ks->alt = down;
232                         continue;
233                 }
234                 if( !down )
235                         continue;
236
237                 ret = 1;
238                 if( ks->shift )
239                         key = adb_shift_table[ key & 0x7f ];
240                 else
241                         key = adb_ascii_table[ key & 0x7f ];
242
243                 if( ks->meta ) {
244                         ks->save_key = key;
245                         key = 27;
246                 } else if( ks->cntrl ) {
247                         key = key - 'a' + 1;
248                 }
249                 *p = key;
250                 if( !*p )
251                         *p = 'x';
252                 break;
253         }
254         PUSH( ret );
255 }
256
257 NODE_METHODS( kbd ) = {
258         { "read",               kbd_read                },
259         { "get-key-map",        kbd_get_key_map         },
260 };
261
262
263 /************************************************************************/
264 /*      client interface 'quiesce'                                      */
265 /************************************************************************/
266
267 DECLARE_NODE( ciface, 0, 0, "/packages/client-iface" );
268
269 /* ( -- ) */
270 static void
271 ciface_quiesce( unsigned long args[], unsigned long ret[] )
272 {
273 #if 0
274         unsigned long msr;
275         /* This seems to be the correct thing to do - but I'm not sure */
276         asm volatile("mfmsr %0" : "=r" (msr) : );
277         msr &= ~(MSR_IR | MSR_DR);
278         asm volatile("mtmsr %0" :: "r" (msr) );
279 #endif
280         printk("=============================================================\n\n");
281         prom_close();
282
283         OSI_KbdCntrl( kKbdCntrlSuspend );
284 }
285
286 /* ( -- ms ) */
287 static void
288 ciface_milliseconds( unsigned long args[], unsigned long ret[] )
289 {
290         static unsigned long mticks=0, usecs=0;
291         unsigned long t;
292
293         asm volatile("mftb %0" : "=r" (t) : );
294         if( mticks )
295                 usecs += OSI_MticksToUsecs( t-mticks );
296         mticks = t;
297
298         PUSH( usecs/1000 );
299 }
300
301
302 NODE_METHODS( ciface ) = {
303         { "quiesce",            ciface_quiesce          },
304         { "milliseconds",       ciface_milliseconds     },
305 };
306
307
308 /************************************************************************/
309 /*      MMU/memory methods                                              */
310 /************************************************************************/
311
312 DECLARE_NODE( memory, INSTALL_OPEN, 0, "/memory" );
313 DECLARE_NODE( mmu, INSTALL_OPEN, 0, "/cpus/@0" );
314 DECLARE_NODE( mmu_ciface, 0, 0, "/packages/client-iface" );
315
316
317 /* ( phys size align --- base ) */
318 static void
319 mem_claim( void )
320 {
321         ucell align = POP();
322         ucell size = POP();
323         ucell phys = POP();
324         ucell ret = ofmem_claim_phys( phys, size, align );
325
326         if( ret == -1 ) {
327                 printk("MEM: claim failure\n");
328                 throw( -13 );
329                 return;
330         }
331         PUSH( ret );
332 }
333
334 /* ( phys size --- ) */
335 static void
336 mem_release( void )
337 {
338         POP(); POP();
339 }
340
341 /* ( phys size align --- base ) */
342 static void
343 mmu_claim( void )
344 {
345         ucell align = POP();
346         ucell size = POP();
347         ucell phys = POP();
348         ucell ret = ofmem_claim_virt( phys, size, align );
349
350         if( ret == -1 ) {
351                 printk("MMU: CLAIM failure\n");
352                 throw( -13 );
353                 return;
354         }
355         PUSH( ret );
356 }
357
358 /* ( phys size --- ) */
359 static void
360 mmu_release( void )
361 {
362         POP(); POP();
363 }
364
365 /* ( phys virt size mode -- [ret???] ) */
366 static void
367 mmu_map( void )
368 {
369         ucell mode = POP();
370         ucell size = POP();
371         ucell virt = POP();
372         ucell phys = POP();
373         ucell ret;
374
375         /* printk("mmu_map: %x %x %x %x\n", phys, virt, size, mode ); */
376         ret = ofmem_map( phys, virt, size, mode );
377
378         if( ret ) {
379                 printk("MMU: map failure\n");
380                 throw( -13 );
381                 return;
382         }
383 }
384
385 /* ( virt size -- ) */
386 static void
387 mmu_unmap( void )
388 {
389         POP(); POP();
390 }
391
392 /* ( virt -- false | phys mode true ) */
393 static void
394 mmu_translate( void )
395 {
396         ucell mode;
397         ucell virt = POP();
398         ucell phys = ofmem_translate( virt, &mode );
399
400         if( phys == -1 ) {
401                 PUSH( 0 );
402         } else {
403                 PUSH( phys );
404                 PUSH( mode );
405                 PUSH( -1 );
406         }
407 }
408
409 /* ( virt size align -- baseaddr|-1 ) */
410 static void
411 ciface_claim( void )
412 {
413         ucell align = POP();
414         ucell size = POP();
415         ucell virt = POP();
416         ucell ret = ofmem_claim( virt, size, align );
417
418         /* printk("ciface_claim: %08x %08x %x\n", virt, size, align ); */
419         PUSH( ret );
420 }
421
422 /* ( virt size -- ) */
423 static void
424 ciface_release( void )
425 {
426         POP();
427         POP();
428 }
429
430
431 NODE_METHODS( memory ) = {
432         { "claim",              mem_claim               },
433         { "release",            mem_release             },
434 };
435
436 NODE_METHODS( mmu ) = {
437         { "claim",              mmu_claim               },
438         { "release",            mmu_release             },
439         { "map",                mmu_map                 },
440         { "unmap",              mmu_unmap               },
441         { "translate",          mmu_translate           },
442 };
443
444 NODE_METHODS( mmu_ciface ) = {
445         { "cif-claim",          ciface_claim            },
446         { "cif-release",        ciface_release          },
447 };
448
449
450 /************************************************************************/
451 /*      init                                                            */
452 /************************************************************************/
453
454 void
455 node_methods_init( void )
456 {
457         REGISTER_NODE( rtas );
458         REGISTER_NODE( powermgt );
459         REGISTER_NODE( kbd );
460         REGISTER_NODE( video_stdout );
461         REGISTER_NODE( ciface );
462         REGISTER_NODE( memory );
463         REGISTER_NODE( mmu );
464         REGISTER_NODE( mmu_ciface );
465
466         if( OSI_CallAvailable(OSI_TTY_GETC) )
467                 REGISTER_NODE( tty );
468
469         OSI_KbdCntrl( kKbdCntrlActivate );
470 }