static inline void shift_data (urj_bus_t *bus, unsigned int bit) { urj_data_register_t *dr = bus->part->active_instruction->data_register; do { DBG (DBG_SHIFT, _("%s: data=%s\n"), __FUNCTION__, urj_tap_register_get_string (dr->in)); urj_tap_chain_shift_data_registers (bus->chain, 1); DBG (DBG_SHIFT, _("%s: data out=%s\n"), __FUNCTION__, urj_tap_register_get_string (dr->out)); /* TODO: add timeout checking */ } while (register_get_bit (dr->out, bit)); }
static inline void shift_instr (urj_bus_t *bus, unsigned int bit) { urj_tap_register_t *r = bus->part->active_instruction->out; do { DBG (DBG_SHIFT, _("%s: instr=%s\n"), __FUNCTION__, urj_tap_register_get_string (bus->part->active_instruction-> value)); urj_tap_chain_shift_instructions_mode (bus->chain, 1, 1, URJ_CHAIN_EXITMODE_IDLE); DBG (DBG_SHIFT, _("%s: ret=%s\n"), __FUNCTION__, urj_tap_register_get_string (r)); /* TODO: add timeout checking */ } while (register_get_bit (r, bit)); }
urj_tap_register_t * urj_tap_register_duplicate (const urj_tap_register_t *tr) { if (!tr) { urj_error_set (URJ_ERROR_INVALID, "tr == NULL"); return NULL; } return urj_tap_register_init (urj_tap_register_alloc (tr->len), urj_tap_register_get_string (tr)); }
int urj_tap_register_match (const urj_tap_register_t *tr, const char *expr) { int i; const char *s; if (!tr || !expr || (tr->len != strlen (expr))) return 0; s = urj_tap_register_get_string (tr); for (i = 0; i < tr->len; i++) if ((expr[i] != '?') && (expr[i] != s[i])) return 0; return 1; }
/** * bus->driver->(*initbus) * */ static int arm9tdmi_bus_init (urj_bus_t *bus) { unsigned int i, status, success; if (urj_tap_state (bus->chain) != URJ_TAP_STATE_RUN_TEST_IDLE) { /* silently skip initialization if TAP isn't in RUNTEST/IDLE state this is required to avoid interfering with detect when initbus is contained in the part description file URJ_BUS_INIT() will be called latest by URJ_BUS_PREPARE() */ return URJ_STATUS_OK; } if (scann == NULL) scann = urj_part_find_data_register (bus->part, "SCANN"); if (scan1 == NULL) scan1 = urj_part_find_data_register (bus->part, "SCAN1"); if (scan2 == NULL) scan2 = urj_part_find_data_register (bus->part, "SCAN2"); if (!(scann)) { urj_error_set (URJ_ERROR_NOTFOUND, _("SCANN register")); return URJ_STATUS_FAIL; } if (!(scan1)) { urj_error_set (URJ_ERROR_NOTFOUND, _("SCAN1 register")); return URJ_STATUS_FAIL; } if (!(scan2)) { urj_error_set (URJ_ERROR_NOTFOUND, _("SCAN2 register")); return URJ_STATUS_FAIL; } /* * select scan chain 2 -- EmbeddedICE-RT */ arm9tdmi_select_scanchain(bus, 2); urj_part_set_instruction (bus->part, "INTEST2"); urj_tap_chain_shift_instructions (bus->chain); arm9tdmi_ice_write(bus, ARM9TDMI_ICE_DBGCTL, 0x3); urj_part_set_instruction (bus->part, "RESTART"); urj_tap_chain_shift_instructions (bus->chain); i = 0; success = 0; status = 0; while (i++ < 10) { urj_part_set_instruction (bus->part, "INTEST2"); urj_tap_chain_shift_instructions (bus->chain); arm9tdmi_ice_read(bus, ARM9TDMI_ICE_DBGSTAT, &status); if (status & 0x01) { success = 1; break; } urj_part_set_instruction (bus->part, "RESTART"); urj_tap_chain_shift_instructions (bus->chain); usleep(100); } if (!success) { urj_error_set (URJ_ERROR_TIMEOUT, _("Failed to enter debug mode, ctrl=%s"), urj_tap_register_get_string (scan2->out)); return URJ_STATUS_FAIL; } arm9tdmi_ice_write(bus, ARM9TDMI_ICE_DBGCTL, 0x00); urj_log (URJ_LOG_LEVEL_NORMAL, _("The target is halted in ")); if (status & 0x10) urj_log (URJ_LOG_LEVEL_NORMAL, _("THUMB mode.\n")); else urj_log (URJ_LOG_LEVEL_NORMAL, _("ARM mode.\n")); /* select scan chain 1, and use INTEST instruction */ arm9tdmi_select_scanchain(bus, 1); urj_part_set_instruction (bus->part, "INTEST1"); urj_tap_chain_shift_instructions_mode (bus->chain, 0, 1, URJ_CHAIN_EXITMODE_UPDATE); bus->initialized = 1; return URJ_STATUS_OK; }
static int cmd_dr_run (urj_chain_t *chain, char *params[]) { int dir = 1; urj_part_t *part; urj_tap_register_t *r; urj_data_register_t *dr; urj_part_instruction_t *active_ir; if (urj_cmd_params (params) < 1 || urj_cmd_params (params) > 2) { urj_error_set (URJ_ERROR_SYNTAX, "%s: #parameters should be >= 1 and <= 2, not %d", params[0], urj_cmd_params (params)); return URJ_STATUS_FAIL; } if (urj_cmd_test_cable (chain) != URJ_STATUS_OK) return URJ_STATUS_FAIL; part = urj_tap_chain_active_part (chain); if (part == NULL) return URJ_STATUS_FAIL; active_ir = part->active_instruction; if (active_ir == NULL) { urj_error_set (URJ_ERROR_ILLEGAL_STATE, _("%s: part without active instruction"), "dr"); return URJ_STATUS_FAIL; } dr = active_ir->data_register; if (dr == NULL) { urj_error_set (URJ_ERROR_ILLEGAL_STATE, _("%s: instruction without active data register"), "dr"); return URJ_STATUS_FAIL; } if (params[1]) { if (strcasecmp (params[1], "in") == 0) dir = 0; else if (strcasecmp (params[1], "out") == 0) dir = 1; else { int ret = urj_tap_register_set_string (dr->in, params[1]); if (ret != URJ_STATUS_OK) return ret; dir = 0; } } if (dir) r = dr->out; else r = dr->in; urj_log (URJ_LOG_LEVEL_NORMAL, "%s (0x%0*" PRIX64 ")\n", urj_tap_register_get_string (r), r->len / 4, urj_tap_register_get_value (r)); return URJ_STATUS_OK; }
static uint32_t ejtag_run_pracc (urj_bus_t *bus, const uint32_t *code, unsigned int len) { urj_data_register_t *ejaddr, *ejdata, *ejctrl; int i, pass; uint32_t addr, data, retval; ejaddr = urj_part_find_data_register (bus->part, "EJADDRESS"); ejdata = urj_part_find_data_register (bus->part, "EJDATA"); ejctrl = urj_part_find_data_register (bus->part, "EJCONTROL"); if (!(ejaddr && ejdata && ejctrl)) { urj_error_set (URJ_ERROR_NOTFOUND, _("EJADDRESS, EJDATA or EJCONTROL register not found")); return 0; } urj_part_set_instruction (bus->part, "EJTAG_CONTROL"); urj_tap_chain_shift_instructions (bus->chain); pass = 0; retval = 0; for (;;) { ejctrl->in->data[PrAcc] = 1; urj_tap_chain_shift_data_registers (bus->chain, 0); urj_tap_chain_shift_data_registers (bus->chain, 1); urj_log (URJ_LOG_LEVEL_ALL, "ctrl=%s\n", urj_tap_register_get_string (ejctrl->out)); if (ejctrl->out->data[Rocc]) { urj_error_set (URJ_ERROR_BUS, _("Reset occurred, ctrl=%s"), urj_tap_register_get_string (ejctrl->out)); bus->initialized = 0; break; } if (!ejctrl->out->data[PrAcc]) { urj_error_set (URJ_ERROR_BUS, _("No processor access, ctrl=%s"), urj_tap_register_get_string (ejctrl->out)); bus->initialized = 0; break; } urj_part_set_instruction (bus->part, "EJTAG_ADDRESS"); urj_tap_chain_shift_instructions (bus->chain); urj_tap_chain_shift_data_registers (bus->chain, 1); addr = reg_value (ejaddr->out); if (addr & 3) { urj_error_set (URJ_ERROR_BUS, _("PrAcc bad alignment: addr=0x%08lx"), (long unsigned) addr); addr &= ~3; } urj_part_set_instruction (bus->part, "EJTAG_DATA"); urj_tap_chain_shift_instructions (bus->chain); urj_tap_register_fill (ejdata->in, 0); if (ejctrl->out->data[PRnW]) { urj_tap_chain_shift_data_registers (bus->chain, 1); data = reg_value (ejdata->out); urj_log (URJ_LOG_LEVEL_ALL, _("%s(%d) PrAcc write: addr=0x%08lx data=0x%08lx\n"), __FILE__, __LINE__, (long unsigned) addr, (long unsigned) data); if (addr == UINT32_C (0xff200000)) { /* Return value from the target CPU. */ retval = data; } else { urj_error_set (URJ_ERROR_BUS, _("Unknown write addr=0x%08lx data=0x%08lx"), (long unsigned) addr, (long unsigned) data); } } else { if (addr == UINT32_C (0xff200200) && pass++) break; data = 0; if (addr >= 0xff200200 && addr < 0xff200200 + (len << 2)) { data = code[(addr - 0xff200200) >> 2]; for (i = 0; i < 32; i++) ejdata->in->data[i] = (data >> i) & 1; } urj_log (URJ_LOG_LEVEL_ALL, "%s(%d) PrAcc read: addr=0x%08lx data=0x%08lx\n", __FILE__, __LINE__, (long unsigned) addr, (long unsigned) data); urj_tap_chain_shift_data_registers (bus->chain, 0); } urj_part_set_instruction (bus->part, "EJTAG_CONTROL"); urj_tap_chain_shift_instructions (bus->chain); ejctrl->in->data[PrAcc] = 0; urj_tap_chain_shift_data_registers (bus->chain, 0); }
/** * low level dma read operation * */ static unsigned int ejtag_dma_read (urj_bus_t *bus, unsigned int addr, int sz) { static urj_data_register_t *ejctrl = NULL; static urj_data_register_t *ejaddr = NULL; static urj_data_register_t *ejdata = NULL; int i = 0; int timeout = 5; unsigned int ret; if (ejctrl == NULL) ejctrl = urj_part_find_data_register (bus->part, "EJCONTROL"); if (ejaddr == NULL) ejaddr = urj_part_find_data_register (bus->part, "EJADDRESS"); if (ejdata == NULL) ejdata = urj_part_find_data_register (bus->part, "EJDATA"); urj_part_set_instruction (bus->part, "EJTAG_ADDRESS"); urj_tap_chain_shift_instructions (bus->chain); for (i = 0; i < 32; i++) ejaddr->in->data[i] = (addr >> i) & 1; urj_tap_chain_shift_data_registers (bus->chain, 0); /* Push the address to read */ urj_log (URJ_LOG_LEVEL_COMM, "Wrote to ejaddr->in =%s %08lX\n", urj_tap_register_get_string (ejaddr->in), (long unsigned) reg_value (ejaddr->in)); urj_part_set_instruction (bus->part, "EJTAG_CONTROL"); urj_tap_chain_shift_instructions (bus->chain); urj_tap_register_fill (ejctrl->in, 0); ejctrl->in->data[PrAcc] = 1; // Processor access ejctrl->in->data[ProbEn] = 1; ejctrl->in->data[DmaAcc] = 1; // DMA operation request */ ejctrl->in->data[DstRt] = 1; if (sz) ejctrl->in->data[sz] = 1; // Size : can be WORD/HALFWORD or nothing for byte ejctrl->in->data[DmaRwn] = 1; // This is a read urj_tap_chain_shift_data_registers (bus->chain, 0); /* Do the operation */ urj_log (URJ_LOG_LEVEL_ALL, "Wrote to ejctrl->in =%s %08lX\n", urj_tap_register_get_string (ejctrl->in), (long unsigned) reg_value (ejctrl->in)); do { urj_part_set_instruction (bus->part, "EJTAG_CONTROL"); urj_tap_chain_shift_instructions (bus->chain); urj_tap_register_fill (ejctrl->in, 0); ejctrl->in->data[PrAcc] = 1; ejctrl->in->data[ProbEn] = 1; ejctrl->in->data[DmaAcc] = 1; urj_tap_chain_shift_data_registers (bus->chain, 1); urj_log (URJ_LOG_LEVEL_ALL, "Wrote to ejctrl->in =%s %08lX\n", urj_tap_register_get_string (ejctrl->in), (long unsigned) reg_value (ejctrl->in)); urj_log (URJ_LOG_LEVEL_ALL, "Read from ejctrl->out =%s %08lX\n", urj_tap_register_get_string (ejctrl->out), (long unsigned) reg_value (ejctrl->out)); timeout--; if (!timeout) break; } while (ejctrl->out->data[DstRt] == 1); // This flag tell us the processor has completed the op urj_part_set_instruction (bus->part, "EJTAG_DATA"); urj_tap_chain_shift_instructions (bus->chain); urj_tap_register_fill (ejdata->in, 0); urj_tap_chain_shift_data_registers (bus->chain, 1); ret = reg_value (ejdata->out); urj_log (URJ_LOG_LEVEL_COMM, "Read from ejdata->out(%c) =%s %08lX\n", siz_ (sz), urj_tap_register_get_string (ejdata->out), (long unsigned) reg_value (ejdata->out)); urj_part_set_instruction (bus->part, "EJTAG_CONTROL"); urj_tap_chain_shift_instructions (bus->chain); urj_tap_register_fill (ejctrl->in, 0); ejctrl->in->data[PrAcc] = 1; ejctrl->in->data[ProbEn] = 1; urj_tap_chain_shift_data_registers (bus->chain, 1); // Disable DMA, reset state to previous one. urj_log (URJ_LOG_LEVEL_ALL, "Wrote to ejctrl->in =%s %08lX\n", urj_tap_register_get_string (ejctrl->in), (long unsigned) reg_value (ejctrl->in)); urj_log (URJ_LOG_LEVEL_ALL, "Read from ejctrl->out =%s %08lX\n", urj_tap_register_get_string (ejctrl->out), (long unsigned) reg_value(ejctrl->out)); if (ejctrl->out->data[Derr] == 1) { // Check for DMA error, i.e. incorrect address urj_error_set (URJ_ERROR_BUS_DMA, _("dma read (dma transaction failed)")); } switch (sz) { case DMA_HALFWORD: if (addr & 2) ret = (ret >> 16) & 0xffff; else ret = ret & 0xffff; break; case DMA_BYTE: if ((addr & 3) == 3) ret = (ret >> 24) & 0xff; else if ((addr & 3) == 2)
/** * low-level dma write * */ static void ejtag_dma_write (urj_bus_t *bus, unsigned int addr, unsigned int data, int sz) { static urj_data_register_t *ejctrl = NULL; static urj_data_register_t *ejaddr = NULL; static urj_data_register_t *ejdata = NULL; int i = 0; int timeout = 5; if (ejctrl == NULL) ejctrl = urj_part_find_data_register (bus->part, "EJCONTROL"); if (ejaddr == NULL) ejaddr = urj_part_find_data_register (bus->part, "EJADDRESS"); if (ejdata == NULL) ejdata = urj_part_find_data_register (bus->part, "EJDATA"); switch (sz) { /* Fill the other bytes with copy of the current */ case DMA_BYTE: data &= 0xff; data |= (data << 8) | (data << 16) | (data << 24); break; case DMA_HALFWORD: data &= 0xffff; data |= (data << 16); break; default: break; } urj_part_set_instruction (bus->part, "EJTAG_ADDRESS"); urj_tap_chain_shift_instructions (bus->chain); for (i = 0; i < 32; i++) ejaddr->in->data[i] = (addr >> i) & 1; urj_tap_chain_shift_data_registers (bus->chain, 0); /* Push the address to write */ urj_log (URJ_LOG_LEVEL_COMM, "Wrote to ejaddr->in =%s %08lX\n", urj_tap_register_get_string (ejaddr->in), (long unsigned) reg_value (ejaddr->in)); urj_part_set_instruction (bus->part, "EJTAG_DATA"); urj_tap_chain_shift_instructions (bus->chain); for (i = 0; i < 32; i++) ejdata->in->data[i] = (data >> i) & 1; urj_tap_chain_shift_data_registers (bus->chain, 0); /* Push the data to write */ urj_log (URJ_LOG_LEVEL_COMM, "Wrote to edata->in(%c) =%s %08lX\n", siz_ (sz), urj_tap_register_get_string (ejdata->in), (long unsigned) reg_value (ejdata->in)); urj_part_set_instruction (bus->part, "EJTAG_CONTROL"); urj_tap_chain_shift_instructions (bus->chain); urj_tap_register_fill (ejctrl->in, 0); ejctrl->in->data[PrAcc] = 1; // Processor access ejctrl->in->data[ProbEn] = 1; ejctrl->in->data[DmaAcc] = 1; // DMA operation request */ ejctrl->in->data[DstRt] = 1; if (sz) ejctrl->in->data[sz] = 1; // Size : can be WORD/HALFWORD or nothing for byte urj_tap_chain_shift_data_registers (bus->chain, 0); /* Do the operation */ urj_log (URJ_LOG_LEVEL_ALL, "Wrote to ejctrl->in =%s %08lX\n", urj_tap_register_get_string (ejctrl->in), (long unsigned) reg_value (ejctrl->in)); do { urj_part_set_instruction (bus->part, "EJTAG_CONTROL"); urj_tap_chain_shift_instructions (bus->chain); urj_tap_register_fill (ejctrl->in, 0); ejctrl->in->data[PrAcc] = 1; ejctrl->in->data[ProbEn] = 1; ejctrl->in->data[DmaAcc] = 1; urj_tap_chain_shift_data_registers (bus->chain, 1); timeout--; if (!timeout) break; } while (ejctrl->out->data[DstRt] == 1); // This flag tell us the processor has completed the op urj_part_set_instruction (bus->part, "EJTAG_CONTROL"); urj_tap_chain_shift_instructions (bus->chain); urj_tap_register_fill (ejctrl->in, 0); ejctrl->in->data[PrAcc] = 1; ejctrl->in->data[ProbEn] = 1; urj_tap_chain_shift_data_registers (bus->chain, 1); // Disable DMA, reset state to previous one. if (ejctrl->out->data[Derr] == 1) { // Check for DMA error, i.e. incorrect address urj_error_set (URJ_ERROR_BUS_DMA, _("dma write (dma transaction failed)")); } return; }