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
set_hybernot_flag(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
rtas_instantiate(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
stdout_write(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
tty_read(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
tty_write(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
kbd_get_key_map(kbd_state_t * ks)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
kbd_read(kbd_state_t * ks)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
ciface_quiesce(unsigned long args[],unsigned long ret[])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
ciface_milliseconds(unsigned long args[],unsigned long ret[])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
mem_claim(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
mem_release(void)336 mem_release( void )
337 {
338 POP(); POP();
339 }
340
341 /* ( phys size align --- base ) */
342 static void
mmu_claim(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
mmu_release(void)360 mmu_release( void )
361 {
362 POP(); POP();
363 }
364
365 /* ( phys virt size mode -- [ret???] ) */
366 static void
mmu_map(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
mmu_unmap(void)387 mmu_unmap( void )
388 {
389 POP(); POP();
390 }
391
392 /* ( virt -- false | phys mode true ) */
393 static void
mmu_translate(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
ciface_claim(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
ciface_release(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
node_methods_init(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 }
471