static int parse_param_lu(const char *eq, long unsigned *lu) { eq += 1; /* Handle hex values as well as decimal. While the C library will take * care of this for us if we used the 'i' conversion modifier, that takes * us into the signed/unsigned world. Unfortunately, the 'u' conversion * modifier doesn't handle hex values transparently. So do it ourselves. */ if (strncmp(eq, "0x", 2)) { if (sscanf(eq, "%lu", lu) == 1) return URJ_STATUS_OK; } else { if (sscanf(eq, "%lx", lu) == 1) return URJ_STATUS_OK; } urj_error_set (URJ_ERROR_SYNTAX, "need unsigned int, not '%s'", eq); return URJ_STATUS_FAIL; }
static int intel_flash_program_buffer (urj_flash_cfi_array_t *cfi_array, uint32_t adr, uint32_t *buffer, int count) { /* NOTE: Write-to-buffer programming operation according to [5], Figure 9 */ uint16_t sr; urj_bus_t *bus = cfi_array->bus; urj_flash_cfi_chip_t *cfi_chip = cfi_array->cfi_chips[0]; int wb_bytes = cfi_chip->cfi.device_geometry.max_bytes_write; int chip_width = cfi_chip->width; int offset = 0; while (count > 0) { int wcount, idx; uint32_t block_adr = adr; /* determine length of next multi-byte write */ wcount = wb_bytes - (adr % wb_bytes); wcount /= chip_width; if (wcount > count) wcount = count; /* issue command WRITE_TO_BUFFER */ URJ_BUS_WRITE (bus, cfi_array->address, CFI_INTEL_CMD_CLEAR_STATUS_REGISTER); /* poll XSR7 == 1 */ do { URJ_BUS_WRITE (bus, adr, CFI_INTEL_CMD_WRITE_TO_BUFFER); } while (!((sr = URJ_BUS_READ (bus, cfi_array->address) & 0xFE) & CFI_INTEL_SR_READY)); /* TODO: add timeout */ /* write count value (number of upcoming writes - 1) */ URJ_BUS_WRITE (bus, adr, wcount - 1); /* write payload to buffer */ for (idx = 0; idx < wcount; idx++) { URJ_BUS_WRITE (bus, adr, buffer[offset + idx]); adr += cfi_array->bus_width; } offset += wcount; /* issue command WRITE_CONFIRM */ URJ_BUS_WRITE (bus, block_adr, CFI_INTEL_CMD_WRITE_CONFIRM); count -= wcount; } /* poll SR7 == 1 */ while (!((sr = URJ_BUS_READ (bus, cfi_array->address) & 0xFE) & CFI_INTEL_SR_READY)); /* TODO: add timeout */ URJ_BUS_WRITE (bus, cfi_array->address, 0x00FF00FF); if (sr != CFI_INTEL_SR_READY) { urj_error_set (URJ_ERROR_FLASH_PROGRAM, _("unknown error while programming")); return URJ_STATUS_FAIL; } return URJ_STATUS_OK; }
static urj_bus_t * mpc837x_bus_new( urj_chain_t *chain, const urj_bus_driver_t *driver, const urj_param_t *cmd_params[] ) { urj_bus_t *bus; bus_params_t *bp; urj_part_t *part; char buff[10]; int i; int failed = 0; bus = urj_bus_generic_new (chain, driver, sizeof (bus_params_t)); if (bus == NULL) return NULL; part = bus->part; bp = bus->params; /* default values */ bp->lbc_muxed = 0; bp->lbc_num_d = 8; bp->lbc_num_ad = 25; for (i = 0; cmd_params[i] != NULL; i++) { switch (cmd_params[i]->key) { case URJ_BUS_PARAM_KEY_HELP: urj_bus_generic_free (bus); urj_log (URJ_LOG_LEVEL_NORMAL, _("Usage: initbus mpc837x [mux] [width=WIDTH]\n" \ " MUX multiplexed data bus (default no)\n" \ " WIDTH data bus width - 8, 16, 32 (default 8)\n")); return NULL; case URJ_BUS_PARAM_KEY_MUX: bp->lbc_muxed = 1; break; case URJ_BUS_PARAM_KEY_WIDTH: switch (cmd_params[i]->value.lu) { case 8: bp->lbc_num_d = 8; break; case 16: bp->lbc_num_d = 16; break; case 32: bp->lbc_num_d = 32; break; default: urj_error_set (URJ_ERROR_UNSUPPORTED, _(" Only 8, 16, 32 bus width are suported\n")); } break; default: urj_bus_generic_free (bus); urj_error_set (URJ_ERROR_SYNTAX, "unrecognised bus parameter '%s'", \ urj_param_string(&urj_bus_param_list, cmd_params[i])); return NULL; } } if ((!bp->lbc_muxed) && (bp->lbc_num_d > 16)) { urj_bus_generic_free (bus); urj_error_set (URJ_ERROR_UNSUPPORTED, _(" Only 8 and 16 non multiplexed bus width are suported\n")); return NULL; } if (bp->lbc_muxed) bp->lbc_num_ad = 32; /* Get the signals */ if (bp->lbc_muxed) { failed |= urj_bus_generic_attach_sig( part, &(ALE), "LALE" ); for (i = 0; i < LBC_NUM_LAD; i++) { sprintf( buff, "LAD%d", i ); failed |= urj_bus_generic_attach_sig( part, &(LAD[i]), buff ); } } else { failed |= urj_bus_generic_attach_sig( part, &(LA[7]), "LDP2" ); failed |= urj_bus_generic_attach_sig( part, &(LA[8]), "LDP3" ); failed |= urj_bus_generic_attach_sig( part, &(LA[9]), "LGPL5" ); failed |= urj_bus_generic_attach_sig( part, &(LA[10]), "LALE" ); for (i = 11; i < 27; i++) { sprintf( buff, "LAD%d", i + 5 ); failed |= urj_bus_generic_attach_sig( part, &(LA[i]), buff ); } } for (i = 27; i < LBC_NUM_LAD; i++) { sprintf( buff, "LA%d", i ); failed |= urj_bus_generic_attach_sig( part, &(LA[i]), buff ); } for (i = 0; i < LBC_NUM_LCS; i++) { sprintf( buff, "LCS_B%d", i ); failed |= urj_bus_generic_attach_sig( part, &(nCS[i]), buff ); } for (i = 0; i < LBC_NUM_LWE; i++) { sprintf( buff, "LWE_B%d", i ); failed |= urj_bus_generic_attach_sig( part, &(nWE[i]), buff ); } failed |= urj_bus_generic_attach_sig( part, &(nOE), "LGPL2" ); failed |= urj_bus_generic_attach_sig( part, &(BCTL), "LBCTL" ); if (failed) { urj_bus_generic_free (bus); return NULL; } urj_log(URJ_LOG_LEVEL_NORMAL, "%sMUXed %db address, %db data bus\n", ((bp->lbc_muxed) ? "" : "Non-"), bp->lbc_num_ad, bp->lbc_num_d); return bus; }
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 int cmd_bfin_run (urj_chain_t *chain, char *params[]) { int num_params; num_params = urj_cmd_params (params); if (num_params < 2) { urj_error_set (URJ_ERROR_SYNTAX, "#parameters should be >= 2, not %d", num_params); return URJ_STATUS_FAIL; } /* The remaining commands require cable or parts. */ if (urj_cmd_test_cable (chain) != URJ_STATUS_OK) return URJ_STATUS_FAIL; if (!chain->parts) { urj_error_set (URJ_ERROR_ILLEGAL_STATE, "no parts, Run '%s' first", "detect"); return URJ_STATUS_FAIL; } if (chain->active_part >= chain->parts->len) { urj_error_set (URJ_ERROR_ILLEGAL_STATE, "no active part"); return URJ_STATUS_FAIL; } if (!part_is_bfin (chain, chain->active_part)) { urj_error_set (URJ_ERROR_ILLEGAL_STATE, "not a Blackfin part"); return URJ_STATUS_FAIL; } assert (chain->active_part >= 0 && chain->active_part < chain->parts->len); if (strcmp (params[1], "emulation") == 0) { if (num_params != 3) { urj_error_set (URJ_ERROR_BFIN, "'bfin emulation' requires 1 parameter, not %d", num_params - 2); return URJ_STATUS_FAIL; } if (strcmp (params[2], "enable") == 0) { part_emulation_enable (chain, chain->active_part); } else if (strcmp (params[2], "trigger") == 0) { part_emulation_trigger (chain, chain->active_part); } else if (strcmp (params[2], "enter") == 0) { part_emulation_enable (chain, chain->active_part); part_emulation_trigger (chain, chain->active_part); } else if (strcmp (params[2], "return") == 0) { part_emulation_return (chain, chain->active_part); } else if (strcmp (params[2], "disable") == 0) { part_emulation_disable (chain, chain->active_part); } else if (strcmp (params[2], "exit") == 0) { part_emulation_return (chain, chain->active_part); part_emulation_disable (chain, chain->active_part); } else if (strcmp (params[2], "status") == 0) { uint16_t dbgstat, excause; const char *str_excause; urj_part_t *part; part_dbgstat_get (chain, chain->active_part); part = chain->parts->parts[chain->active_part]; dbgstat = BFIN_PART_DBGSTAT (part); excause = part_dbgstat_emucause (chain, chain->active_part); switch (excause) { case 0x0: str_excause = "EMUEXCPT was executed"; break; case 0x1: str_excause = "EMUIN pin was asserted"; break; case 0x2: str_excause = "Watchpoint event occurred"; break; case 0x4: str_excause = "Performance Monitor 0 overflowed"; break; case 0x5: str_excause = "Performance Monitor 1 overflowed"; break; case 0x8: str_excause = "Emulation single step"; break; default: str_excause = "Reserved??"; break; } urj_log (URJ_LOG_LEVEL_NORMAL, "Core [%d] DBGSTAT = 0x%"PRIx16"\n", chain->active_part, dbgstat); urj_log (URJ_LOG_LEVEL_NORMAL, "\tEMUDOF = %u\n" "\tEMUDIF = %u\n" "\tEMUDOOVF = %u\n" "\tEMUDIOVF = %u\n" "\tEMUREADY = %u\n" "\tEMUACK = %u\n" "\tEMUCAUSE = 0x%x (%s)\n" "\tBIST_DONE = %u\n" "\tLPDEC0 = %u\n" "\tIN_RESET = %u\n" "\tIDLE = %u\n" "\tCORE_FAULT = %u\n" "\tLPDEC1 = %u\n", part_dbgstat_is_emudof (chain, chain->active_part), part_dbgstat_is_emudif (chain, chain->active_part), part_dbgstat_is_emudoovf (chain, chain->active_part), part_dbgstat_is_emudiovf (chain, chain->active_part), part_dbgstat_is_emuready (chain, chain->active_part), part_dbgstat_is_emuack (chain, chain->active_part), excause, str_excause, part_dbgstat_is_bist_done (chain, chain->active_part), part_dbgstat_is_lpdec0 (chain, chain->active_part), part_dbgstat_is_in_reset (chain, chain->active_part), part_dbgstat_is_idle (chain, chain->active_part), part_dbgstat_is_core_fault (chain, chain->active_part), part_dbgstat_is_lpdec1 (chain, chain->active_part)); } else if (strcmp (params[2], "singlestep") == 0) { part_dbgstat_get (chain, chain->active_part); if (!part_dbgstat_is_emuready (chain, chain->active_part)) { urj_error_set (URJ_ERROR_BFIN, "Run '%s' first", "bfin emulation enter"); return URJ_STATUS_FAIL; } /* TODO Allow an argument to specify how many single steps. */ part_scan_select (chain, chain->active_part, DBGCTL_SCAN); part_dbgctl_bit_set_esstep (chain, chain->active_part); urj_tap_chain_shift_data_registers_mode (chain, 0, 1, URJ_CHAIN_EXITMODE_UPDATE); part_emuir_set (chain, chain->active_part, INSN_RTE, URJ_CHAIN_EXITMODE_IDLE); part_scan_select (chain, chain->active_part, DBGCTL_SCAN); part_dbgctl_bit_clear_esstep (chain, chain->active_part); urj_tap_chain_shift_data_registers_mode (chain, 0, 1, URJ_CHAIN_EXITMODE_UPDATE); } else { urj_error_set (URJ_ERROR_BFIN, "unknown emulation subcommand '%s'", params[2]); return URJ_STATUS_FAIL; } return URJ_STATUS_OK; } else if (strcmp (params[1], "execute") == 0) { int execute_ret = URJ_STATUS_FAIL; part_dbgstat_get (chain, chain->active_part); if (!part_dbgstat_is_emuready (chain, chain->active_part)) { urj_error_set (URJ_ERROR_BFIN, "Run '%s' first", "bfin emulation enter"); return URJ_STATUS_FAIL; } if (num_params > 2) { int i; struct bfin_insn *insns = NULL; struct bfin_insn **last = &insns; char tmp[8]; char *tmpfile = NULL; for (i = 2; i < num_params; i++) { if (params[i][0] == '[' && params[i][1] == '0') { uint64_t n; if (sscanf (params[i], "[0%[xX]%"PRIx64"]", tmp, &n) != 2) goto execute_cleanup; *last = (struct bfin_insn *) malloc (sizeof (struct bfin_insn)); if (*last == NULL) goto execute_cleanup; (*last)->i = n; (*last)->type = BFIN_INSN_SET_EMUDAT; (*last)->next = NULL; last = &((*last)->next); } else if (params[i][0] == '0') { uint64_t n; if (sscanf (params[i], "0%[xX]%"PRIx64, tmp, &n) != 2) goto execute_cleanup; *last = (struct bfin_insn *) malloc (sizeof (struct bfin_insn)); if (*last == NULL) goto execute_cleanup; (*last)->i = n; (*last)->type = BFIN_INSN_NORMAL; (*last)->next = NULL; last = &((*last)->next); } else { #ifndef HAVE_SYS_WAIT_H urj_error_set (URJ_ERROR_BFIN, "Sorry, dynamic code not available for your platform"); goto execute_cleanup; #else unsigned char raw_insn[4]; char *tmp_buf; char *tuples[] = {"uclinux", "linux-uclibc", "elf"}; size_t t; FILE *fp; /* 1024 should be plenty. */ char insns_string[1024]; char *p = insns_string; for (; i < num_params; i++) { p += snprintf (p, sizeof (insns_string) - (p - insns_string), "%s ", params[i]); if (params[i][strlen (params[i]) - 1] == '"') break; if (params[i][strlen (params[i]) - 1] == ';') break; } if (i == num_params) { urj_error_set (URJ_ERROR_BFIN, "unbalanced double quotes"); goto execute_cleanup; } /* p points past the '\0'. p - 1 points to the ending '\0'. p - 2 points to the last double quote. */ *(p - 2) = ';'; if (insns_string[0] == '"') insns_string[0] = ' '; /* HRM states that branches and hardware loop setup results in undefined behavior. Should check opcode instead? */ if (strcasestr(insns_string, "jump") || strcasestr(insns_string, "call") || strcasestr(insns_string, "lsetup")) urj_warning (_("jump/call/lsetup insns may not work in emulation\n")); /* get a temporary file to work with -- a little racy */ if (!tmpfile) { tmpfile = tmpnam (NULL); if (!tmpfile) goto execute_cleanup; tmpfile = strdup (tmpfile); if (!tmpfile) goto execute_cleanup; } /* try to find a toolchain in $PATH */ for (t = 0; t < ARRAY_SIZE(tuples); ++t) { int ret; /* TODO Pass -mcpu= to gas. */ ret = asprintf (&tmp_buf, "bfin-%3$s-as --version >/dev/null 2>&1 || exit $?;" "echo '%1$s' | bfin-%3$s-as - -o \"%2$s\"" " && bfin-%3$s-objcopy -O binary \"%2$s\"", insns_string, tmpfile, tuples[t]); if (ret == -1) { urj_error_set (URJ_ERROR_OUT_OF_MEMORY, _("asprintf() failed")); goto execute_cleanup; } ret = system (tmp_buf); free (tmp_buf); if (WIFEXITED(ret)) { if (WEXITSTATUS(ret) == 0) break; /* 127 -> not found in $PATH */ else if (WEXITSTATUS(ret) == 127) continue; else { urj_error_set (URJ_ERROR_BFIN, "GAS failed parsing: %s", insns_string); goto execute_cleanup; } } } if (t == ARRAY_SIZE(tuples)) { urj_error_set (URJ_ERROR_BFIN, "unable to find Blackfin toolchain in $PATH\n"); goto execute_cleanup; } /* Read the binary blob from the toolchain */ fp = fopen (tmpfile, FOPEN_R); if (fp == NULL) goto execute_cleanup; /* Figure out how many instructions there are */ t = 0; p = insns_string; while ((p = strchr(p, ';')) != NULL) { ++t; ++p; } while (t-- && fread (raw_insn, 1, 2, fp) == 2) { uint16_t iw = raw_insn[0] | (raw_insn[1] << 8); uint64_t n = iw; int is_multiinsn = INSN_IS_MULTI (raw_insn[1]); if ((iw & 0xf000) >= 0xc000) { if (fread (raw_insn, 1, 2, fp) != 2) goto execute_cleanup; iw = raw_insn[0] | (raw_insn[1] << 8); n = (n << 16) | iw; } if (is_multiinsn) { if (fread (raw_insn, 1, 4, fp) != 4) goto execute_cleanup; n = (n << 32) | ((uint64_t)raw_insn[0] << 16) | ((uint64_t)raw_insn[1] << 24) | raw_insn[2] | (raw_insn[3] << 8); } *last = (struct bfin_insn *) malloc (sizeof (struct bfin_insn)); if (*last == NULL) goto execute_cleanup; (*last)->i = n; (*last)->type = BFIN_INSN_NORMAL; (*last)->next = NULL; last = &((*last)->next); } fclose (fp); #endif } } part_execute_instructions (chain, chain->active_part, insns); execute_ret = URJ_STATUS_OK; execute_cleanup: if (tmpfile) { unlink (tmpfile); free (tmpfile); } while (insns) { struct bfin_insn *tmp = insns->next; free (insns); insns = tmp; } } if (execute_ret == URJ_STATUS_OK) { uint64_t emudat; emudat = part_emudat_get (chain, chain->active_part, URJ_CHAIN_EXITMODE_UPDATE); urj_log (URJ_LOG_LEVEL_NORMAL, "EMUDAT = 0x%"PRIx64"\n", emudat); part_dbgstat_get (chain, chain->active_part); if (part_dbgstat_is_core_fault (chain, chain->active_part)) urj_warning (_("core fault detected\n")); } return execute_ret; } else if (strcmp (params[1], "reset") == 0) { int reset_what = 0; part_dbgstat_get (chain, chain->active_part); if (!part_dbgstat_is_emuready (chain, chain->active_part)) { urj_error_set (URJ_ERROR_BFIN, "Run '%s' first", "bfin emulation enter"); return URJ_STATUS_FAIL; } if (num_params == 3) { if (!strcmp (params[2], "core")) reset_what |= 0x1; else if (!strcmp (params[2], "system")) reset_what |= 0x2; else { urj_error_set (URJ_ERROR_BFIN, "bad parameter '%s'", params[2]); return URJ_STATUS_FAIL; } } else if (num_params == 2) reset_what = 0x1 | 0x2; else { urj_error_set (URJ_ERROR_BFIN, "'bfin emulation' requires 0 or 1 parameter, not %d", num_params - 2); return URJ_STATUS_FAIL; } urj_log (URJ_LOG_LEVEL_NORMAL, _("%s: reseting processor ... "), "bfin"); fflush (stdout); if (reset_what == 0x3) software_reset (chain, chain->active_part); else if (reset_what & 0x1) bfin_core_reset (chain, chain->active_part); else if (reset_what & 0x2) chain_system_reset (chain); urj_log (URJ_LOG_LEVEL_NORMAL, _("OK\n")); return URJ_STATUS_OK; } else { urj_error_set (URJ_ERROR_BFIN, "unknown command '%s'", params[1]); return URJ_STATUS_FAIL; } return URJ_STATUS_OK; }
int urj_flash_cfi_detect (urj_bus_t *bus, uint32_t adr, urj_flash_cfi_array_t **cfi_array) { unsigned int bw; /* bus width */ unsigned int d; /* data offset */ size_t ba; /* bus width address multiplier */ int ma; /* flash mode address multiplier */ urj_bus_area_t area; if (!cfi_array || !bus) { urj_error_set (URJ_ERROR_INVALID, "cfi_array or bus"); return URJ_STATUS_FAIL; } *cfi_array = calloc (1, sizeof (urj_flash_cfi_array_t)); if (!*cfi_array) { urj_error_set (URJ_ERROR_OUT_OF_MEMORY, "calloc(%zd,%zd) fails", (size_t) 1, sizeof (urj_flash_cfi_array_t)); return URJ_STATUS_FAIL; } (*cfi_array)->bus = bus; (*cfi_array)->address = adr; if (URJ_BUS_AREA (bus, adr, &area) != URJ_STATUS_OK) // retain error state return URJ_STATUS_FAIL; if (URJ_BUS_TYPE (bus) != URJ_BUS_TYPE_PARALLEL) return URJ_STATUS_FAIL; bw = area.width; if (bw != 8 && bw != 16 && bw != 32) { urj_error_set (URJ_ERROR_INVALID, "bus width = %d", bw); return URJ_STATUS_FAIL; } (*cfi_array)->bus_width = ba = bw / 8; (*cfi_array)->cfi_chips = calloc (ba, sizeof (urj_flash_cfi_chip_t *)); if (!(*cfi_array)->cfi_chips) { urj_error_set (URJ_ERROR_OUT_OF_MEMORY, "calloc(%zd,%zd) fails", ba, sizeof (urj_flash_cfi_chip_t *)); return URJ_STATUS_FAIL; } for (d = 0; d < bw; d += 8) { #define A(off) (adr + (off) * ba * ma) #define D(data) ((data) << d) #define gD(data) (((data) >> d) & 0xFF) #define read1(off) gD(URJ_BUS_READ( bus, A(off) )) // @@@@ RFHH check status of URJ_BUS_READ_START #define read2(off) (URJ_BUS_READ_START (bus, A(off)), gD (URJ_BUS_READ_NEXT (bus, A((off) + 1))) | gD (URJ_BUS_READ_END (bus)) << 8) #define write1(off,data) URJ_BUS_WRITE( bus, A(off), D(data) ) urj_flash_cfi_query_structure_t *cfi; uint32_t tmp; int ret = -4; /* CFI not detected (Q) */ uint16_t pri_vendor_tbl_adr; /* detect CFI capable devices - see Table 1 in [1] */ for (ma = 1; ma <= 4; ma *= 2) { write1 (CFI_CMD_QUERY_OFFSET, CFI_CMD_QUERY); if (read1 (CFI_QUERY_ID_OFFSET) == 'Q') { ret = -5; /* CFI not detected (R) */ if (read1 (CFI_QUERY_ID_OFFSET + 1) == 'R') break; } write1 (0, CFI_CMD_READ_ARRAY1); write1 (0, CFI_CMD_READ_ARRAY2); } if (ma > 4) { if (ret == -4) urj_error_set (URJ_ERROR_FLASH, "CFI not detected (Q)"); else urj_error_set (URJ_ERROR_FLASH, "CFI not detected (R)"); return URJ_STATUS_FAIL; } if (read1 (CFI_QUERY_ID_OFFSET + 2) != 'Y') { write1 (0, CFI_CMD_READ_ARRAY1); write1 (0, CFI_CMD_READ_ARRAY2); urj_error_set (URJ_ERROR_FLASH, "CFI not detected (Y)"); return URJ_STATUS_FAIL; } (*cfi_array)->cfi_chips[d / 8] = calloc (1, sizeof (urj_flash_cfi_chip_t)); if (!(*cfi_array)->cfi_chips[d / 8]) { write1 (0, CFI_CMD_READ_ARRAY1); write1 (0, CFI_CMD_READ_ARRAY2); urj_error_set (URJ_ERROR_OUT_OF_MEMORY, "calloc(%zd,%zd) fails", (size_t) 1, sizeof (urj_flash_cfi_chip_t)); return URJ_STATUS_FAIL; } cfi = &(*cfi_array)->cfi_chips[d / 8]->cfi; /* Identification string - see Table 6 in [1] */ cfi->identification_string.pri_id_code = read2 (PRI_VENDOR_ID_OFFSET); cfi->identification_string.pri_vendor_tbl = NULL; cfi->identification_string.alt_id_code = read2 (ALT_VENDOR_ID_OFFSET); cfi->identification_string.alt_vendor_tbl = NULL; /* System interface information - see Table 7 in [1] */ tmp = read1 (VCC_MIN_WEV_OFFSET); cfi->system_interface_info.vcc_min_wev = ((tmp >> 4) & 0xF) * 1000 + (tmp & 0xF) * 100; tmp = read1 (VCC_MAX_WEV_OFFSET); cfi->system_interface_info.vcc_max_wev = ((tmp >> 4) & 0xF) * 1000 + (tmp & 0xF) * 100; tmp = read1 (VPP_MIN_WEV_OFFSET); cfi->system_interface_info.vpp_min_wev = ((tmp >> 4) & 0xF) * 1000 + (tmp & 0xF) * 100; tmp = read1 (VPP_MAX_WEV_OFFSET); cfi->system_interface_info.vpp_max_wev = ((tmp >> 4) & 0xF) * 1000 + (tmp & 0xF) * 100; /* TODO: Add out of range checks for timeouts */ tmp = read1 (TYP_SINGLE_WRITE_TIMEOUT_OFFSET); cfi->system_interface_info.typ_single_write_timeout = tmp ? (1 << tmp) : 0; tmp = read1 (TYP_BUFFER_WRITE_TIMEOUT_OFFSET); cfi->system_interface_info.typ_buffer_write_timeout = tmp ? (1 << tmp) : 0; tmp = read1 (TYP_BLOCK_ERASE_TIMEOUT_OFFSET); cfi->system_interface_info.typ_block_erase_timeout = tmp ? (1 << tmp) : 0; tmp = read1 (TYP_CHIP_ERASE_TIMEOUT_OFFSET); cfi->system_interface_info.typ_chip_erase_timeout = tmp ? (1 << tmp) : 0; tmp = read1 (MAX_SINGLE_WRITE_TIMEOUT_OFFSET); cfi->system_interface_info.max_single_write_timeout = (tmp ? (1 << tmp) : 0) * cfi->system_interface_info.typ_single_write_timeout; tmp = read1 (MAX_BUFFER_WRITE_TIMEOUT_OFFSET); cfi->system_interface_info.max_buffer_write_timeout = (tmp ? (1 << tmp) : 0) * cfi->system_interface_info.typ_buffer_write_timeout; tmp = read1 (MAX_BLOCK_ERASE_TIMEOUT_OFFSET); cfi->system_interface_info.max_block_erase_timeout = (tmp ? (1 << tmp) : 0) * cfi->system_interface_info.typ_block_erase_timeout; tmp = read1 (MAX_CHIP_ERASE_TIMEOUT_OFFSET); cfi->system_interface_info.max_chip_erase_timeout = (tmp ? (1 << tmp) : 0) * cfi->system_interface_info.typ_chip_erase_timeout; /* Device geometry - see Table 8 in [1] */ /* TODO: Add out of range check */ cfi->device_geometry.device_size = 1 << read1 (DEVICE_SIZE_OFFSET); cfi->device_geometry.device_interface = read2 (FLASH_DEVICE_INTERFACE_OFFSET); /* TODO: Add out of range check */ cfi->device_geometry.max_bytes_write = 1 << read2 (MAX_BYTES_WRITE_OFFSET); tmp = cfi->device_geometry.number_of_erase_regions = read1 (NUMBER_OF_ERASE_REGIONS_OFFSET); cfi->device_geometry.erase_block_regions = malloc (tmp * sizeof (urj_flash_cfi_erase_block_region_t)); if (!cfi->device_geometry.erase_block_regions) { write1 (0, CFI_CMD_READ_ARRAY1); write1 (0, CFI_CMD_READ_ARRAY2); urj_error_set (URJ_ERROR_OUT_OF_MEMORY, "malloc(%zd) fails", (size_t) tmp * sizeof (urj_flash_cfi_erase_block_region_t)); return URJ_STATUS_FAIL; } { int a; int i; for (i = 0, a = ERASE_BLOCK_REGION_OFFSET; i < tmp; i++, a += 4) { uint32_t y = read2 (a); uint32_t z = read2 (a + 2) << 8; if (z == 0) z = 128; cfi->device_geometry.erase_block_regions[i].erase_block_size = z; cfi->device_geometry.erase_block_regions[i]. number_of_erase_blocks = y + 1; } } pri_vendor_tbl_adr = read2 (PRI_VENDOR_TABLE_ADR_OFFSET); /* AMD CFI Primary Vendor-Specific Extended Query Table - see [3] and [4] */ if (cfi->identification_string.pri_id_code == CFI_VENDOR_AMD_SCS && pri_vendor_tbl_adr != 0) { urj_flash_cfi_amd_pri_extened_query_structure_t *pri_vendor_tbl; uint8_t major_version; uint8_t minor_version; uint8_t num_of_banks; int i; #undef A #define A(off) (adr + (pri_vendor_tbl_adr + (off)) * ba * ma) if (read1 (0) != 'P' || read1 (1) != 'R' || read1 (2) != 'I') { write1 (0, CFI_CMD_READ_ARRAY1); write1 (0, CFI_CMD_READ_ARRAY2); urj_error_set (URJ_ERROR_FLASH, "CFI primary vendor table not detected"); return URJ_STATUS_FAIL; } major_version = read1 (MAJOR_VERSION_OFFSET); minor_version = read1 (MINOR_VERSION_OFFSET); if (major_version > '1' || (major_version == '1' && minor_version >= '3')) num_of_banks = read1 (BANK_ORGANIZATION_OFFSET); else num_of_banks = 0; pri_vendor_tbl = calloc (1, sizeof (urj_flash_cfi_amd_pri_extened_query_structure_t) + num_of_banks * sizeof (uint8_t)); if (!pri_vendor_tbl) { write1 (0, CFI_CMD_READ_ARRAY1); write1 (0, CFI_CMD_READ_ARRAY2); urj_error_set (URJ_ERROR_OUT_OF_MEMORY, "calloc(%zd,%zd) fails", (size_t) 1, sizeof (urj_flash_cfi_amd_pri_extened_query_structure_t) + num_of_banks * sizeof (uint8_t)); return URJ_STATUS_FAIL; } if (major_version > '1' || (major_version == '1' && minor_version >= '0')) { pri_vendor_tbl->major_version = major_version; pri_vendor_tbl->minor_version = minor_version; pri_vendor_tbl->address_sensitive_unlock = read1 (ADDRESS_SENSITIVE_UNLOCK_OFFSET); pri_vendor_tbl->erase_suspend = read1 (ERASE_SUSPEND_OFFSET); pri_vendor_tbl->sector_protect = read1 (SECTOR_PROTECT_OFFSET); pri_vendor_tbl->sector_temporary_unprotect = read1 (SECTOR_TEMPORARY_UNPROTECT_OFFSET); pri_vendor_tbl->sector_protect_scheme = read1 (SECTOR_PROTECT_SCHEME_OFFSET); pri_vendor_tbl->simultaneous_operation = read1 (SIMULTANEOUS_OPERATION_OFFSET); pri_vendor_tbl->burst_mode_type = read1 (BURST_MODE_TYPE_OFFSET); pri_vendor_tbl->page_mode_type = read1 (PAGE_MODE_TYPE_OFFSET); } if (major_version > '1' || (major_version == '1' && minor_version >= '1')) { tmp = read1 (ACC_MIN_OFFSET); pri_vendor_tbl->acc_min = ((tmp >> 4) & 0xF) * 1000 + (tmp & 0xF) * 100; tmp = read1 (ACC_MAX_OFFSET); pri_vendor_tbl->acc_max = ((tmp >> 4) & 0xF) * 1000 + (tmp & 0xF) * 100; pri_vendor_tbl->top_bottom_sector_flag = read1 (TOP_BOTTOM_SECTOR_FLAG_OFFSET); } if (major_version > '1' || (major_version == '1' && minor_version >= '2')) pri_vendor_tbl->program_suspend = read1 (PROGRAM_SUSPEND_OFFSET); if (major_version > '1' || (major_version == '1' && minor_version >= '3')) { if (pri_vendor_tbl->simultaneous_operation) pri_vendor_tbl->bank_organization = read1 (BANK_ORGANIZATION_OFFSET); else pri_vendor_tbl->bank_organization = 0; for (i = 0; i < pri_vendor_tbl->bank_organization; i++) pri_vendor_tbl->bank_region_info[i] = read1 (BANK_REGION_INFO_OFFSET + i * sizeof (uint8_t)); } if (major_version > '1' || (major_version == '1' && minor_version >= '4')) { pri_vendor_tbl->unlock_bypass = read1 (UNLOCK_BYPASS_OFFSET); tmp = read1 (SECSI_SECTOR_SIZE_OFFSET); pri_vendor_tbl->secsi_sector_size = tmp ? (1 << tmp) : 0; tmp = read1 (EMBEDDED_HWRST_TIMEOUT_MAX_OFFSET); pri_vendor_tbl->embedded_hwrst_timeout_max = tmp ? (1 << tmp) : 0; tmp = read1 (NON_EMBEDDED_HWRST_TIMEOUT_MAX_OFFSET); pri_vendor_tbl->non_embedded_hwrst_timeout_max = tmp ? (1 << tmp) : 0; tmp = read1 (ERASE_SUSPEND_TIMEOUT_MAX_OFFSET); pri_vendor_tbl->erase_suspend_timeout_max = tmp ? (1 << tmp) : 0; tmp = read1 (PROGRAM_SUSPEND_TIMEOUT_MAX_OFFSET); pri_vendor_tbl->program_suspend_timeout_max = tmp ? (1 << tmp) : 0; } cfi->identification_string.pri_vendor_tbl = (void *) pri_vendor_tbl; #undef A #define A(off) (adr + (off) * ba * ma) /* Reverse the order of erase block region information for top boot devices. */ if ((major_version > '1' || (major_version == '1' && minor_version >= '1')) && pri_vendor_tbl->top_bottom_sector_flag == 0x3) { uint32_t y, z; uint32_t n = cfi->device_geometry.number_of_erase_regions; for (i = 0; i < n / 2; i++) { z = cfi->device_geometry.erase_block_regions[i]. erase_block_size; y = cfi->device_geometry.erase_block_regions[i]. number_of_erase_blocks; cfi->device_geometry.erase_block_regions[i]. erase_block_size = cfi->device_geometry.erase_block_regions[n - i - 1]. erase_block_size; cfi->device_geometry.erase_block_regions[i]. number_of_erase_blocks = cfi->device_geometry.erase_block_regions[n - i - 1]. number_of_erase_blocks; cfi->device_geometry.erase_block_regions[n - i - 1]. erase_block_size = z; cfi->device_geometry.erase_block_regions[n - i - 1]. number_of_erase_blocks = y; } } }
int urj_tap_cable_add_queue_item (urj_cable_t *cable, urj_cable_queue_info_t *q) { int i, j; if (q->num_items >= q->max_items) /* queue full? */ { int new_max_items; urj_cable_queue_t *resized; urj_log (URJ_LOG_LEVEL_DETAIL, "Queue %p needs resizing; n(%d) >= max(%d); free=%d, next=%d\n", q, q->num_items, q->max_items, q->next_free, q->next_item); new_max_items = q->max_items + 128; resized = realloc (q->data, new_max_items * sizeof (urj_cable_queue_t)); if (resized == NULL) { urj_error_set (URJ_ERROR_OUT_OF_MEMORY, "realloc(%s,%zd) fails", "q->data", new_max_items * sizeof (urj_cable_queue_t)); return -1; /* report failure */ } urj_log (URJ_LOG_LEVEL_DETAIL, _("(Resized JTAG activity queue to hold max %d items)\n"), new_max_items); q->data = resized; /* The queue was full. Except for the special case when next_item is 0, * resizing just introduced a gap between old and new max, which has to * be filled; either by moving data from next_item .. max_items, or * from 0 .. next_free (whatever is smaller). */ #define CHOOSE_SMALLEST_AREA_TO_MOVE 1 if (q->next_item != 0) { int added_space = new_max_items - q->max_items; int num_to_move = q->max_items - q->next_item; #ifdef CHOOSE_SMALLEST_AREA_TO_MOVE if (num_to_move <= q->next_free) #endif /* def CHOOSE_SMALLEST_AREA_TO_MOVE */ { /* Move queue items at end of old array * towards end of new array: 345612__ -> 3456__12 */ int dest = new_max_items - num_to_move; urj_log (URJ_LOG_LEVEL_DETAIL, "Resize: Move %d items towards end of queue memory (%d > %d)\n", num_to_move, q->next_item, dest); memmove (&q->data[dest], &q->data[q->next_item], num_to_move * sizeof (urj_cable_queue_t)); q->next_item = dest; } #ifdef CHOOSE_SMALLEST_AREA_TO_MOVE else { if (q->next_free <= added_space) { /* Relocate queue items at beginning of old array * to end of new array: 561234__ -> __123456 */ urj_log (URJ_LOG_LEVEL_DETAIL, "Resize: Move %d items from start to end\n", q->next_free); memcpy (&q->data[q->max_items], &q->data[0], q->next_free * sizeof (urj_cable_queue_t)); } else { /* Same as above, but for the case if new space * isn't large enough to hold all relocated items */ /* Step 1: 456123__ -> __612345 */ urj_log (URJ_LOG_LEVEL_DETAIL, "Resize.A: Move %d items from start to end\n", added_space); memcpy (&q->data[q->max_items], &q->data[0], added_space * sizeof (urj_cable_queue_t)); /* Step 2: __612345 -> 6__12345 */ urj_log (URJ_LOG_LEVEL_DETAIL, "Resize.B: Move %d items towards start (offset %d)\n", (q->next_free - added_space), added_space); memmove (&q->data[0], &q->data[added_space], (q->next_free - added_space) * sizeof (urj_cable_queue_t)); } } #endif /* def CHOOSE_SMALLEST_AREA_TO_MOVE */ } q->max_items = new_max_items; q->next_free = q->next_item + q->num_items; if (q->next_free >= new_max_items) q->next_free -= new_max_items; urj_log (URJ_LOG_LEVEL_DETAIL, "Queue %p after resizing; n(%d) >= max(%d); free=%d, next=%d\n", q, q->num_items, q->max_items, q->next_free, q->next_item); } i = q->next_free; j = i + 1; if (j >= q->max_items) j = 0; q->next_free = j; q->num_items++; // urj_log (URJ_LOG_LEVEL_DEBUG, "add_queue_item to %p: %d\n", q, i); return i; }
/** * bus->driver->(*new_bus) * */ static urj_bus_t * prototype_bus_new (urj_chain_t *chain, const urj_bus_driver_t *driver, const urj_param_t *cmd_params[]) { urj_bus_t *bus; urj_part_signal_t *sig; char buff[16], fmt[16], afmt[16], dfmt[16]; int i, j, inst, max, min; int failed = 0; int ashift = -1; const char *value; bus = urj_bus_generic_new (chain, driver, sizeof (bus_params_t)); if (bus == NULL) return NULL; CS = OE = WE = NULL; ALSBI = AMSBI = DLSBI = DMSBI = -1; for (i = 0; cmd_params[i] != NULL; i++) { if (cmd_params[i]->key == URJ_BUS_PARAM_KEY_AMODE || cmd_params[i]->key == URJ_BUS_PARAM_KEY_WIDTH) { switch (cmd_params[i]->value.lu) { case 8: ashift = 0; break; case 16: ashift = 1; break; case 32: ashift = 2; break; case 0: // "auto" break; default: urj_error_set (URJ_ERROR_INVALID, _("value %lu not defined for parameter %s"), cmd_params[i]->value.lu, urj_param_string(&urj_bus_param_list, cmd_params[i])); failed = 1; // @@@@ RFHH break; } } else { if (cmd_params[i]->type != URJ_PARAM_TYPE_STRING) { urj_error_set (URJ_ERROR_SYNTAX, "parameter must be of type string"); failed = 1; continue; } value = cmd_params[i]->value.string; inst = 32; prototype_bus_signal_parse (value, fmt, &inst); // @@@@ RFHH Flag error? // @@@@ RFHH If it is mandatory for a signal to have an int inst // number, why does prototype_bus_signal_parse() accept values // without an int? if (inst > 31 || inst < 0) continue; sig = urj_part_find_signal (bus->part, value); if (!sig) { urj_error_set (URJ_ERROR_NOTFOUND, _("signal '%s' not found"), value); failed = 1; continue; } switch (cmd_params[i]->key) { case URJ_BUS_PARAM_KEY_ALSB: ALSBI = inst; A[inst] = sig; strcpy (afmt, fmt); break; case URJ_BUS_PARAM_KEY_AMSB: AMSBI = inst; A[inst] = sig; strcpy (afmt, fmt); break; case URJ_BUS_PARAM_KEY_DLSB: DLSBI = inst; D[inst] = sig; strcpy (dfmt, fmt); break; case URJ_BUS_PARAM_KEY_DMSB: DMSBI = inst; D[inst] = sig; strcpy (dfmt, fmt); break; case URJ_BUS_PARAM_KEY_CS: case URJ_BUS_PARAM_KEY_NCS: CS = sig; CSA = (cmd_params[i]->key == URJ_BUS_PARAM_KEY_CS); break; case URJ_BUS_PARAM_KEY_OE: case URJ_BUS_PARAM_KEY_NOE: OE = sig; OEA = (cmd_params[i]->key == URJ_BUS_PARAM_KEY_OE); break; case URJ_BUS_PARAM_KEY_WE: case URJ_BUS_PARAM_KEY_NWE: WE = sig; WEA = (cmd_params[i]->key == URJ_BUS_PARAM_KEY_WE); break; default: urj_error_set (URJ_ERROR_INVALID, _("parameter %s is unknown"), urj_param_string(&urj_bus_param_list, cmd_params[i])); failed = 1; break; } } } if (ALSBI >= 0 || AMSBI >= 0) { if (ALSBI == -1 || AMSBI == -1) { for (min = 0; min <= 31; min++) { sprintf (buff, afmt, min); A[min] = urj_part_find_signal (bus->part, buff); if (A[min]) break; } for (max = 31; max >= 0; max--) { sprintf (buff, afmt, max); A[max] = urj_part_find_signal (bus->part, buff); if (A[max]) break; } if (ALSBI == -1) ALSBI = (max - AMSBI < AMSBI - min) ? min : max; else AMSBI = (max - ALSBI < ALSBI - min) ? min : max; } AI = (AMSBI > ALSBI ? 1 : -1); AW = (AMSBI > ALSBI ? AMSBI - ALSBI : ALSBI - AMSBI) + 1; for (i = 0, j = ALSBI; i < AW; i++, j += AI) { sprintf (buff, afmt, j); // @@@@ RFHH check result A[j] = urj_part_find_signal (bus->part, buff); } } else { urj_error_set (URJ_ERROR_INVALID, _("parameters alsb=<signal> and/or amsb=<signal> are not defined")); failed = 1; } if (DLSBI >= 0 || DMSBI >= 0) { if (DLSBI == -1 || DMSBI == -1) { for (min = 0; min <= 31; min++) { sprintf (buff, dfmt, min); D[min] = urj_part_find_signal (bus->part, buff); if (D[min]) break; } for (max = 31; max >= 0; max--) { sprintf (buff, dfmt, max); D[max] = urj_part_find_signal (bus->part, buff); if (D[max]) break; } if (DLSBI == -1) DLSBI = (max - DMSBI < DMSBI - min) ? min : max; else DMSBI = (max - DLSBI < DLSBI - min) ? min : max; } DI = (DMSBI > DLSBI ? 1 : -1); DW = (DMSBI > DLSBI ? DMSBI - DLSBI : DLSBI - DMSBI) + 1; for (i = 0, j = DLSBI; i < DW; i++, j += DI) { sprintf (buff, dfmt, j); D[j] = urj_part_find_signal (bus->part, buff); } /* bus drivers are called with a byte address this address needs to be adjusted by setup_address() to the memory data width */ if (ashift < 0) { int nbytes; /* parameter 'amode' wasn't specified, derive the address shift from the data bus width */ nbytes = DW / 8; if (DW % 8 > 0) nbytes++; ashift = 0; while (nbytes != 1) { nbytes >>= 1; ashift++; } } ASHIFT = ashift; }
static int cmd_print_run (urj_chain_t *chain, char *params[]) { #define FORMAT_LENGTH 128 char format[FORMAT_LENGTH]; #if HAVE_SWPRINTF wchar_t wformat[FORMAT_LENGTH]; #endif /* HAVE_SWPRINTF */ wchar_t wheader[FORMAT_LENGTH]; char header[FORMAT_LENGTH]; int i; int noheader = 0; if (urj_cmd_params (params) > 2) { urj_error_set (URJ_ERROR_SYNTAX, "%s: #parameters should be <= %d, not %d", params[0], 2, urj_cmd_params (params)); return URJ_STATUS_FAIL; } if (urj_cmd_test_cable (chain) != URJ_STATUS_OK) return URJ_STATUS_FAIL; if (!chain->parts) { urj_error_set (URJ_ERROR_ILLEGAL_STATE, "Run \"detect\" first"); return URJ_STATUS_FAIL; } if (urj_cmd_params (params) == 2) { if (strcasecmp (params[1], "bus") == 0) noheader = 1; if (strcasecmp (params[1], "signals") == 0) { urj_log (URJ_LOG_LEVEL_NORMAL, "Signals:\n"); urj_part_t *part; urj_part_signal_t *s; part = chain->parts->parts[chain->active_part]; for (s = part->signals; s != NULL; s = s->next) { urj_part_salias_t *sa; if (s->pin) urj_log (URJ_LOG_LEVEL_NORMAL, "%s %s", s->name, s->pin); else urj_log (URJ_LOG_LEVEL_NORMAL, "%s", s->name); if (s->input) urj_log (URJ_LOG_LEVEL_NORMAL, "\tinput=%s", s->input->name); if (s->output) urj_log (URJ_LOG_LEVEL_NORMAL, "\toutput=%s", s->output->name); for (sa = part->saliases; sa != NULL; sa = sa->next) { if (s == sa->signal) urj_log (URJ_LOG_LEVEL_NORMAL, "\tsalias=%s", sa->name); } urj_log (URJ_LOG_LEVEL_NORMAL, "\n"); } return URJ_STATUS_OK; } if (strcasecmp (params[1], "instructions") == 0) { urj_part_t *part; urj_part_instruction_t *inst; snprintf (format, sizeof format, _(" Active %%-%ds %%-%ds\n"), URJ_INSTRUCTION_MAXLEN_INSTRUCTION, URJ_DATA_REGISTER_MAXLEN); #if HAVE_SWPRINTF if (mbstowcs (wformat, format, sizeof format) == -1) // @@@@ RFHH throw urj_error? printf (_("(%d) String conversion failed!\n"), __LINE__); swprintf (wheader, sizeof format, wformat, _("Instruction"), _("Register")); if (wcstombs (header, wheader, sizeof format) == -1) // @@@@ RFHH throw urj_error? printf (_("(%d) String conversion failed!\n"), __LINE__); #else /* HAVE_SWPRINTF */ snprintf (header, sizeof format, format, _("Instruction"), _("Register")); if (mbstowcs (wheader, header, sizeof format) == -1) // @@@@ RFHH throw urj_error? printf (_("(%d) String conversion failed!\n"), __LINE__); #endif /* HAVE_SWPRINTF */ urj_log (URJ_LOG_LEVEL_NORMAL, "%s", header); for (i = 0; i < wcslen (wheader); i++) urj_log (URJ_LOG_LEVEL_NORMAL, "%c", '-'); urj_log (URJ_LOG_LEVEL_NORMAL, "%c", '\n'); snprintf (format, sizeof format, _(" %%c %%-%ds %%-%ds\n"), URJ_INSTRUCTION_MAXLEN_INSTRUCTION, URJ_DATA_REGISTER_MAXLEN); part = chain->parts->parts[chain->active_part]; for (inst = part->instructions; inst != NULL; inst = inst->next) { urj_log (URJ_LOG_LEVEL_NORMAL, format, (inst == part->active_instruction) ? 'X' : ' ', inst->name, inst->data_register->name); } return URJ_STATUS_OK; } } if (noheader == 0) { snprintf (format, sizeof format, _(" No. %%-%ds %%-%ds %%-%ds %%-%ds %%-%ds\n"), URJ_PART_MANUFACTURER_MAXLEN, URJ_PART_PART_MAXLEN, URJ_PART_STEPPING_MAXLEN, URJ_INSTRUCTION_MAXLEN_INSTRUCTION, URJ_DATA_REGISTER_MAXLEN); #if HAVE_SWPRINTF if (mbstowcs (wformat, format, sizeof format) == -1) // @@@@ RFHH throw urj_error? printf (_("(%d) String conversion failed!\n"), __LINE__); swprintf (wheader, sizeof format, wformat, _("Manufacturer"), _("Part"), _("Stepping"), _("Instruction"), _("Register")); if (wcstombs (header, wheader, sizeof format) == -1) // @@@@ RFHH throw urj_error? printf (_("(%d) String conversion failed!\n"), __LINE__); #else /* HAVE_SWPRINTF */ snprintf (header, sizeof format, format, _("Manufacturer"), _("Part"), _("Stepping"), _("Instruction"), _("Register")); if (mbstowcs (wheader, header, sizeof format) == -1) // @@@@ RFHH throw urj_error? printf (_("(%d) String conversion failed!\n"), __LINE__); #endif /* HAVE_SWPRINTF */ urj_log (URJ_LOG_LEVEL_NORMAL, "%s", header); for (i = 0; i < wcslen (wheader); i++) urj_log (URJ_LOG_LEVEL_NORMAL, "%c", '-'); urj_log (URJ_LOG_LEVEL_NORMAL, "%c", '\n'); } if (urj_cmd_params (params) == 1) { int r = URJ_STATUS_OK; if (chain->parts->len > chain->active_part) { if (chain->parts->parts[chain->active_part]->alias) urj_log (URJ_LOG_LEVEL_NORMAL, _(" %3d %s "), chain->active_part, chain->parts->parts[chain->active_part]->alias); else urj_log (URJ_LOG_LEVEL_NORMAL, _(" %3d "), chain->active_part); urj_part_print (URJ_LOG_LEVEL_NORMAL, chain->parts->parts[chain->active_part]); } if (urj_bus != NULL) { int i; uint64_t a; urj_bus_area_t area; for (i = 0; i < urj_buses.len; i++) if (urj_buses.buses[i] == urj_bus) break; urj_log (URJ_LOG_LEVEL_NORMAL, _("\nActive bus:\n*%d: "), i); URJ_BUS_PRINTINFO (URJ_LOG_LEVEL_NORMAL, urj_bus); for (a = 0; a < UINT64_C (0x100000000); a = area.start + area.length) { r = URJ_BUS_AREA (urj_bus, a, &area); if (r != URJ_STATUS_OK) { urj_log (URJ_LOG_LEVEL_NORMAL, _("Error in bus area discovery at 0x%08llX\n"), (long long unsigned int) a); break; } if (area.width != 0) { if (area.description != NULL) urj_log (URJ_LOG_LEVEL_NORMAL, _("\tstart: 0x%08lX, length: 0x%08llX, data width: %d bit, (%s)\n"), (long unsigned) area.start, (long long unsigned int) area.length, area.width, _(area.description)); else urj_log (URJ_LOG_LEVEL_NORMAL, _("\tstart: 0x%08lX, length: 0x%08llX, data width: %d bit\n"), (long unsigned) area.start, (long long unsigned int) area.length, area.width); } } } return r; } if (strcasecmp (params[1], "chain") == 0) { urj_part_parts_print (URJ_LOG_LEVEL_NORMAL, chain->parts); return URJ_STATUS_OK; } for (i = 0; i < urj_buses.len; i++) { if (urj_buses.buses[i] == urj_bus) urj_log (URJ_LOG_LEVEL_NORMAL, _("*%d: "), i); else urj_log (URJ_LOG_LEVEL_NORMAL, _("%d: "), i); URJ_BUS_PRINTINFO (URJ_LOG_LEVEL_NORMAL, urj_buses.buses[i]); } return URJ_STATUS_OK; }
/** @return number of flushed bytes on success; -1 on error */ static int usbconn_ftd2xx_flush (ftd2xx_param_t *p) { FT_STATUS status; DWORD xferred; DWORD recvd = 0; if (!p->fc) return -1; urj_log (URJ_LOG_LEVEL_COMM, "%sflush begin:\n", module); urj_log (URJ_LOG_LEVEL_COMM, " send_buf_len %d, send_buffered %d\n", p->send_buf_len, p->send_buffered); urj_log (URJ_LOG_LEVEL_COMM, " recv_buf_len %d, to_recv %d\n", p->recv_buf_len, p->to_recv); urj_log (URJ_LOG_LEVEL_COMM, " recv_write_idx %d, recv_read_idx %d\n", p->recv_write_idx, p->recv_read_idx); if (p->send_buffered == 0) return 0; if ((status = FT_Write (p->fc, p->send_buf, p->send_buffered, &xferred)) != FT_OK) { urj_error_set (URJ_ERROR_FTD, _("FT_Write() failed: %s"), ftd2xx_status_string(status)); return -1; } if (xferred < p->send_buffered) { urj_error_set (URJ_ERROR_ILLEGAL_STATE, _("Written fewer bytes than requested")); return -1; } p->send_buffered = 0; /* now read all scheduled receive bytes */ if (p->to_recv) { if (p->recv_write_idx + p->to_recv > p->recv_buf_len) { /* extend receive buffer */ p->recv_buf_len = p->recv_write_idx + p->to_recv; if (p->recv_buf) p->recv_buf = realloc (p->recv_buf, p->recv_buf_len); } if (!p->recv_buf) { urj_error_set (URJ_ERROR_ILLEGAL_STATE, _("Receive buffer does not exist")); return -1; } while (recvd == 0) if ((status = FT_Read (p->fc, &p->recv_buf[p->recv_write_idx], p->to_recv, &recvd)) != FT_OK) urj_error_set (URJ_ERROR_FTD, _("Error from FT_Read(): %s"), ftd2xx_status_string(status)); if (recvd < p->to_recv) urj_log (URJ_LOG_LEVEL_NORMAL, _("%s(): Received fewer bytes than requested.\n"), __func__); p->to_recv -= recvd; p->recv_write_idx += recvd; } urj_log (URJ_LOG_LEVEL_COMM, "%sflush end: status %ld, xferred %ld, recvd %ld\n", module, status, xferred, recvd); return status != FT_OK ? -1 : xferred; }
int urj_tap_chain_connect (urj_chain_t *chain, const char *drivername, char *params[]) { urj_cable_t *cable; int j, paramc; const urj_param_t **cable_params; const urj_cable_driver_t *driver; urj_cable_parport_devtype_t devtype; const char *devname; int param_start; param_start = 0; paramc = urj_cmd_params (params); driver = urj_tap_cable_find (drivername); if (!driver) { urj_error_set (URJ_ERROR_INVALID, "unknown cable driver '%s'", drivername); return URJ_STATUS_FAIL; } if (driver->device_type == URJ_CABLE_DEVICE_PARPORT) { if (paramc < 2) { urj_error_set (URJ_ERROR_SYNTAX, "parallel cable requires >= 4 parameters, got %d", paramc); return URJ_STATUS_FAIL; } for (j = 0; j < URJ_CABLE_PARPORT_N_DEVS; j++) if (strcasecmp (params[0], urj_cable_parport_devtype_string (j)) == 0) break; if (j == URJ_CABLE_PARPORT_N_DEVS) { urj_error_set (URJ_ERROR_INVALID, "unknown parallel port device type '%s'", params[0]); return URJ_STATUS_FAIL; } devtype = j; devname = params[1]; param_start = 2; } else { /* Silence gcc uninitialized warnings */ devtype = -1; devname = NULL; } if (urj_param_init_list (&cable_params, ¶ms[param_start], &urj_cable_param_list) != URJ_STATUS_OK) return URJ_STATUS_FAIL; switch (driver->device_type) { case URJ_CABLE_DEVICE_PARPORT: cable = urj_tap_cable_parport_connect (chain, driver, devtype, devname, cable_params); break; case URJ_CABLE_DEVICE_USB: cable = urj_tap_cable_usb_connect (chain, driver, cable_params); break; case URJ_CABLE_DEVICE_OTHER: cable = urj_tap_cable_other_connect (chain, driver, cable_params); break; default: cable = NULL; break; } urj_param_clear (&cable_params); if (cable == NULL) return URJ_STATUS_FAIL; chain->cable->chain = chain; return URJ_STATUS_OK; }
/** * 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; }
static int wiggler_connect (urj_cable_t *cable, urj_cable_parport_devtype_t devtype, const char *devname, const urj_param_t *params[]) { const urj_param_t *param_bitmap = NULL; const char *bitmap = NULL; wiggler_params_t *wiggler_params; if (urj_param_num (params) > 0) { /* acquire optional parameter for bit<->pin mapping */ param_bitmap = params[0]; if (params[0]->type != URJ_PARAM_TYPE_STRING) { urj_error_set (URJ_ERROR_SYNTAX, "mapping name should be a string"); return URJ_STATUS_FAIL; } /* urj_tap_cable_generic_parport_connect() shouldn't see this parameter */ params[0] = NULL; } if (urj_tap_cable_generic_parport_connect (cable, devtype, devname, params) != URJ_STATUS_OK) return URJ_STATUS_FAIL; if (param_bitmap) params[0] = param_bitmap; wiggler_params = malloc (sizeof *wiggler_params); if (!wiggler_params) { urj_error_set (URJ_ERROR_OUT_OF_MEMORY, _("malloc(%zd) fails"), sizeof *wiggler_params); /* NOTE: * Call the underlying parport driver (*free) routine directly * not generic_parconn_free() since it also free's cable->params * (which is not established) and cable (which the caller will do) */ cable->link.port->driver->parport_free (cable->link.port); return 4; } /* set new wiggler-specific params */ free (cable->params); cable->params = wiggler_params; if (!param_bitmap) bitmap = (char *) std_wgl_map; else bitmap = param_bitmap->value.string; if (set_mapping (bitmap, cable) != 0) { urj_log (URJ_LOG_LEVEL_ERROR, _("Pin mapping failed\n")); /* NOTE: * Call the underlying parport driver (*free) routine directly * not generic_parconn_free() since it also free's cable (which * the caller will do) */ cable->link.port->driver->parport_free (cable->link.port); free (cable->params); return URJ_STATUS_FAIL; } /* Certain Macraigor Wigglers appear to use one of the unused data lines as a power line so set all unused bits high. */ PRM_UNUSED_BITS (cable) = ~(PRM_SRST_ACT (cable) | PRM_SRST_INACT (cable) | PRM_TMS_ACT (cable) | PRM_TMS_INACT (cable) | PRM_TCK_ACT (cable) | PRM_TCK_INACT (cable) | PRM_TDI_ACT (cable) | PRM_TDI_INACT (cable) | PRM_TRST_ACT (cable) | PRM_TRST_INACT (cable)) & 0xff; return 0; }
int urj_tap_cable_generic_usbconn_connect (urj_cable_t *cable, const urj_param_t *params[]) { urj_usbconn_cable_t user_specified = { NULL, /* no name */ NULL, /* no string pattern */ NULL, /* no specific driver */ -1, /* no VID */ -1, /* no PID */ 0, /* default interface */ }; urj_tap_cable_generic_params_t *cable_params; urj_usbconn_t *conn = NULL; int i; if (strcasecmp (cable->driver->name, "usb") != 0) { user_specified.name = cable->driver->name; } if (params != NULL) /* parse arguments beyond the cable name */ for (i = 0; params[i] != NULL; i++) { switch (params[i]->key) { case URJ_CABLE_PARAM_KEY_PID: user_specified.pid = params[i]->value.lu; break; case URJ_CABLE_PARAM_KEY_VID: user_specified.vid = params[i]->value.lu; break; case URJ_CABLE_PARAM_KEY_DESC: user_specified.desc = params[i]->value.string; break; case URJ_CABLE_PARAM_KEY_DRIVER: user_specified.driver = params[i]->value.string; break; case URJ_CABLE_PARAM_KEY_INTERFACE: user_specified.interface = params[i]->value.lu; break; case URJ_CABLE_PARAM_KEY_INDEX: user_specified.index = params[i]->value.lu; break; default: // hand these to the driver connect() break; } } /* search usbconn driver list */ for (i = 0; urj_tap_usbconn_drivers[i] && !conn; i++) { if ((user_specified.driver == NULL) || (strcasecmp (user_specified.driver, urj_tap_usbconn_drivers[i]->type) == 0)) { int j; /* search cable list */ for (j = 0; urj_tap_cable_usbconn_cables[j] && !conn; j++) { if ((user_specified.name == NULL) || (strcasecmp (user_specified.name, urj_tap_cable_usbconn_cables[j]->name) == 0)) { if (strcasecmp (urj_tap_cable_usbconn_cables[j]->driver, urj_tap_usbconn_drivers[i]->type) == 0) { urj_usbconn_cable_t cable_try = *(urj_tap_cable_usbconn_cables[j]); if (user_specified.vid >= 0) cable_try.vid = user_specified.vid; if (user_specified.pid >= 0) cable_try.pid = user_specified.pid; if (user_specified.desc != 0) cable_try.desc = user_specified.desc; if (user_specified.interface != 0) cable_try.interface = user_specified.interface; if (user_specified.index != 0) cable_try.index = user_specified.index; conn = urj_tap_usbconn_drivers[i]->connect (&cable_try, params); } } } } } if (!conn) { // @@@@ RFHH make this into either the error from drivers->connect, // or urj_error_set (NOT_FOUND) urj_log (URJ_LOG_LEVEL_ERROR, _("Couldn't connect to suitable USB device.\n")); return URJ_STATUS_FAIL; } else { /* If some cables have been tried before a suitable cable is found, urj_error will still contain an error from the last fail trial. Clear it to avoid confusing error reporting. */ urj_error_reset (); } cable_params = malloc (sizeof (urj_tap_cable_generic_params_t)); if (!cable_params) { urj_error_set (URJ_ERROR_OUT_OF_MEMORY, _("malloc(%zd) fails"), sizeof (urj_tap_cable_generic_params_t)); urj_tap_usbconn_drivers[i]->free (conn); return URJ_STATUS_FAIL; } cable->link.usb = conn; cable->params = cable_params; cable->chain = NULL; return URJ_STATUS_OK; }
int urj_part_bsbit_alloc_control (urj_part_t *part, int bit, const char *name, int type, int safe, int ctrl_num, int ctrl_val, int ctrl_state) { urj_bsbit_t *b; urj_data_register_t *bsr; urj_part_signal_t *signal; bsr = urj_part_find_data_register (part, "BSR"); if (bsr == NULL) { urj_error_set(URJ_ERROR_NOTFOUND, _("missing Boundary Scan Register (BSR)")); return URJ_STATUS_FAIL; } if (bit >= bsr->in->len) { urj_error_set(URJ_ERROR_INVALID, _("invalid boundary bit number")); return URJ_STATUS_FAIL; } if (part->bsbits[bit] != NULL) { urj_error_set(URJ_ERROR_ALREADY, _("duplicate bit declaration")); return URJ_STATUS_FAIL; } if (ctrl_num != -1 && ctrl_num >= bsr->in->len) { urj_error_set(URJ_ERROR_INVALID, _("invalid control bit number")); return URJ_STATUS_FAIL; } signal = urj_part_find_signal (part, name); bsr->in->data[bit] = safe; b = malloc (sizeof *b); if (!b) { urj_error_set (URJ_ERROR_OUT_OF_MEMORY, "malloc(%zd) fails", sizeof *b); return URJ_STATUS_FAIL; } b->name = strdup (name); if (!b->name) { free (b); urj_error_set (URJ_ERROR_OUT_OF_MEMORY, "strdup(%s) fails", name); return URJ_STATUS_FAIL; } b->bit = bit; b->type = type; b->signal = signal; b->safe = (safe == 1); b->control = -1; part->bsbits[bit] = b; if (signal != NULL) { switch (type) { case URJ_BSBIT_INPUT: signal->input = b; break; case URJ_BSBIT_OUTPUT: signal->output = b; break; case URJ_BSBIT_BIDIR: signal->input = b; signal->output = b; break; } } if (ctrl_num != -1) { b->control = ctrl_num; b->control_value = ctrl_val; b->control_state = ctrl_state; } 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); }
/** * bus->driver->(*new_bus) * */ static urj_bus_t * avr32_bus_new (urj_chain_t *chain, const urj_bus_driver_t *driver, const urj_param_t *cmd_params[]) { urj_bus_t *bus; urj_part_t *part; unsigned int mode = BUS_MODE_ERROR; if (cmd_params[0] == NULL) { urj_error_set (URJ_ERROR_SYNTAX, "no bus mode specified"); return NULL; } if (cmd_params[1] != NULL) { urj_error_set (URJ_ERROR_SYNTAX, "invalid bus parameter: %s", urj_param_string(&urj_bus_param_list, cmd_params[1])); return NULL; } bus = urj_bus_generic_new (chain, driver, sizeof (bus_params_t)); if (bus == NULL) return NULL; part = bus->part; switch (cmd_params[0]->key) { case URJ_BUS_PARAM_KEY_OCD: mode = BUS_MODE_OCD; break; case URJ_BUS_PARAM_KEY_HSBC: mode = BUS_MODE_HSBC; break; case URJ_BUS_PARAM_KEY_HSBU: mode = BUS_MODE_HSBU; break; case URJ_BUS_PARAM_KEY_X8: // see also: width=8 mode = BUS_MODE_x8; break; case URJ_BUS_PARAM_KEY_X16: // see also: width=16 mode = BUS_MODE_x16; break; case URJ_BUS_PARAM_KEY_X32: // see also: width=32 mode = BUS_MODE_x32; break; // RFHH introduced 'width=8|16|32' as an alias for x8, x16, x32 case URJ_BUS_PARAM_KEY_WIDTH: switch (cmd_params[0]->value.lu) { case 8: mode = BUS_MODE_x8; break; case 16: mode = BUS_MODE_x16; break; case 32: mode = BUS_MODE_x32; break; default: urj_bus_generic_free (bus); urj_error_set (URJ_ERROR_SYNTAX, "invalid bus width: %lu", cmd_params[0]->value.lu); return NULL; } break; default: urj_bus_generic_free (bus); urj_error_set (URJ_ERROR_SYNTAX, "invalid bus mode: %s", urj_param_string(&urj_bus_param_list, cmd_params[0])); return NULL; } switch (mode) { case BUS_MODE_OCD: case BUS_MODE_HSBC: case BUS_MODE_HSBU: if (check_instruction (part, "MEMORY_WORD_ACCESS")) { urj_bus_generic_free (bus); return NULL; } break; case BUS_MODE_x8: case BUS_MODE_x16: case BUS_MODE_x32: if (check_instruction (part, "NEXUS_ACCESS")) { urj_bus_generic_free (bus); return NULL; } break; default: urj_error_set (URJ_ERROR_INVALID, "need bus mode parameter"); urj_bus_generic_free (bus); return NULL; } avr32_bus_setup (bus, chain, part, mode); return bus; }
int urj_tap_chain_shift_data_registers_mode (urj_chain_t *chain, int capture_output, int capture, int chain_exit) { int i; urj_parts_t *ps; if (!chain || !chain->parts) { urj_error_set (URJ_ERROR_NO_CHAIN, "no chain or no part"); return URJ_STATUS_FAIL; } ps = chain->parts; for (i = 0; i < ps->len; i++) { if (ps->parts[i]->active_instruction == NULL) { urj_error_set (URJ_ERROR_NO_ACTIVE_INSTRUCTION, _("Part %d without active instruction"), i); return URJ_STATUS_FAIL; } if (ps->parts[i]->active_instruction->data_register == NULL) { urj_error_set (URJ_ERROR_NO_DATA_REGISTER, _("Part %d without data register"), i); return URJ_STATUS_FAIL; } } if (capture) urj_tap_capture_dr (chain); /* new implementation: split into defer + retrieve part shift the data register of each part in the chain one by one */ for (i = 0; i < ps->len; i++) { urj_tap_defer_shift_register (chain, ps->parts[i]->active_instruction->data_register->in, capture_output ? ps->parts[i]->active_instruction->data_register->out : NULL, (i + 1) == ps->len ? chain_exit : URJ_CHAIN_EXITMODE_SHIFT); } if (capture_output) { for (i = 0; i < ps->len; i++) { urj_tap_shift_register_output (chain, ps->parts[i]->active_instruction->data_register->in, ps->parts[i]->active_instruction->data_register->out, (i + 1) == ps->len ? chain_exit : URJ_CHAIN_EXITMODE_SHIFT); } } else { /* give the cable driver a chance to flush if it's considered useful */ urj_tap_cable_flush (chain->cable, URJ_TAP_CABLE_TO_OUTPUT); } return URJ_STATUS_OK; }
/** * 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_set_run (urj_chain_t *chain, char *params[]) { int dir; long unsigned data = 0; urj_part_signal_t *s; urj_part_t *part; if (urj_cmd_params (params) < 4 || urj_cmd_params (params) > 5) { urj_error_set (URJ_ERROR_SYNTAX, "%s: #parameters should be 4 or 5, not %d", params[0], urj_cmd_params (params)); return URJ_STATUS_FAIL; } if (strcasecmp (params[1], "signal") != 0) { urj_error_set (URJ_ERROR_SYNTAX, "%s: second parameter must be '%s'", params[0], params[1]); 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; /* direction */ if (strcasecmp (params[3], "in") != 0 && strcasecmp (params[3], "out") != 0) { urj_error_set (URJ_ERROR_SYNTAX, "%s: DIR parameter must be 'in' or 'out', not '%s'", params[0], params[3]); return URJ_STATUS_FAIL; } dir = (strcasecmp (params[3], "in") == 0) ? 0 : 1; if (dir) { if (urj_cmd_get_number (params[4], &data) != URJ_STATUS_OK) return URJ_STATUS_FAIL; if (data > 1) { urj_error_set (URJ_ERROR_SYNTAX, "%s: DATA parameter must be '0' or '1', not '%s'", params[0], params[4]); return URJ_STATUS_FAIL; } } s = urj_part_find_signal (part, params[2]); if (!s) { urj_error_set (URJ_ERROR_NOTFOUND, _("signal '%s' not found"), params[2]); return URJ_STATUS_FAIL; } return urj_part_set_signal (part, s, dir, data); }