ppc: Add RTAS rtas-version property
[openbios/afaerber.git] / arch / ppc / qemu / init.c
blobbfd147afb3cf63aa24785fac4281343d0cf65fd5
1 /*
2 * Creation Date: <2004/08/28 18:38:22 greg>
3 * Time-stamp: <2004/08/28 18:38:22 greg>
5 * <init.c>
7 * Initialization for qemu
9 * Copyright (C) 2004 Greg Watson
10 * Copyright (C) 2005 Stefan Reinauer
12 * based on mol/init.c:
14 * Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004 Samuel & David Rydh
15 * (samuel@ibrium.se, dary@lindesign.se)
17 * This program is free software; you can redistribute it and/or
18 * modify it under the terms of the GNU General Public License
19 * as published by the Free Software Foundation
23 #include "config.h"
24 #include "libopenbios/openbios.h"
25 #include "libopenbios/bindings.h"
26 #include "drivers/pci.h"
27 #include "arch/common/nvram.h"
28 #include "drivers/drivers.h"
29 #include "qemu/qemu.h"
30 #include "libopenbios/ofmem.h"
31 #include "openbios-version.h"
32 #include "libc/byteorder.h"
33 #include "libc/vsprintf.h"
34 #define NO_QEMU_PROTOS
35 #include "arch/common/fw_cfg.h"
36 #include "arch/ppc/processor.h"
38 #define UUID_FMT "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x"
40 struct cpudef {
41 unsigned long iu_version;
42 const char *name;
43 int icache_size, dcache_size;
44 int icache_sets, dcache_sets;
45 int icache_block_size, dcache_block_size;
46 int clock_frequency;
47 void (*initfn)(const struct cpudef *cpu);
50 static uint16_t machine_id = 0;
52 extern void unexpected_excep( int vector );
54 void
55 unexpected_excep( int vector )
57 printk("openbios panic: Unexpected exception %x\n", vector );
58 for( ;; )
62 enum {
63 ARCH_PREP = 0,
64 ARCH_MAC99,
65 ARCH_HEATHROW,
66 ARCH_MAC99_U3,
69 int is_apple(void)
71 return 1;
74 int is_oldworld(void)
76 return machine_id == ARCH_HEATHROW;
79 int is_newworld(void)
81 return (machine_id == ARCH_MAC99) ||
82 (machine_id == ARCH_MAC99_U3);
85 static const pci_arch_t known_arch[] = {
86 [ARCH_PREP] = {
87 .name = "PREP",
88 .vendor_id = PCI_VENDOR_ID_MOTOROLA,
89 .device_id = PCI_DEVICE_ID_MOTOROLA_RAVEN,
90 .cfg_addr = 0x80800000,
91 .cfg_data = 0x800c0000,
92 .cfg_base = 0x80000000,
93 .cfg_len = 0x00100000,
94 .host_mem_base = 0xf0000000,
95 .pci_mem_base = 0xf0000000,
96 .mem_len = 0x10000000,
97 .io_base = 0x80000000,
98 .io_len = 0x00010000,
99 .rbase = 0x00000000,
100 .rlen = 0x00400000,
101 .irqs = { 9, 11, 9, 11 }
103 [ARCH_MAC99] = {
104 .name = "MAC99",
105 .vendor_id = PCI_VENDOR_ID_APPLE,
106 .device_id = PCI_DEVICE_ID_APPLE_UNI_N_PCI,
107 .cfg_addr = 0xf2800000,
108 .cfg_data = 0xf2c00000,
109 .cfg_base = 0xf2000000,
110 .cfg_len = 0x02000000,
111 .host_mem_base = 0x80000000,
112 .pci_mem_base = 0x80000000,
113 .mem_len = 0x10000000,
114 .io_base = 0xf2000000,
115 .io_len = 0x00800000,
116 .rbase = 0x00000000,
117 .rlen = 0x01000000,
118 .irqs = { 0x1b, 0x1c, 0x1d, 0x1e }
120 [ARCH_MAC99_U3] = {
121 .name = "MAC99_U3",
122 .vendor_id = PCI_VENDOR_ID_APPLE,
123 .device_id = PCI_DEVICE_ID_APPLE_U3_AGP,
124 .cfg_addr = 0xf0800000,
125 .cfg_data = 0xf0c00000,
126 .cfg_base = 0xf0000000,
127 .cfg_len = 0x02000000,
128 .host_mem_base = 0x80000000,
129 .pci_mem_base = 0x80000000,
130 .mem_len = 0x10000000,
131 .io_base = 0xf2000000,
132 .io_len = 0x00800000,
133 .rbase = 0x00000000,
134 .rlen = 0x01000000,
135 .irqs = { 0x1b, 0x1c, 0x1d, 0x1e }
137 [ARCH_HEATHROW] = {
138 .name = "HEATHROW",
139 .vendor_id = PCI_VENDOR_ID_MOTOROLA,
140 .device_id = PCI_DEVICE_ID_MOTOROLA_MPC106,
141 .cfg_addr = 0xfec00000,
142 .cfg_data = 0xfee00000,
143 .cfg_base = 0x80000000,
144 .cfg_len = 0x7f000000,
145 .host_mem_base = 0x80000000,
146 .pci_mem_base = 0x80000000,
147 .mem_len = 0x01000000,
148 .io_base = 0xfe000000,
149 .io_len = 0x00800000,
150 .rbase = 0xfd000000,
151 .rlen = 0x01000000,
152 .irqs = { 21, 22, 23, 24 }
155 uint32_t isa_io_base;
157 void
158 entry( void )
160 uint32_t temp = 0;
161 char buf[5];
163 arch = &known_arch[ARCH_HEATHROW];
165 fw_cfg_init();
167 fw_cfg_read(FW_CFG_SIGNATURE, buf, 4);
168 buf[4] = '\0';
169 if (strncmp(buf, "QEMU", 4) == 0) {
170 temp = fw_cfg_read_i32(FW_CFG_ID);
171 if (temp == 1) {
172 machine_id = fw_cfg_read_i16(FW_CFG_MACHINE_ID);
173 arch = &known_arch[machine_id];
177 isa_io_base = arch->io_base;
179 if (temp != 1) {
180 printk("Incompatible configuration device version, freezing\n");
181 for(;;);
184 ofmem_init();
185 initialize_forth();
186 /* won't return */
188 printk("of_startup returned!\n");
189 for( ;; )
193 static void
194 cpu_generic_init(const struct cpudef *cpu)
196 unsigned long iu_version;
198 push_str("/cpus");
199 fword("find-device");
201 fword("new-device");
203 push_str(cpu->name);
204 fword("device-name");
206 push_str("cpu");
207 fword("device-type");
209 asm("mfpvr %0\n"
210 : "=r"(iu_version) :);
211 PUSH(iu_version);
212 fword("encode-int");
213 push_str("cpu-version");
214 fword("property");
216 PUSH(cpu->dcache_size);
217 fword("encode-int");
218 push_str("dcache-size");
219 fword("property");
221 PUSH(cpu->icache_size);
222 fword("encode-int");
223 push_str("icache-size");
224 fword("property");
226 PUSH(cpu->dcache_sets);
227 fword("encode-int");
228 push_str("dcache-sets");
229 fword("property");
231 PUSH(cpu->icache_sets);
232 fword("encode-int");
233 push_str("icache-sets");
234 fword("property");
236 PUSH(cpu->dcache_block_size);
237 fword("encode-int");
238 push_str("dcache-block-size");
239 fword("property");
241 PUSH(cpu->icache_block_size);
242 fword("encode-int");
243 push_str("icache-block-size");
244 fword("property");
246 PUSH(fw_cfg_read_i32(FW_CFG_PPC_TBFREQ));
247 fword("encode-int");
248 push_str("timebase-frequency");
249 fword("property");
251 PUSH(fw_cfg_read_i32(FW_CFG_PPC_CPUFREQ));
252 fword("encode-int");
253 push_str("clock-frequency");
254 fword("property");
256 push_str("running");
257 fword("encode-string");
258 push_str("state");
259 fword("property");
262 static void
263 cpu_add_pir_property(void)
265 unsigned long pir;
267 asm("mfspr %0, 1023\n"
268 : "=r"(pir) :);
269 PUSH(pir);
270 fword("encode-int");
271 push_str("reg");
272 fword("property");
275 static void
276 cpu_604_init(const struct cpudef *cpu)
278 cpu_generic_init(cpu);
279 cpu_add_pir_property();
281 fword("finish-device");
284 static void
285 cpu_750_init(const struct cpudef *cpu)
287 cpu_generic_init(cpu);
289 PUSH(0);
290 fword("encode-int");
291 push_str("reg");
292 fword("property");
294 fword("finish-device");
297 static void
298 cpu_g4_init(const struct cpudef *cpu)
300 cpu_generic_init(cpu);
301 cpu_add_pir_property();
303 fword("finish-device");
306 /* In order to get 64 bit aware handlers that rescue all our
307 GPRs from getting truncated to 32 bits, we need to patch the
308 existing handlers so they jump to our 64 bit aware ones. */
309 static void
310 ppc64_patch_handlers(void)
312 uint32_t *dsi = (uint32_t *)0x300UL;
313 uint32_t *isi = (uint32_t *)0x400UL;
315 // Patch the first DSI handler instruction to: ba 0x2000
316 *dsi = 0x48002002;
318 // Patch the first ISI handler instruction to: ba 0x2200
319 *isi = 0x48002202;
321 // Invalidate the cache lines
322 asm ( "icbi 0, %0" : : "r"(dsi) );
323 asm ( "icbi 0, %0" : : "r"(isi) );
326 static void
327 cpu_970_init(const struct cpudef *cpu)
329 cpu_generic_init(cpu);
331 PUSH(0);
332 fword("encode-int");
333 push_str("reg");
334 fword("property");
336 PUSH(0);
337 PUSH(0);
338 fword("encode-bytes");
339 push_str("64-bit");
340 fword("property");
342 fword("finish-device");
344 /* The 970 is a PPC64 CPU, so we need to activate
345 * 64bit aware interrupt handlers */
347 ppc64_patch_handlers();
349 /* The 970 also implements the HIOR which we need to set to 0 */
351 mtspr(S_HIOR, 0);
354 static const struct cpudef ppc_defs[] = {
356 .iu_version = 0x00040000,
357 .name = "PowerPC,604",
358 .icache_size = 0x4000,
359 .dcache_size = 0x4000,
360 .icache_sets = 0x80,
361 .dcache_sets = 0x80,
362 .icache_block_size = 0x20,
363 .dcache_block_size = 0x20,
364 .clock_frequency = 0x07de2900,
365 .initfn = cpu_604_init,
367 { // XXX find out real values
368 .iu_version = 0x00090000,
369 .name = "PowerPC,604e",
370 .icache_size = 0x4000,
371 .dcache_size = 0x4000,
372 .icache_sets = 0x80,
373 .dcache_sets = 0x80,
374 .icache_block_size = 0x20,
375 .dcache_block_size = 0x20,
376 .clock_frequency = 0x07de2900,
377 .initfn = cpu_604_init,
379 { // XXX find out real values
380 .iu_version = 0x000a0000,
381 .name = "PowerPC,604r",
382 .icache_size = 0x4000,
383 .dcache_size = 0x4000,
384 .icache_sets = 0x80,
385 .dcache_sets = 0x80,
386 .icache_block_size = 0x20,
387 .dcache_block_size = 0x20,
388 .clock_frequency = 0x07de2900,
389 .initfn = cpu_604_init,
391 { // XXX find out real values
392 .iu_version = 0x80040000,
393 .name = "PowerPC,MPC86xx",
394 .icache_size = 0x8000,
395 .dcache_size = 0x8000,
396 .icache_sets = 0x80,
397 .dcache_sets = 0x80,
398 .icache_block_size = 0x20,
399 .dcache_block_size = 0x20,
400 .clock_frequency = 0x14dc9380,
401 .initfn = cpu_750_init,
404 .iu_version = 0x000080000,
405 .name = "PowerPC,750",
406 .icache_size = 0x8000,
407 .dcache_size = 0x8000,
408 .icache_sets = 0x80,
409 .dcache_sets = 0x80,
410 .icache_block_size = 0x20,
411 .dcache_block_size = 0x20,
412 .clock_frequency = 0x14dc9380,
413 .initfn = cpu_750_init,
415 { // XXX find out real values
416 .iu_version = 0x10080000,
417 .name = "PowerPC,750",
418 .icache_size = 0x8000,
419 .dcache_size = 0x8000,
420 .icache_sets = 0x80,
421 .dcache_sets = 0x80,
422 .icache_block_size = 0x20,
423 .dcache_block_size = 0x20,
424 .clock_frequency = 0x14dc9380,
425 .initfn = cpu_750_init,
427 { // XXX find out real values
428 .iu_version = 0x70000000,
429 .name = "PowerPC,750",
430 .icache_size = 0x8000,
431 .dcache_size = 0x8000,
432 .icache_sets = 0x80,
433 .dcache_sets = 0x80,
434 .icache_block_size = 0x20,
435 .dcache_block_size = 0x20,
436 .clock_frequency = 0x14dc9380,
437 .initfn = cpu_750_init,
439 { // XXX find out real values
440 .iu_version = 0x70020000,
441 .name = "PowerPC,750",
442 .icache_size = 0x8000,
443 .dcache_size = 0x8000,
444 .icache_sets = 0x80,
445 .dcache_sets = 0x80,
446 .icache_block_size = 0x20,
447 .dcache_block_size = 0x20,
448 .clock_frequency = 0x14dc9380,
449 .initfn = cpu_750_init,
451 { // XXX find out real values
452 .iu_version = 0x800c0000,
453 .name = "PowerPC,74xx",
454 .icache_size = 0x8000,
455 .dcache_size = 0x8000,
456 .icache_sets = 0x80,
457 .dcache_sets = 0x80,
458 .icache_block_size = 0x20,
459 .dcache_block_size = 0x20,
460 .clock_frequency = 0x14dc9380,
461 .initfn = cpu_750_init,
464 .iu_version = 0x0000c0000,
465 .name = "PowerPC,G4",
466 .icache_size = 0x8000,
467 .dcache_size = 0x8000,
468 .icache_sets = 0x80,
469 .dcache_sets = 0x80,
470 .icache_block_size = 0x20,
471 .dcache_block_size = 0x20,
472 .clock_frequency = 0x1dcd6500,
473 .initfn = cpu_g4_init,
476 .iu_version = 0x00390000,
477 .name = "PowerPC,970",
478 .icache_size = 0x10000,
479 .dcache_size = 0x8000,
480 .icache_sets = 0x200,
481 .dcache_sets = 0x80,
482 .icache_block_size = 0x80,
483 .dcache_block_size = 0x80,
484 .clock_frequency = 0x5f5e1000,
485 .initfn = cpu_970_init,
487 { // XXX find out real values
488 .iu_version = 0x003C0000,
489 .name = "PowerPC,970FX",
490 .icache_size = 0x10000,
491 .dcache_size = 0x8000,
492 .icache_sets = 0x80,
493 .dcache_sets = 0x80,
494 .icache_block_size = 0x80,
495 .dcache_block_size = 0x80,
496 .clock_frequency = 0x1dcd6500,
497 .initfn = cpu_970_init,
501 static const struct cpudef *
502 id_cpu(void)
504 unsigned long iu_version;
505 unsigned int i;
507 asm("mfpvr %0\n"
508 : "=r"(iu_version) :);
509 iu_version &= 0xffff0000;
511 for (i = 0; i < sizeof(ppc_defs)/sizeof(struct cpudef); i++) {
512 if (iu_version == ppc_defs[i].iu_version)
513 return &ppc_defs[i];
515 printk("Unknown cpu (pvr %lx), freezing!\n", iu_version);
516 for (;;);
519 static void go( void );
521 static void
522 go( void )
524 ucell addr;
526 feval("saved-program-state >sps.entry @");
527 addr = POP();
529 call_elf( 0, 0, addr);
532 static void kvm_of_init(void)
534 char hypercall[4 * 4];
535 uint32_t *hc32;
537 /* Don't expose /hypervisor when not in KVM */
538 if (!fw_cfg_read_i32(FW_CFG_PPC_IS_KVM))
539 return;
541 push_str("/");
542 fword("find-device");
544 fword("new-device");
546 push_str("hypervisor");
547 fword("device-name");
549 push_str("hypervisor");
550 fword("device-type");
552 /* compatible */
554 push_str("linux,kvm");
555 fword("encode-string");
556 push_str("epapr,hypervisor-0.2");
557 fword("encode-string");
558 fword("encode+");
559 push_str("compatible");
560 fword("property");
562 /* Tell the guest about the hypercall instructions */
563 fw_cfg_read(FW_CFG_PPC_KVM_HC, hypercall, 4 * 4);
564 hc32 = (uint32_t*)hypercall;
565 PUSH(hc32[0]);
566 fword("encode-int");
567 PUSH(hc32[1]);
568 fword("encode-int");
569 fword("encode+");
570 PUSH(hc32[2]);
571 fword("encode-int");
572 fword("encode+");
573 PUSH(hc32[3]);
574 fword("encode-int");
575 fword("encode+");
576 push_str("hcall-instructions");
577 fword("property");
579 /* ePAPR requires us to provide a unique guest id */
580 PUSH(fw_cfg_read_i32(FW_CFG_PPC_KVM_PID));
581 fword("encode-int");
582 push_str("guest-id");
583 fword("property");
585 /* ePAPR requires us to provide a guest name */
586 push_str("KVM guest");
587 fword("encode-string");
588 push_str("guest-name");
589 fword("property");
591 fword("finish-device");
594 void
595 arch_of_init( void )
597 #ifdef CONFIG_RTAS
598 phandle_t ph;
599 #endif
600 uint64_t ram_size;
601 const struct cpudef *cpu;
602 char buf[64], qemu_uuid[16];
603 const char *stdin_path, *stdout_path, *boot_path;
604 uint32_t temp = 0;
606 ofmem_t *ofmem = ofmem_arch_get_private();
608 openbios_init();
609 modules_init();
610 setup_timers();
611 #ifdef CONFIG_DRIVER_PCI
612 ob_pci_init();
613 #endif
615 printk("\n");
616 printk("=============================================================\n");
617 printk(PROGRAM_NAME " " OPENBIOS_VERSION_STR " [%s]\n",
618 OPENBIOS_BUILD_DATE);
620 fw_cfg_read(FW_CFG_SIGNATURE, buf, 4);
621 buf[4] = '\0';
622 printk("Configuration device id %s", buf);
624 temp = fw_cfg_read_i32(FW_CFG_ID);
625 printk(" version %d machine id %d\n", temp, machine_id);
627 temp = fw_cfg_read_i32(FW_CFG_NB_CPUS);
629 printk("CPUs: %x\n", temp);
631 ram_size = ofmem->ramsize;
633 printk("Memory: %lldM\n", ram_size / 1024 / 1024);
635 fw_cfg_read(FW_CFG_UUID, qemu_uuid, 16);
637 printk("UUID: " UUID_FMT "\n", qemu_uuid[0], qemu_uuid[1], qemu_uuid[2],
638 qemu_uuid[3], qemu_uuid[4], qemu_uuid[5], qemu_uuid[6],
639 qemu_uuid[7], qemu_uuid[8], qemu_uuid[9], qemu_uuid[10],
640 qemu_uuid[11], qemu_uuid[12], qemu_uuid[13], qemu_uuid[14],
641 qemu_uuid[15]);
643 /* set device tree root info */
645 push_str("/");
646 fword("find-device");
648 switch(machine_id) {
649 case ARCH_HEATHROW: /* OldWorld */
651 /* model */
653 push_str("Power Macintosh");
654 fword("model");
656 /* compatible */
658 push_str("AAPL,PowerMac G3");
659 fword("encode-string");
660 push_str("MacRISC");
661 fword("encode-string");
662 fword("encode+");
663 push_str("compatible");
664 fword("property");
666 /* misc */
668 push_str("device-tree");
669 fword("encode-string");
670 push_str("AAPL,original-name");
671 fword("property");
673 PUSH(0);
674 fword("encode-int");
675 push_str("AAPL,cpu-id");
676 fword("property");
678 PUSH(66 * 1000 * 1000);
679 fword("encode-int");
680 push_str("clock-frequency");
681 fword("property");
682 break;
684 case ARCH_MAC99:
685 case ARCH_MAC99_U3:
686 case ARCH_PREP:
687 default:
689 /* model */
691 push_str("PowerMac2,1");
692 fword("model");
694 /* compatible */
696 push_str("PowerMac2,1");
697 fword("encode-string");
698 push_str("MacRISC");
699 fword("encode-string");
700 fword("encode+");
701 push_str("Power Macintosh");
702 fword("encode-string");
703 fword("encode+");
704 push_str("compatible");
705 fword("property");
707 /* misc */
709 push_str("bootrom");
710 fword("device-type");
712 PUSH(100 * 1000 * 1000);
713 fword("encode-int");
714 push_str("clock-frequency");
715 fword("property");
716 break;
719 /* Perhaps we can store UUID here ? */
721 push_str("0000000000000");
722 fword("encode-string");
723 push_str("system-id");
724 fword("property");
726 /* memory info */
728 push_str("/memory");
729 fword("find-device");
731 /* all memory */
733 PUSH(ram_size >> 32);
734 fword("encode-int");
735 PUSH(ram_size & 0xffffffff);
736 fword("encode-int");
737 fword("encode+");
738 PUSH(0);
739 fword("encode-int");
740 fword("encode+");
741 PUSH(0);
742 fword("encode-int");
743 fword("encode+");
744 push_str("reg");
745 fword("property");
747 cpu = id_cpu();
748 cpu->initfn(cpu);
749 printk("CPU type %s\n", cpu->name);
751 snprintf(buf, sizeof(buf), "/cpus/%s", cpu->name);
752 ofmem_register(find_dev("/memory"), find_dev(buf));
753 node_methods_init(buf);
755 #ifdef CONFIG_RTAS
756 /* OldWorld Macs don't have an /rtas node. */
757 switch (machine_id) {
758 case ARCH_MAC99:
759 case ARCH_MAC99_U3:
760 if (!(ph = find_dev("/rtas"))) {
761 printk("Warning: No /rtas node\n");
762 } else {
763 unsigned long size = 0x1000;
764 while (size < (unsigned long)of_rtas_end - (unsigned long)of_rtas_start)
765 size *= 2;
766 set_property(ph, "rtas-size", (char*)&size, sizeof(size));
767 set_int_property(ph, "rtas-version", is_apple() ? 0x41 : 1);
769 break;
771 #endif
773 if (fw_cfg_read_i16(FW_CFG_NOGRAPHIC)) {
774 if (CONFIG_SERIAL_PORT) {
775 stdin_path = "scca";
776 stdout_path = "scca";
777 } else {
778 stdin_path = "sccb";
779 stdout_path = "sccb";
782 /* Some bootloaders force the output to the screen device, so
783 let's create a screen alias for the serial device too */
784 push_str("/aliases");
785 fword("find-device");
787 push_str(stdout_path);
788 fword("pathres-resolve-aliases");
789 fword("encode-string");
790 push_str("screen");
791 fword("property");
792 } else {
793 stdin_path = "adb-keyboard";
794 stdout_path = "screen";
797 kvm_of_init();
799 /* Setup nvram variables */
800 push_str("/options");
801 fword("find-device");
803 uint16_t boot_device = fw_cfg_read_i16(FW_CFG_BOOT_DEVICE);
804 switch (boot_device) {
805 case 'c':
806 boot_path = "hd";
807 break;
808 default:
809 case 'd':
810 boot_path = "cd";
811 break;
814 /* Setup default boot devices */
815 snprintf(buf, sizeof(buf), "%s:,\\\\:tbxi %s:,\\ppc\\bootinfo.txt", boot_path, boot_path);
816 push_str(buf);
817 fword("encode-string");
818 push_str("boot-device");
819 fword("property");
821 /* Set up other properties */
822 push_str("/chosen");
823 fword("find-device");
825 push_str(stdin_path);
826 fword("open-dev");
827 fword("encode-int");
828 push_str("stdin");
829 fword("property");
831 push_str(stdout_path);
832 fword("open-dev");
833 fword("encode-int");
834 push_str("stdout");
835 fword("property");
837 push_str(stdin_path);
838 fword("pathres-resolve-aliases");
839 push_str("input-device");
840 fword("$setenv");
842 push_str(stdout_path);
843 fword("pathres-resolve-aliases");
844 push_str("output-device");
845 fword("$setenv");
847 push_str(stdin_path);
848 fword("input");
850 push_str(stdout_path);
851 fword("output");
853 #if 0
854 if( getbool("tty-interface?") == 1 )
855 #endif
856 fword("activate-tty-interface");
858 device_end();
860 bind_func("platform-boot", boot );
861 bind_func("(go)", go);