struct hw * hw_tree_vparse (struct hw *current, const char *fmt, va_list ap) { char device_specifier[1024]; name_specifier spec; /* format the path */ vsprintf (device_specifier, fmt, ap); if (strlen (device_specifier) >= sizeof (device_specifier)) hw_abort (NULL, "device_tree_add_deviced: buffer overflow\n"); /* construct the tree down to the final struct hw */ current = split_fill_path (current, device_specifier, &spec); /* is there an interrupt spec */ if (spec.property == NULL && spec.value != NULL) { char *op = split_value (&spec); switch (op[0]) { case '>': { char *my_port_name = split_value (&spec); int my_port; char *dest_port_name = split_value (&spec); int dest_port; name_specifier dest_spec; char *dest_hw_name = split_value (&spec); struct hw *dest; /* find my name */ if (!hw_finished_p (current)) hw_finish (current); my_port = hw_port_decode (current, my_port_name, output_port); /* find the dest device and port */ dest = split_fill_path (current, dest_hw_name, &dest_spec); if (!hw_finished_p (dest)) hw_finish (dest); dest_port = hw_port_decode (dest, dest_port_name, input_port); /* connect the two */ hw_port_attach (current, my_port, dest, dest_port, permenant_object); break; } default: hw_abort (current, "unreconised interrupt spec %s\n", spec.value); break; } } /* is there a property */ if (spec.property != NULL) { if (strcmp (spec.value, "true") == 0) hw_add_boolean_property (current, spec.property, 1); else if (strcmp (spec.value, "false") == 0) hw_add_boolean_property (current, spec.property, 0); else { const struct hw_property *property; switch (spec.value[0]) { #if NOT_YET case '*': { parse_ihandle_property (current, spec.property, spec.value + 1); break; } #endif case '[': { unsigned8 words[1024]; char *curr = spec.value + 1; int nr_words = 0; while (1) { char *next; words[nr_words] = H2BE_1 (strtoul (curr, &next, 0)); if (curr == next) break; curr = next; nr_words += 1; } hw_add_array_property (current, spec.property, words, sizeof(words[0]) * nr_words); break; } case '"': { parse_string_property (current, spec.property, spec.value); break; } case '!': { spec.value++; property = hw_tree_find_property (current, spec.value); if (property == NULL) hw_abort (current, "property %s not found\n", spec.value); hw_add_duplicate_property (current, spec.property, property); break; } default: { if (strcmp (spec.property, "reg") == 0 || strcmp (spec.property, "assigned-addresses") == 0 || strcmp (spec.property, "alternate-reg") == 0) { parse_reg_property (current, spec.property, spec.value); } else if (strcmp (spec.property, "ranges") == 0) { parse_ranges_property (current, spec.property, spec.value); } else if (isdigit(spec.value[0]) || (spec.value[0] == '-' && isdigit(spec.value[1])) || (spec.value[0] == '+' && isdigit(spec.value[1]))) { parse_integer_property(current, spec.property, spec.value); } else parse_string_property(current, spec.property, spec.value); break; } } } } return current; }
static int sim_hw_configure (SIM_DESC sd) { const struct bfd_arch_info *arch; struct hw *device_tree; sim_cpu *cpu; arch = STATE_ARCHITECTURE (sd); if (arch == 0) return 0; cpu = STATE_CPU (sd, 0); cpu->cpu_configured_arch = arch; device_tree = sim_hw_parse (sd, "/"); if (arch->arch == bfd_arch_m68hc11) { cpu->cpu_interpretor = cpu_interp_m6811; if (hw_tree_find_property (device_tree, "/m68hc11/reg") == 0) { /* Allocate core managed memory */ /* the monitor */ sim_do_commandf (sd, "memory region 0x%lx@%d,0x%lx", /* MONITOR_BASE, MONITOR_SIZE */ 0x8000, M6811_RAM_LEVEL, 0x8000); sim_do_commandf (sd, "memory region 0x000@%d,0x8000", M6811_RAM_LEVEL); sim_hw_parse (sd, "/m68hc11/reg 0x1000 0x03F"); if (cpu->bank_start < cpu->bank_end) { sim_do_commandf (sd, "memory region 0x%lx@%d,0x100000", cpu->bank_virtual, M6811_RAM_LEVEL); sim_hw_parse (sd, "/m68hc11/use_bank 1"); } } if (cpu->cpu_start_mode) { sim_hw_parse (sd, "/m68hc11/mode %s", cpu->cpu_start_mode); } if (hw_tree_find_property (device_tree, "/m68hc11/m68hc11sio/reg") == 0) { sim_hw_parse (sd, "/m68hc11/m68hc11sio/reg 0x2b 0x5"); sim_hw_parse (sd, "/m68hc11/m68hc11sio/backend stdio"); sim_hw_parse (sd, "/m68hc11 > cpu-reset reset /m68hc11/m68hc11sio"); } if (hw_tree_find_property (device_tree, "/m68hc11/m68hc11tim/reg") == 0) { /* M68hc11 Timer configuration. */ sim_hw_parse (sd, "/m68hc11/m68hc11tim/reg 0x1b 0x5"); sim_hw_parse (sd, "/m68hc11 > cpu-reset reset /m68hc11/m68hc11tim"); sim_hw_parse (sd, "/m68hc11 > capture capture /m68hc11/m68hc11tim"); } /* Create the SPI device. */ if (hw_tree_find_property (device_tree, "/m68hc11/m68hc11spi/reg") == 0) { sim_hw_parse (sd, "/m68hc11/m68hc11spi/reg 0x28 0x3"); sim_hw_parse (sd, "/m68hc11 > cpu-reset reset /m68hc11/m68hc11spi"); } if (hw_tree_find_property (device_tree, "/m68hc11/nvram/reg") == 0) { /* M68hc11 persistent ram configuration. */ sim_hw_parse (sd, "/m68hc11/nvram/reg 0x0 256"); sim_hw_parse (sd, "/m68hc11/nvram/file m68hc11.ram"); sim_hw_parse (sd, "/m68hc11/nvram/mode save-modified"); /*sim_hw_parse (sd, "/m68hc11 > cpu-reset reset /m68hc11/pram"); */ } if (hw_tree_find_property (device_tree, "/m68hc11/m68hc11eepr/reg") == 0) { sim_hw_parse (sd, "/m68hc11/m68hc11eepr/reg 0xb000 512"); sim_hw_parse (sd, "/m68hc11 > cpu-reset reset /m68hc11/m68hc11eepr"); } sim_hw_parse (sd, "/m68hc11 > port-a cpu-write-port /m68hc11"); sim_hw_parse (sd, "/m68hc11 > port-b cpu-write-port /m68hc11"); sim_hw_parse (sd, "/m68hc11 > port-c cpu-write-port /m68hc11"); sim_hw_parse (sd, "/m68hc11 > port-d cpu-write-port /m68hc11"); cpu->hw_cpu = sim_hw_parse (sd, "/m68hc11"); } else { cpu->cpu_interpretor = cpu_interp_m6812; if (hw_tree_find_property (device_tree, "/m68hc12/reg") == 0) { /* Allocate core external memory. */ sim_do_commandf (sd, "memory region 0x%lx@%d,0x%lx", 0x8000, M6811_RAM_LEVEL, 0x8000); sim_do_commandf (sd, "memory region 0x000@%d,0x8000", M6811_RAM_LEVEL); if (cpu->bank_start < cpu->bank_end) { sim_do_commandf (sd, "memory region 0x%lx@%d,0x100000", cpu->bank_virtual, M6811_RAM_LEVEL); sim_hw_parse (sd, "/m68hc12/use_bank 1"); } sim_hw_parse (sd, "/m68hc12/reg 0x0 0x3FF"); } if (!hw_tree_find_property (device_tree, "/m68hc12/m68hc12sio@1/reg")) { sim_hw_parse (sd, "/m68hc12/m68hc12sio@1/reg 0xC0 0x8"); sim_hw_parse (sd, "/m68hc12/m68hc12sio@1/backend stdio"); sim_hw_parse (sd, "/m68hc12 > cpu-reset reset /m68hc12/m68hc12sio@1"); } if (hw_tree_find_property (device_tree, "/m68hc12/m68hc12tim/reg") == 0) { /* M68hc11 Timer configuration. */ sim_hw_parse (sd, "/m68hc12/m68hc12tim/reg 0x1b 0x5"); sim_hw_parse (sd, "/m68hc12 > cpu-reset reset /m68hc12/m68hc12tim"); sim_hw_parse (sd, "/m68hc12 > capture capture /m68hc12/m68hc12tim"); } /* Create the SPI device. */ if (hw_tree_find_property (device_tree, "/m68hc12/m68hc12spi/reg") == 0) { sim_hw_parse (sd, "/m68hc12/m68hc12spi/reg 0x28 0x3"); sim_hw_parse (sd, "/m68hc12 > cpu-reset reset /m68hc12/m68hc12spi"); } if (hw_tree_find_property (device_tree, "/m68hc12/nvram/reg") == 0) { /* M68hc11 persistent ram configuration. */ sim_hw_parse (sd, "/m68hc12/nvram/reg 0x2000 8192"); sim_hw_parse (sd, "/m68hc12/nvram/file m68hc12.ram"); sim_hw_parse (sd, "/m68hc12/nvram/mode save-modified"); } if (hw_tree_find_property (device_tree, "/m68hc12/m68hc12eepr/reg") == 0) { sim_hw_parse (sd, "/m68hc12/m68hc12eepr/reg 0x0800 2048"); sim_hw_parse (sd, "/m68hc12 > cpu-reset reset /m68hc12/m68hc12eepr"); } sim_hw_parse (sd, "/m68hc12 > port-a cpu-write-port /m68hc12"); sim_hw_parse (sd, "/m68hc12 > port-b cpu-write-port /m68hc12"); sim_hw_parse (sd, "/m68hc12 > port-c cpu-write-port /m68hc12"); sim_hw_parse (sd, "/m68hc12 > port-d cpu-write-port /m68hc12"); cpu->hw_cpu = sim_hw_parse (sd, "/m68hc12"); } return 1; }
static unsigned hw_pal_io_read_buffer (struct hw *me, void *dest, int space, unsigned_word addr, unsigned nr_bytes) { hw_pal_device *hw_pal = (hw_pal_device *) hw_data (me); unsigned_1 *byte = (unsigned_1 *) dest; memset (dest, 0, nr_bytes); switch (addr & hw_pal_address_mask) { case hw_pal_cpu_nr_register: #ifdef CPU_INDEX *byte = CPU_INDEX (hw_system_cpu (me)); #else *byte = 0; #endif HW_TRACE ((me, "read - cpu-nr %d\n", *byte)); break; case hw_pal_nr_cpu_register: if (hw_tree_find_property (me, "/openprom/options/smp") == NULL) { *byte = 1; HW_TRACE ((me, "read - nr-cpu %d (not defined)\n", *byte)); } else { *byte = hw_tree_find_integer_property (me, "/openprom/options/smp"); HW_TRACE ((me, "read - nr-cpu %d\n", *byte)); } break; case hw_pal_read_fifo: *byte = hw_pal->input.buffer; HW_TRACE ((me, "read - input-fifo %d\n", *byte)); break; case hw_pal_read_status: scan_hw_pal (me); *byte = hw_pal->input.status; HW_TRACE ((me, "read - input-status %d\n", *byte)); break; case hw_pal_write_fifo: *byte = hw_pal->output.buffer; HW_TRACE ((me, "read - output-fifo %d\n", *byte)); break; case hw_pal_write_status: *byte = hw_pal->output.status; HW_TRACE ((me, "read - output-status %d\n", *byte)); break; case hw_pal_countdown: do_counter_read (me, hw_pal, "countdown", &hw_pal->countdown, dest, nr_bytes); break; case hw_pal_countdown_value: do_counter_value (me, hw_pal, "countdown-value", &hw_pal->countdown, dest, nr_bytes); break; case hw_pal_timer: do_counter_read (me, hw_pal, "timer", &hw_pal->timer, dest, nr_bytes); break; case hw_pal_timer_value: do_counter_value (me, hw_pal, "timer-value", &hw_pal->timer, dest, nr_bytes); break; default: HW_TRACE ((me, "read - ???\n")); break; } return nr_bytes; }