|
|
1.1 ! root 1: /* tag: openbios forth environment, executable code ! 2: * ! 3: * Copyright (C) 2003 Patrick Mauritz, Stefan Reinauer ! 4: * ! 5: * See the file "COPYING" for further information about ! 6: * the copyright and warranty status of this work. ! 7: */ ! 8: ! 9: #include "config.h" ! 10: #include "libopenbios/openbios.h" ! 11: #include "libopenbios/bindings.h" ! 12: #include "drivers/drivers.h" ! 13: #include "dict.h" ! 14: #include "arch/common/nvram.h" ! 15: #include "packages/nvram.h" ! 16: #include "libopenbios/sys_info.h" ! 17: #include "openbios.h" ! 18: #include "drivers/pci.h" ! 19: #include "asm/pci.h" ! 20: #include "boot.h" ! 21: #include "../../drivers/timer.h" // XXX ! 22: #define NO_QEMU_PROTOS ! 23: #include "arch/common/fw_cfg.h" ! 24: #include "libopenbios/ofmem.h" ! 25: ! 26: #define UUID_FMT "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x" ! 27: ! 28: #define NVRAM_ADDR_LO 0x74 ! 29: #define NVRAM_ADDR_HI 0x75 ! 30: #define NVRAM_DATA 0x77 ! 31: ! 32: #define APB_SPECIAL_BASE 0x1fe00000000ULL ! 33: #define APB_MEM_BASE 0x1ff00000000ULL ! 34: ! 35: #define MEMORY_SIZE (512*1024) /* 512K ram for hosted system */ ! 36: ! 37: static ucell *memory; ! 38: ! 39: // XXX ! 40: #define NVRAM_SIZE 0x2000 ! 41: #define NVRAM_IDPROM 0x1fd8 ! 42: #define NVRAM_IDPROM_SIZE 32 ! 43: #define NVRAM_OB_START (0) ! 44: #define NVRAM_OB_SIZE ((0x1fd0 - NVRAM_OB_START) & ~15) ! 45: ! 46: #define OBIO_CMDLINE_MAX 256 ! 47: static char obio_cmdline[OBIO_CMDLINE_MAX]; ! 48: ! 49: static uint8_t idprom[NVRAM_IDPROM_SIZE]; ! 50: ! 51: struct hwdef { ! 52: pci_arch_t pci; ! 53: uint16_t machine_id_low, machine_id_high; ! 54: }; ! 55: ! 56: static const struct hwdef hwdefs[] = { ! 57: { ! 58: .pci = { ! 59: .name = "SUNW,sabre", ! 60: .vendor_id = PCI_VENDOR_ID_SUN, ! 61: .device_id = PCI_DEVICE_ID_SUN_SABRE, ! 62: .cfg_addr = APB_SPECIAL_BASE + 0x1000000ULL, // PCI bus configuration space ! 63: .cfg_data = APB_MEM_BASE, // PCI bus memory space ! 64: .cfg_base = APB_SPECIAL_BASE, ! 65: .cfg_len = 0x2000000, ! 66: .host_mem_base = APB_MEM_BASE, ! 67: .pci_mem_base = 0, ! 68: .mem_len = 0x10000000, ! 69: .io_base = APB_SPECIAL_BASE + 0x2000000ULL, // PCI Bus I/O space ! 70: .io_len = 0x10000, ! 71: .irqs = { 0, 1, 2, 3 }, ! 72: }, ! 73: .machine_id_low = 0, ! 74: .machine_id_high = 255, ! 75: }, ! 76: }; ! 77: ! 78: struct cpudef { ! 79: unsigned long iu_version; ! 80: const char *name; ! 81: unsigned long ecache_associativity; ! 82: unsigned long ecache_line_size; ! 83: unsigned long ecache_size; ! 84: unsigned long num_dtlb_entries; ! 85: unsigned long dcache_associativity; ! 86: unsigned long dcache_line_size; ! 87: unsigned long dcache_size; ! 88: unsigned long num_itlb_entries; ! 89: unsigned long icache_associativity; ! 90: unsigned long icache_line_size; ! 91: unsigned long icache_size; ! 92: }; ! 93: ! 94: /* ! 95: ( addr -- ? ) ! 96: */ ! 97: static void ! 98: set_trap_table(void) ! 99: { ! 100: unsigned long addr; ! 101: ! 102: addr = POP(); ! 103: asm("wrpr %0, %%tba\n" ! 104: : : "r" (addr)); ! 105: } ! 106: ! 107: /* Reset control register is defined in 17.2.7.3 of US IIi User Manual */ ! 108: static void ! 109: sparc64_reset_all(void) ! 110: { ! 111: unsigned long addr = 0x1fe0000f020ULL; ! 112: unsigned long val = 1 << 29; ! 113: ! 114: asm("stxa %0, [%1] 0x15\n\t" ! 115: : : "r" (val), "r" (addr) : "memory"); ! 116: } ! 117: ! 118: static void cpu_generic_init(const struct cpudef *cpu, uint32_t clock_frequency) ! 119: { ! 120: unsigned long iu_version; ! 121: ! 122: push_str("/"); ! 123: fword("find-device"); ! 124: ! 125: fword("new-device"); ! 126: ! 127: push_str(cpu->name); ! 128: fword("device-name"); ! 129: ! 130: push_str("cpu"); ! 131: fword("device-type"); ! 132: ! 133: asm("rdpr %%ver, %0\n" ! 134: : "=r"(iu_version) :); ! 135: ! 136: PUSH((iu_version >> 48) & 0xff); ! 137: fword("encode-int"); ! 138: push_str("manufacturer#"); ! 139: fword("property"); ! 140: ! 141: PUSH((iu_version >> 32) & 0xff); ! 142: fword("encode-int"); ! 143: push_str("implementation#"); ! 144: fword("property"); ! 145: ! 146: PUSH((iu_version >> 24) & 0xff); ! 147: fword("encode-int"); ! 148: push_str("mask#"); ! 149: fword("property"); ! 150: ! 151: PUSH(9); ! 152: fword("encode-int"); ! 153: push_str("sparc-version"); ! 154: fword("property"); ! 155: ! 156: PUSH(0); ! 157: fword("encode-int"); ! 158: push_str("cpuid"); ! 159: fword("property"); ! 160: ! 161: PUSH(0); ! 162: fword("encode-int"); ! 163: push_str("upa-portid"); ! 164: fword("property"); ! 165: ! 166: PUSH(clock_frequency); ! 167: fword("encode-int"); ! 168: push_str("clock-frequency"); ! 169: fword("property"); ! 170: ! 171: PUSH(cpu->ecache_associativity); ! 172: fword("encode-int"); ! 173: push_str("ecache-associativity"); ! 174: fword("property"); ! 175: ! 176: PUSH(cpu->ecache_line_size); ! 177: fword("encode-int"); ! 178: push_str("ecache-line-size"); ! 179: fword("property"); ! 180: ! 181: PUSH(cpu->ecache_size); ! 182: fword("encode-int"); ! 183: push_str("ecache-size"); ! 184: fword("property"); ! 185: ! 186: PUSH(cpu->dcache_associativity); ! 187: fword("encode-int"); ! 188: push_str("dcache-associativity"); ! 189: fword("property"); ! 190: ! 191: PUSH(cpu->dcache_line_size); ! 192: fword("encode-int"); ! 193: push_str("dcache-line-size"); ! 194: fword("property"); ! 195: ! 196: PUSH(cpu->dcache_size); ! 197: fword("encode-int"); ! 198: push_str("dcache-size"); ! 199: fword("property"); ! 200: ! 201: PUSH(cpu->icache_associativity); ! 202: fword("encode-int"); ! 203: push_str("icache-associativity"); ! 204: fword("property"); ! 205: ! 206: PUSH(cpu->ecache_line_size); ! 207: fword("encode-int"); ! 208: push_str("icache-line-size"); ! 209: fword("property"); ! 210: ! 211: PUSH(cpu->ecache_size); ! 212: fword("encode-int"); ! 213: push_str("icache-size"); ! 214: fword("property"); ! 215: ! 216: PUSH(cpu->num_itlb_entries); ! 217: fword("encode-int"); ! 218: push_str("#itlb-entries"); ! 219: fword("property"); ! 220: ! 221: PUSH(cpu->num_dtlb_entries); ! 222: fword("encode-int"); ! 223: push_str("#dtlb-entries"); ! 224: fword("property"); ! 225: ! 226: fword("finish-device"); ! 227: ! 228: // Trap table ! 229: push_str("/openprom/client-services"); ! 230: fword("find-device"); ! 231: bind_func("SUNW,set-trap-table", set_trap_table); ! 232: ! 233: // Reset ! 234: bind_func("sparc64-reset-all", sparc64_reset_all); ! 235: push_str("' sparc64-reset-all to reset-all"); ! 236: fword("eval"); ! 237: } ! 238: ! 239: static const struct cpudef sparc_defs[] = { ! 240: { ! 241: .iu_version = (0x04ULL << 48) | (0x02ULL << 32), ! 242: .name = "FJSV,GP", ! 243: }, ! 244: { ! 245: .iu_version = (0x04ULL << 48) | (0x03ULL << 32), ! 246: .name = "FJSV,GPUSK", ! 247: }, ! 248: { ! 249: .iu_version = (0x04ULL << 48) | (0x04ULL << 32), ! 250: .name = "FJSV,GPUSC", ! 251: }, ! 252: { ! 253: .iu_version = (0x04ULL << 48) | (0x05ULL << 32), ! 254: .name = "FJSV,GPUZC", ! 255: }, ! 256: { ! 257: .iu_version = (0x17ULL << 48) | (0x10ULL << 32), ! 258: .name = "SUNW,UltraSPARC", ! 259: .ecache_associativity = 1, .ecache_line_size = 0x40, .ecache_size = 0x100000, ! 260: .dcache_associativity = 1, .dcache_line_size = 0x20, .dcache_size = 0x4000, ! 261: .icache_associativity = 2, .icache_line_size = 0x20, .icache_size = 0x4000, ! 262: .num_dtlb_entries = 0x40, .num_itlb_entries = 0x40, ! 263: }, ! 264: { ! 265: .iu_version = (0x17ULL << 48) | (0x11ULL << 32), ! 266: .name = "SUNW,UltraSPARC-II", ! 267: .ecache_associativity = 1, .ecache_line_size = 0x40, .ecache_size = 0x100000, ! 268: .dcache_associativity = 1, .dcache_line_size = 0x20, .dcache_size = 0x4000, ! 269: .icache_associativity = 2, .icache_line_size = 0x20, .icache_size = 0x4000, ! 270: .num_dtlb_entries = 0x40, .num_itlb_entries = 0x40, ! 271: }, ! 272: { ! 273: .iu_version = (0x17ULL << 48) | (0x12ULL << 32), ! 274: .name = "SUNW,UltraSPARC-IIi", ! 275: .ecache_associativity = 1, .ecache_line_size = 0x40, .ecache_size = 0x40000, ! 276: .dcache_associativity = 1, .dcache_line_size = 0x20, .dcache_size = 0x4000, ! 277: .icache_associativity = 2, .icache_line_size = 0x20, .icache_size = 0x4000, ! 278: .num_dtlb_entries = 0x40, .num_itlb_entries = 0x40, ! 279: }, ! 280: { ! 281: .iu_version = (0x17ULL << 48) | (0x13ULL << 32), ! 282: .name = "SUNW,UltraSPARC-IIe", ! 283: }, ! 284: { ! 285: .iu_version = (0x3eULL << 48) | (0x14ULL << 32), ! 286: .name = "SUNW,UltraSPARC-III", ! 287: }, ! 288: { ! 289: .iu_version = (0x3eULL << 48) | (0x15ULL << 32), ! 290: .name = "SUNW,UltraSPARC-III+", ! 291: }, ! 292: { ! 293: .iu_version = (0x3eULL << 48) | (0x16ULL << 32), ! 294: .name = "SUNW,UltraSPARC-IIIi", ! 295: }, ! 296: { ! 297: .iu_version = (0x3eULL << 48) | (0x18ULL << 32), ! 298: .name = "SUNW,UltraSPARC-IV", ! 299: }, ! 300: { ! 301: .iu_version = (0x3eULL << 48) | (0x19ULL << 32), ! 302: .name = "SUNW,UltraSPARC-IV+", ! 303: }, ! 304: { ! 305: .iu_version = (0x3eULL << 48) | (0x22ULL << 32), ! 306: .name = "SUNW,UltraSPARC-IIIi+", ! 307: }, ! 308: { ! 309: .iu_version = (0x3eULL << 48) | (0x23ULL << 32), ! 310: .name = "SUNW,UltraSPARC-T1", ! 311: }, ! 312: { ! 313: .iu_version = (0x3eULL << 48) | (0x24ULL << 32), ! 314: .name = "SUNW,UltraSPARC-T2", ! 315: }, ! 316: { ! 317: .iu_version = (0x22ULL << 48) | (0x10ULL << 32), ! 318: .name = "SUNW,UltraSPARC", ! 319: }, ! 320: }; ! 321: ! 322: static const struct cpudef * ! 323: id_cpu(void) ! 324: { ! 325: unsigned long iu_version; ! 326: unsigned int i; ! 327: ! 328: asm("rdpr %%ver, %0\n" ! 329: : "=r"(iu_version) :); ! 330: iu_version &= 0xffffffff00000000ULL; ! 331: ! 332: for (i = 0; i < sizeof(sparc_defs)/sizeof(struct cpudef); i++) { ! 333: if (iu_version == sparc_defs[i].iu_version) ! 334: return &sparc_defs[i]; ! 335: } ! 336: printk("Unknown cpu (psr %lx), freezing!\n", iu_version); ! 337: for (;;); ! 338: } ! 339: ! 340: static uint8_t nvram_read_byte(uint16_t offset) ! 341: { ! 342: outb(offset & 0xff, NVRAM_ADDR_LO); ! 343: outb(offset >> 8, NVRAM_ADDR_HI); ! 344: return inb(NVRAM_DATA); ! 345: } ! 346: ! 347: static void nvram_read(uint16_t offset, char *buf, unsigned int nbytes) ! 348: { ! 349: unsigned int i; ! 350: ! 351: for (i = 0; i < nbytes; i++) ! 352: buf[i] = nvram_read_byte(offset + i); ! 353: } ! 354: ! 355: static void nvram_write_byte(uint16_t offset, uint8_t val) ! 356: { ! 357: outb(offset & 0xff, NVRAM_ADDR_LO); ! 358: outb(offset >> 8, NVRAM_ADDR_HI); ! 359: outb(val, NVRAM_DATA); ! 360: } ! 361: ! 362: static void nvram_write(uint16_t offset, const char *buf, unsigned int nbytes) ! 363: { ! 364: unsigned int i; ! 365: ! 366: for (i = 0; i < nbytes; i++) ! 367: nvram_write_byte(offset + i, buf[i]); ! 368: } ! 369: ! 370: static uint8_t qemu_uuid[16]; ! 371: ! 372: void arch_nvram_get(char *data) ! 373: { ! 374: uint32_t size = 0; ! 375: const struct cpudef *cpu; ! 376: char buf[256]; ! 377: uint32_t temp; ! 378: uint64_t ram_size; ! 379: uint32_t clock_frequency; ! 380: uint16_t machine_id; ! 381: const char *stdin_path, *stdout_path; ! 382: ! 383: fw_cfg_init(); ! 384: ! 385: fw_cfg_read(FW_CFG_SIGNATURE, buf, 4); ! 386: buf[4] = '\0'; ! 387: ! 388: printk("Configuration device id %s", buf); ! 389: ! 390: temp = fw_cfg_read_i32(FW_CFG_ID); ! 391: machine_id = fw_cfg_read_i16(FW_CFG_MACHINE_ID); ! 392: ! 393: printk(" version %d machine id %d\n", temp, machine_id); ! 394: ! 395: if (temp != 1) { ! 396: printk("Incompatible configuration device version, freezing\n"); ! 397: for(;;); ! 398: } ! 399: ! 400: kernel_size = fw_cfg_read_i32(FW_CFG_KERNEL_SIZE); ! 401: if (kernel_size) ! 402: kernel_image = fw_cfg_read_i64(FW_CFG_KERNEL_ADDR); ! 403: ! 404: size = fw_cfg_read_i32(FW_CFG_CMDLINE_SIZE); ! 405: if (size > OBIO_CMDLINE_MAX - 1) ! 406: size = OBIO_CMDLINE_MAX - 1; ! 407: if (size) { ! 408: fw_cfg_read(FW_CFG_CMDLINE_DATA, obio_cmdline, size); ! 409: } ! 410: obio_cmdline[size] = '\0'; ! 411: qemu_cmdline = (uint64_t)obio_cmdline; ! 412: cmdline_size = size; ! 413: boot_device = fw_cfg_read_i16(FW_CFG_BOOT_DEVICE); ! 414: ! 415: if (kernel_size) ! 416: printk("kernel addr %llx size %llx\n", kernel_image, kernel_size); ! 417: if (size) ! 418: printk("kernel cmdline %s\n", obio_cmdline); ! 419: ! 420: nvram_read(NVRAM_OB_START, data, NVRAM_OB_SIZE); ! 421: ! 422: temp = fw_cfg_read_i32(FW_CFG_NB_CPUS); ! 423: ! 424: printk("CPUs: %x", temp); ! 425: ! 426: clock_frequency = 100000000; ! 427: ! 428: cpu = id_cpu(); ! 429: //cpu->initfn(); ! 430: cpu_generic_init(cpu, clock_frequency); ! 431: printk(" x %s\n", cpu->name); ! 432: ! 433: // Add /uuid ! 434: fw_cfg_read(FW_CFG_UUID, (char *)qemu_uuid, 16); ! 435: ! 436: printk("UUID: " UUID_FMT "\n", qemu_uuid[0], qemu_uuid[1], qemu_uuid[2], ! 437: qemu_uuid[3], qemu_uuid[4], qemu_uuid[5], qemu_uuid[6], ! 438: qemu_uuid[7], qemu_uuid[8], qemu_uuid[9], qemu_uuid[10], ! 439: qemu_uuid[11], qemu_uuid[12], qemu_uuid[13], qemu_uuid[14], ! 440: qemu_uuid[15]); ! 441: ! 442: push_str("/"); ! 443: fword("find-device"); ! 444: ! 445: PUSH((long)&qemu_uuid); ! 446: PUSH(16); ! 447: fword("encode-bytes"); ! 448: push_str("uuid"); ! 449: fword("property"); ! 450: ! 451: // Add /idprom ! 452: nvram_read(NVRAM_IDPROM, (char *)idprom, NVRAM_IDPROM_SIZE); ! 453: ! 454: PUSH((long)&idprom); ! 455: PUSH(32); ! 456: fword("encode-bytes"); ! 457: push_str("idprom"); ! 458: fword("property"); ! 459: ! 460: PUSH(500 * 1000 * 1000); ! 461: fword("encode-int"); ! 462: push_str("clock-frequency"); ! 463: fword("property"); ! 464: ! 465: ram_size = fw_cfg_read_i64(FW_CFG_RAM_SIZE); ! 466: ! 467: ob_mmu_init(cpu->name, ram_size); ! 468: ! 469: /* Setup nvram variables */ ! 470: push_str("/options"); ! 471: fword("find-device"); ! 472: ! 473: switch (boot_device) { ! 474: case 'a': ! 475: push_str("/obio/SUNW,fdtwo"); ! 476: break; ! 477: case 'c': ! 478: push_str("disk:a"); ! 479: break; ! 480: default: ! 481: case 'd': ! 482: push_str("cdrom:f cdrom"); ! 483: break; ! 484: case 'n': ! 485: push_str("net"); ! 486: break; ! 487: } ! 488: ! 489: fword("encode-string"); ! 490: push_str("boot-device"); ! 491: fword("property"); ! 492: ! 493: push_str(obio_cmdline); ! 494: fword("encode-string"); ! 495: push_str("boot-file"); ! 496: fword("property"); ! 497: ! 498: /* Set up other properties */ ! 499: push_str("/chosen"); ! 500: fword("find-device"); ! 501: ! 502: if (fw_cfg_read_i16(FW_CFG_NOGRAPHIC)) { ! 503: stdin_path = stdout_path = "ttya"; ! 504: } else { ! 505: stdin_path = "keyboard"; ! 506: stdout_path = "screen"; ! 507: } ! 508: ! 509: push_str(stdin_path); ! 510: fword("open-dev"); ! 511: fword("encode-int"); ! 512: push_str("stdin"); ! 513: fword("property"); ! 514: ! 515: push_str(stdout_path); ! 516: fword("open-dev"); ! 517: fword("encode-int"); ! 518: push_str("stdout"); ! 519: fword("property"); ! 520: ! 521: push_str(stdin_path); ! 522: push_str("input-device"); ! 523: fword("$setenv"); ! 524: ! 525: push_str(stdout_path); ! 526: push_str("output-device"); ! 527: fword("$setenv"); ! 528: ! 529: push_str(stdin_path); ! 530: fword("input"); ! 531: ! 532: push_str(stdout_path); ! 533: fword("output"); ! 534: } ! 535: ! 536: void arch_nvram_put(char *data) ! 537: { ! 538: nvram_write(0, data, NVRAM_OB_SIZE); ! 539: } ! 540: ! 541: int arch_nvram_size(void) ! 542: { ! 543: return NVRAM_OB_SIZE; ! 544: } ! 545: ! 546: void setup_timers(void) ! 547: { ! 548: } ! 549: ! 550: void udelay(unsigned int usecs) ! 551: { ! 552: } ! 553: ! 554: static void init_memory(void) ! 555: { ! 556: memory = malloc(MEMORY_SIZE); ! 557: if (!memory) ! 558: printk("panic: not enough memory on host system.\n"); ! 559: ! 560: /* we push start and end of memory to the stack ! 561: * so that it can be used by the forth word QUIT ! 562: * to initialize the memory allocator ! 563: */ ! 564: ! 565: PUSH((ucell)memory); ! 566: PUSH((ucell)memory + (ucell)MEMORY_SIZE); ! 567: } ! 568: ! 569: static void ! 570: arch_init( void ) ! 571: { ! 572: openbios_init(); ! 573: modules_init(); ! 574: #ifdef CONFIG_DRIVER_PCI ! 575: ob_pci_init(); ! 576: #endif ! 577: nvconf_init(); ! 578: device_end(); ! 579: ! 580: bind_func("platform-boot", boot ); ! 581: bind_func("(go)", go); ! 582: } ! 583: ! 584: unsigned long isa_io_base; ! 585: ! 586: int openbios(void) ! 587: { ! 588: unsigned int i; ! 589: uint16_t machine_id; ! 590: const struct hwdef *hwdef = NULL; ! 591: ! 592: ! 593: for (i = 0; i < sizeof(hwdefs) / sizeof(struct hwdef); i++) { ! 594: isa_io_base = hwdefs[i].pci.io_base; ! 595: machine_id = fw_cfg_read_i16(FW_CFG_MACHINE_ID); ! 596: if (hwdefs[i].machine_id_low <= machine_id && ! 597: hwdefs[i].machine_id_high >= machine_id) { ! 598: hwdef = &hwdefs[i]; ! 599: arch = &hwdefs[i].pci; ! 600: break; ! 601: } ! 602: } ! 603: if (!hwdef) ! 604: for(;;); // Internal inconsistency, hang ! 605: ! 606: #ifdef CONFIG_DEBUG_CONSOLE ! 607: #ifdef CONFIG_DEBUG_CONSOLE_SERIAL ! 608: uart_init(CONFIG_SERIAL_PORT, CONFIG_SERIAL_SPEED); ! 609: #endif ! 610: /* Clear the screen. */ ! 611: cls(); ! 612: printk("OpenBIOS for Sparc64\n"); ! 613: #endif ! 614: ! 615: ofmem_init(); ! 616: ! 617: collect_sys_info(&sys_info); ! 618: ! 619: dict = (unsigned char *)sys_info.dict_start; ! 620: dicthead = (cell)sys_info.dict_end; ! 621: last = sys_info.dict_last; ! 622: dictlimit = sys_info.dict_limit; ! 623: ! 624: forth_init(); ! 625: ! 626: #ifdef CONFIG_DEBUG_BOOT ! 627: printk("forth started.\n"); ! 628: printk("initializing memory..."); ! 629: #endif ! 630: ! 631: init_memory(); ! 632: ! 633: #ifdef CONFIG_DEBUG_BOOT ! 634: printk("done\n"); ! 635: #endif ! 636: ! 637: PUSH_xt( bind_noname_func(arch_init) ); ! 638: fword("PREPOST-initializer"); ! 639: ! 640: PC = (ucell)findword("initialize-of"); ! 641: ! 642: if (!PC) { ! 643: printk("panic: no dictionary entry point.\n"); ! 644: return -1; ! 645: } ! 646: #ifdef CONFIG_DEBUG_DICTIONARY ! 647: printk("done (%d bytes).\n", dicthead); ! 648: printk("Jumping to dictionary...\n"); ! 649: #endif ! 650: ! 651: enterforth((xt_t)PC); ! 652: printk("falling off...\n"); ! 653: free(dict); ! 654: return 0; ! 655: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.