|
|
1.1 root 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 ([email protected])
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.