|
|
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.