X-Git-Url: https://review.openocd.org/gitweb?p=openocd.git;a=blobdiff_plain;f=src%2Ftarget%2Flakemont.c;h=31882b8289799163343cffe355089e3c5ff22968;hp=2bd12fd41ce14b3562dd2c12715ce39d8d4d3577;hb=c69da2eb0c118dbcfcc26090355fa23818cec61e;hpb=47b8cf84202bf792cf66fbfa01169e9592236b8a diff --git a/src/target/lakemont.c b/src/target/lakemont.c index 2bd12fd41c..31882b8289 100644 --- a/src/target/lakemont.c +++ b/src/target/lakemont.c @@ -322,8 +322,8 @@ static int restore_context(struct target *t) } for (i = 0; i < (x86_32->cache->num_regs); i++) { - x86_32->cache->reg_list[i].dirty = 0; - x86_32->cache->reg_list[i].valid = 0; + x86_32->cache->reg_list[i].dirty = false; + x86_32->cache->reg_list[i].valid = false; } return err; } @@ -357,8 +357,8 @@ static int lakemont_set_core_reg(struct reg *reg, uint8_t *buf) if (check_not_halted(t)) return ERROR_TARGET_NOT_HALTED; buf_set_u32(reg->value, 0, 32, value); - reg->dirty = 1; - reg->valid = 1; + reg->dirty = true; + reg->valid = true; return ERROR_OK; } @@ -405,8 +405,8 @@ struct reg_cache *lakemont_build_reg_cache(struct target *t) reg_list[i].name = regs[i].name; reg_list[i].size = 32; reg_list[i].value = calloc(1, 4); - reg_list[i].dirty = 0; - reg_list[i].valid = 0; + reg_list[i].dirty = false; + reg_list[i].valid = false; reg_list[i].type = &lakemont_reg_type; reg_list[i].arch_info = &arch_info[i]; @@ -444,6 +444,8 @@ static uint32_t get_tapstatus(struct target *t) static int enter_probemode(struct target *t) { uint32_t tapstatus = 0; + int retries = 100; + tapstatus = get_tapstatus(t); LOG_DEBUG("TS before PM enter = 0x%08" PRIx32, tapstatus); if (tapstatus & TS_PM_BIT) { @@ -456,15 +458,17 @@ static int enter_probemode(struct target *t) scan.out[0] = 1; if (drscan(t, scan.out, scan.in, 1) != ERROR_OK) return ERROR_FAIL; - tapstatus = get_tapstatus(t); - LOG_DEBUG("TS after PM enter = 0x%08" PRIx32, tapstatus); - if ((tapstatus & TS_PM_BIT) && (!(tapstatus & TS_EN_PM_BIT))) - return ERROR_OK; - else { - LOG_ERROR("%s PM enter error, tapstatus = 0x%08" PRIx32 - , __func__, tapstatus); - return ERROR_FAIL; + + while (retries--) { + tapstatus = get_tapstatus(t); + LOG_DEBUG("TS after PM enter = 0x%08" PRIx32, tapstatus); + if ((tapstatus & TS_PM_BIT) && (!(tapstatus & TS_EN_PM_BIT))) + return ERROR_OK; } + + LOG_ERROR("%s PM enter error, tapstatus = 0x%08" PRIx32 + , __func__, tapstatus); + return ERROR_FAIL; } static int exit_probemode(struct target *t) @@ -663,8 +667,8 @@ static int read_hw_reg(struct target *t, int reg, uint32_t *regval, uint8_t cach *regval = buf_get_u32(scan.out, 0, 32); if (cache) { buf_set_u32(x86_32->cache->reg_list[reg].value, 0, 32, *regval); - x86_32->cache->reg_list[reg].valid = 1; - x86_32->cache->reg_list[reg].dirty = 0; + x86_32->cache->reg_list[reg].valid = true; + x86_32->cache->reg_list[reg].dirty = false; } LOG_DEBUG("reg=%s, op=0x%016" PRIx64 ", val=0x%08" PRIx32, x86_32->cache->reg_list[reg].name, @@ -705,8 +709,8 @@ static int write_hw_reg(struct target *t, int reg, uint32_t regval, uint8_t cach /* we are writing from the cache so ensure we reset flags */ if (cache) { - x86_32->cache->reg_list[reg].dirty = 0; - x86_32->cache->reg_list[reg].valid = 0; + x86_32->cache->reg_list[reg].dirty = false; + x86_32->cache->reg_list[reg].valid = false; } return ERROR_OK; } @@ -943,8 +947,8 @@ int lakemont_poll(struct target *t) * breakpoint instruction. This needs to be corrected. */ buf_set_u32(x86_32->cache->reg_list[EIP].value, 0, 32, eip-1); - x86_32->cache->reg_list[EIP].dirty = 1; - x86_32->cache->reg_list[EIP].valid = 1; + x86_32->cache->reg_list[EIP].dirty = true; + x86_32->cache->reg_list[EIP].valid = true; LOG_USER("hit software breakpoint at 0x%08" PRIx32, eip-1); } else { /* it's not a hardware breakpoint (checked already in DR6 state) @@ -966,6 +970,7 @@ int lakemont_poll(struct target *t) return target_call_event_callbacks(t, TARGET_EVENT_HALTED); } } + return ERROR_OK; } @@ -1111,15 +1116,137 @@ int lakemont_step(struct target *t, int current, return retval; } -/* TODO - implement resetbreak fully through CLTAP registers */ +static int lakemont_reset_break(struct target *t) +{ + struct x86_32_common *x86_32 = target_to_x86_32(t); + struct jtag_tap *saved_tap = x86_32->curr_tap; + struct scan_field *fields = &scan.field; + + int retval = ERROR_OK; + + LOG_DEBUG("issuing port 0xcf9 reset"); + + /* prepare resetbreak setting the proper bits in CLTAPC_CPU_VPREQ */ + x86_32->curr_tap = jtag_tap_by_position(1); + if (x86_32->curr_tap == NULL) { + x86_32->curr_tap = saved_tap; + LOG_ERROR("%s could not select quark_x10xx.cltap", __func__); + return ERROR_FAIL; + } + + fields->in_value = NULL; + fields->num_bits = 8; + + /* select CLTAPC_CPU_VPREQ instruction*/ + scan.out[0] = 0x51; + fields->out_value = ((uint8_t *)scan.out); + jtag_add_ir_scan(x86_32->curr_tap, fields, TAP_IDLE); + retval = jtag_execute_queue(); + if (retval != ERROR_OK) { + x86_32->curr_tap = saved_tap; + LOG_ERROR("%s irscan failed to execute queue", __func__); + return retval; + } + + /* set enable_preq_on_reset & enable_preq_on_reset2 bits*/ + scan.out[0] = 0x06; + fields->out_value = ((uint8_t *)scan.out); + jtag_add_dr_scan(x86_32->curr_tap, 1, fields, TAP_IDLE); + retval = jtag_execute_queue(); + if (retval != ERROR_OK) { + LOG_ERROR("%s drscan failed to execute queue", __func__); + x86_32->curr_tap = saved_tap; + return retval; + } + + /* restore current tap */ + x86_32->curr_tap = saved_tap; + + return ERROR_OK; +} + +/* + * If we ever get an adapter with support for PREQ# and PRDY#, we should + * update this function to add support for using those two signals. + * + * Meanwhile, we're assuming that we only support reset break. + */ int lakemont_reset_assert(struct target *t) { - LOG_DEBUG("-"); + struct x86_32_common *x86_32 = target_to_x86_32(t); + /* write 0x6 to I/O port 0xcf9 to cause the reset */ + uint8_t cf9_reset_val = 0x6; + int retval; + + LOG_DEBUG(" "); + + if (t->state != TARGET_HALTED) { + LOG_DEBUG("target must be halted first"); + retval = lakemont_halt(t); + if (retval != ERROR_OK) { + LOG_ERROR("could not halt target"); + return retval; + } + x86_32->forced_halt_for_reset = true; + } + + if (t->reset_halt) { + retval = lakemont_reset_break(t); + if (retval != ERROR_OK) + return retval; + } + + retval = x86_32_common_write_io(t, 0xcf9, BYTE, &cf9_reset_val); + if (retval != ERROR_OK) { + LOG_ERROR("could not write to port 0xcf9"); + return retval; + } + + if (!t->reset_halt && x86_32->forced_halt_for_reset) { + x86_32->forced_halt_for_reset = false; + retval = lakemont_resume(t, true, 0x00, false, true); + if (retval != ERROR_OK) + return retval; + } + + /* remove breakpoints and watchpoints */ + x86_32_common_reset_breakpoints_watchpoints(t); + return ERROR_OK; } int lakemont_reset_deassert(struct target *t) { - LOG_DEBUG("-"); + int retval; + + LOG_DEBUG(" "); + + if (target_was_examined(t)) { + retval = lakemont_poll(t); + if (retval != ERROR_OK) + return retval; + } + + if (t->reset_halt) { + /* entered PM after reset, update the state */ + retval = lakemont_update_after_probemode_entry(t); + if (retval != ERROR_OK) { + LOG_ERROR("could not update state after probemode entry"); + return retval; + } + + if (t->state != TARGET_HALTED) { + LOG_WARNING("%s: ran after reset and before halt ...", + target_name(t)); + if (target_was_examined(t)) { + retval = target_halt(t); + if (retval != ERROR_OK) + return retval; + } else { + t->state = TARGET_UNKNOWN; + } + } + } + return ERROR_OK; }