static void bfin_mmr_invalid (struct hw *me, address_word addr, unsigned nr_bytes, bool write, bool missing) { SIM_CPU *cpu = hw_system_cpu (me); const char *rw = write ? "write" : "read"; const char *reason = missing ? "no such register" : (addr & 3) ? "must be 32-bit aligned" : "invalid length"; /* Only throw a fit if the cpu is doing the access. DMA/GDB simply go unnoticed. Not exactly hardware behavior, but close enough. */ if (!cpu) { sim_io_eprintf (hw_system (me), "%s: invalid MMR %s at %#x length %u: %s\n", hw_path (me), rw, addr, nr_bytes, reason); return; } HW_TRACE ((me, "invalid MMR %s at %#x length %u: %s", rw, addr, nr_bytes, reason)); /* XXX: is this what hardware does ? What about priority of unaligned vs wrong length vs missing register ? What about system-vs-core ? */ /* XXX: We should move this addr check to a model property so we get the same behavior regardless of where we map the model. */ if (addr >= BFIN_CORE_MMR_BASE) /* XXX: This should be setting up CPLB fault addrs ? */ mmu_process_fault (cpu, addr, write, false, false, true); else /* XXX: Newer parts set up an interrupt from EBIU and program EBIU_ERRADDR with the address. */ cec_hwerr (cpu, HWERR_SYSTEM_MMR); }
static void bfin_mmr_invalid (struct hw *me, SIM_CPU *cpu, address_word addr, unsigned nr_bytes, bool write) { if (!cpu) cpu = hw_system_cpu (me); /* Only throw a fit if the cpu is doing the access. DMA/GDB simply go unnoticed. Not exactly hardware behavior, but close enough. */ if (!cpu) { sim_io_eprintf (hw_system (me), "%s: invalid MMR access @ %#x\n", hw_path (me), addr); return; } HW_TRACE ((me, "invalid MMR %s to 0x%08lx length %u", write ? "write" : "read", (unsigned long) addr, nr_bytes)); /* XXX: is this what hardware does ? */ if (addr >= BFIN_CORE_MMR_BASE) /* XXX: This should be setting up CPLB fault addrs ? */ mmu_process_fault (cpu, addr, write, false, false, true); else /* XXX: Newer parts set up an interrupt from EBIU and program EBIU_ERRADDR with the address. */ cec_hwerr (cpu, HWERR_SYSTEM_MMR); }
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; }