Esempio n. 1
0
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;
}
Esempio n. 2
0
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;
}
Esempio n. 3
0
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;
}
Esempio n. 4
0
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;
}
Esempio n. 5
0
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;
}
Esempio n. 6
0
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;
                }
            }
        }
Esempio n. 7
0
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;
}
Esempio n. 8
0
/**
 * 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;

    }
Esempio n. 9
0
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;
}
Esempio n. 10
0
/** @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;
}
Esempio n. 11
0
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, &params[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;
}
Esempio n. 12
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)
Esempio n. 13
0
/**
 * 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;
}
Esempio n. 14
0
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;
}
Esempio n. 15
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;
}
Esempio n. 16
0
File: bsbit.c Progetto: bgelb/urjtag
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;
}
Esempio n. 17
0
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);
    }
Esempio n. 18
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;
}
Esempio n. 19
0
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;
}
Esempio n. 20
0
/**
 * 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;
}
Esempio n. 21
0
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);
}