From cff4fa8415a3224a5abdd2b1dd7f431e4ea49366 Mon Sep 17 00:00:00 2001 From: "Igor M. Liplianin" Date: Fri, 23 Sep 2011 11:17:41 -0300 Subject: [media] altera-stapl: it is time to move out from staging [mchehab@redhat.com: Fix a merge conflict] Signed-off-by: Igor M. Liplianin Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx23885/cx23885-cards.c | 2 +- drivers/misc/Kconfig | 1 + drivers/misc/Makefile | 1 + drivers/misc/altera-stapl/Kconfig | 8 + drivers/misc/altera-stapl/Makefile | 3 + drivers/misc/altera-stapl/altera-comp.c | 142 ++ drivers/misc/altera-stapl/altera-exprt.h | 33 + drivers/misc/altera-stapl/altera-jtag.c | 1021 +++++++++++ drivers/misc/altera-stapl/altera-jtag.h | 113 ++ drivers/misc/altera-stapl/altera-lpt.c | 70 + drivers/misc/altera-stapl/altera.c | 2536 +++++++++++++++++++++++++++ drivers/staging/Kconfig | 2 - drivers/staging/Makefile | 1 - drivers/staging/altera-stapl/Kconfig | 6 - drivers/staging/altera-stapl/Makefile | 3 - drivers/staging/altera-stapl/altera-comp.c | 142 -- drivers/staging/altera-stapl/altera-exprt.h | 33 - drivers/staging/altera-stapl/altera-jtag.c | 1021 ----------- drivers/staging/altera-stapl/altera-jtag.h | 113 -- drivers/staging/altera-stapl/altera-lpt.c | 70 - drivers/staging/altera-stapl/altera.c | 2536 --------------------------- drivers/staging/altera-stapl/altera.h | 49 - include/misc/altera.h | 49 + 23 files changed, 3978 insertions(+), 3977 deletions(-) create mode 100644 drivers/misc/altera-stapl/Kconfig create mode 100644 drivers/misc/altera-stapl/Makefile create mode 100644 drivers/misc/altera-stapl/altera-comp.c create mode 100644 drivers/misc/altera-stapl/altera-exprt.h create mode 100644 drivers/misc/altera-stapl/altera-jtag.c create mode 100644 drivers/misc/altera-stapl/altera-jtag.h create mode 100644 drivers/misc/altera-stapl/altera-lpt.c create mode 100644 drivers/misc/altera-stapl/altera.c delete mode 100644 drivers/staging/altera-stapl/Kconfig delete mode 100644 drivers/staging/altera-stapl/Makefile delete mode 100644 drivers/staging/altera-stapl/altera-comp.c delete mode 100644 drivers/staging/altera-stapl/altera-exprt.h delete mode 100644 drivers/staging/altera-stapl/altera-jtag.c delete mode 100644 drivers/staging/altera-stapl/altera-jtag.h delete mode 100644 drivers/staging/altera-stapl/altera-lpt.c delete mode 100644 drivers/staging/altera-stapl/altera.c delete mode 100644 drivers/staging/altera-stapl/altera.h create mode 100644 include/misc/altera.h diff --git a/drivers/media/video/cx23885/cx23885-cards.c b/drivers/media/video/cx23885/cx23885-cards.c index 76b7563de39..62fd25e7633 100644 --- a/drivers/media/video/cx23885/cx23885-cards.c +++ b/drivers/media/video/cx23885/cx23885-cards.c @@ -25,8 +25,8 @@ #include #include #include +#include -#include "../../../staging/altera-stapl/altera.h" #include "cx23885.h" #include "tuner-xc2028.h" #include "netup-eeprom.h" diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index 2d6423c2d19..50d5f27f09d 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -506,5 +506,6 @@ source "drivers/misc/iwmc3200top/Kconfig" source "drivers/misc/ti-st/Kconfig" source "drivers/misc/lis3lv02d/Kconfig" source "drivers/misc/carma/Kconfig" +source "drivers/misc/altera-stapl/Kconfig" endif # MISC_DEVICES diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index 8f3efb68a14..b26495a0255 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile @@ -47,3 +47,4 @@ obj-$(CONFIG_AB8500_PWM) += ab8500-pwm.o obj-y += lis3lv02d/ obj-y += carma/ obj-$(CONFIG_USB_SWITCH_FSA9480) += fsa9480.o +obj-$(CONFIG_ALTERA_STAPL) +=altera-stapl/ diff --git a/drivers/misc/altera-stapl/Kconfig b/drivers/misc/altera-stapl/Kconfig new file mode 100644 index 00000000000..7f01d8e9399 --- /dev/null +++ b/drivers/misc/altera-stapl/Kconfig @@ -0,0 +1,8 @@ +comment "Altera FPGA firmware download module" + +config ALTERA_STAPL + tristate "Altera FPGA firmware download module" + depends on I2C + default n + help + An Altera FPGA module. Say Y when you want to support this tool. diff --git a/drivers/misc/altera-stapl/Makefile b/drivers/misc/altera-stapl/Makefile new file mode 100644 index 00000000000..055f61ee781 --- /dev/null +++ b/drivers/misc/altera-stapl/Makefile @@ -0,0 +1,3 @@ +altera-stapl-objs = altera-lpt.o altera-jtag.o altera-comp.o altera.o + +obj-$(CONFIG_ALTERA_STAPL) += altera-stapl.o diff --git a/drivers/misc/altera-stapl/altera-comp.c b/drivers/misc/altera-stapl/altera-comp.c new file mode 100644 index 00000000000..49b103bedaa --- /dev/null +++ b/drivers/misc/altera-stapl/altera-comp.c @@ -0,0 +1,142 @@ +/* + * altera-comp.c + * + * altera FPGA driver + * + * Copyright (C) Altera Corporation 1998-2001 + * Copyright (C) 2010 NetUP Inc. + * Copyright (C) 2010 Igor M. Liplianin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include "altera-exprt.h" + +#define SHORT_BITS 16 +#define CHAR_BITS 8 +#define DATA_BLOB_LENGTH 3 +#define MATCH_DATA_LENGTH 8192 +#define ALTERA_REQUEST_SIZE 1024 +#define ALTERA_BUFFER_SIZE (MATCH_DATA_LENGTH + ALTERA_REQUEST_SIZE) + +static u32 altera_bits_req(u32 n) +{ + u32 result = SHORT_BITS; + + if (n == 0) + result = 1; + else { + /* Look for the highest non-zero bit position */ + while ((n & (1 << (SHORT_BITS - 1))) == 0) { + n <<= 1; + --result; + } + } + + return result; +} + +static u32 altera_read_packed(u8 *buffer, u32 bits, u32 *bits_avail, + u32 *in_index) +{ + u32 result = 0; + u32 shift = 0; + u32 databyte = 0; + + while (bits > 0) { + databyte = buffer[*in_index]; + result |= (((databyte >> (CHAR_BITS - *bits_avail)) + & (0xff >> (CHAR_BITS - *bits_avail))) << shift); + + if (bits <= *bits_avail) { + result &= (0xffff >> (SHORT_BITS - (bits + shift))); + *bits_avail -= bits; + bits = 0; + } else { + ++(*in_index); + shift += *bits_avail; + bits -= *bits_avail; + *bits_avail = CHAR_BITS; + } + } + + return result; +} + +u32 altera_shrink(u8 *in, u32 in_length, u8 *out, u32 out_length, s32 version) +{ + u32 i, j, data_length = 0L; + u32 offset, length; + u32 match_data_length = MATCH_DATA_LENGTH; + u32 bits_avail = CHAR_BITS; + u32 in_index = 0L; + + if (version > 0) + --match_data_length; + + for (i = 0; i < out_length; ++i) + out[i] = 0; + + /* Read number of bytes in data. */ + for (i = 0; i < sizeof(in_length); ++i) { + data_length = data_length | ( + altera_read_packed(in, + CHAR_BITS, + &bits_avail, + &in_index) << (i * CHAR_BITS)); + } + + if (data_length > out_length) { + data_length = 0L; + return data_length; + } + + i = 0; + while (i < data_length) { + /* A 0 bit indicates literal data. */ + if (altera_read_packed(in, 1, &bits_avail, + &in_index) == 0) { + for (j = 0; j < DATA_BLOB_LENGTH; ++j) { + if (i < data_length) { + out[i] = (u8)altera_read_packed(in, + CHAR_BITS, + &bits_avail, + &in_index); + i++; + } + } + } else { + /* A 1 bit indicates offset/length to follow. */ + offset = altera_read_packed(in, altera_bits_req((s16) + (i > match_data_length ? + match_data_length : i)), + &bits_avail, + &in_index); + length = altera_read_packed(in, CHAR_BITS, + &bits_avail, + &in_index); + for (j = 0; j < length; ++j) { + if (i < data_length) { + out[i] = out[i - offset]; + i++; + } + } + } + } + + return data_length; +} diff --git a/drivers/misc/altera-stapl/altera-exprt.h b/drivers/misc/altera-stapl/altera-exprt.h new file mode 100644 index 00000000000..39c38d84a67 --- /dev/null +++ b/drivers/misc/altera-stapl/altera-exprt.h @@ -0,0 +1,33 @@ +/* + * altera-exprt.h + * + * altera FPGA driver + * + * Copyright (C) Altera Corporation 1998-2001 + * Copyright (C) 2010 NetUP Inc. + * Copyright (C) 2010 Igor M. Liplianin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef ALTERA_EXPRT_H +#define ALTERA_EXPRT_H + + +u32 altera_shrink(u8 *in, u32 in_length, u8 *out, u32 out_length, s32 version); +int netup_jtag_io_lpt(void *device, int tms, int tdi, int read_tdo); + +#endif /* ALTERA_EXPRT_H */ diff --git a/drivers/misc/altera-stapl/altera-jtag.c b/drivers/misc/altera-stapl/altera-jtag.c new file mode 100644 index 00000000000..f4bf2009697 --- /dev/null +++ b/drivers/misc/altera-stapl/altera-jtag.c @@ -0,0 +1,1021 @@ +/* + * altera-jtag.c + * + * altera FPGA driver + * + * Copyright (C) Altera Corporation 1998-2001 + * Copyright (C) 2010 NetUP Inc. + * Copyright (C) 2010 Igor M. Liplianin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include "altera-exprt.h" +#include "altera-jtag.h" + +#define alt_jtag_io(a, b, c)\ + astate->config->jtag_io(astate->config->dev, a, b, c); + +#define alt_malloc(a) kzalloc(a, GFP_KERNEL); + +/* + * This structure shows, for each JTAG state, which state is reached after + * a single TCK clock cycle with TMS high or TMS low, respectively. This + * describes all possible state transitions in the JTAG state machine. + */ +struct altera_jtag_machine { + enum altera_jtag_state tms_high; + enum altera_jtag_state tms_low; +}; + +static const struct altera_jtag_machine altera_transitions[] = { + /* RESET */ { RESET, IDLE }, + /* IDLE */ { DRSELECT, IDLE }, + /* DRSELECT */ { IRSELECT, DRCAPTURE }, + /* DRCAPTURE */ { DREXIT1, DRSHIFT }, + /* DRSHIFT */ { DREXIT1, DRSHIFT }, + /* DREXIT1 */ { DRUPDATE, DRPAUSE }, + /* DRPAUSE */ { DREXIT2, DRPAUSE }, + /* DREXIT2 */ { DRUPDATE, DRSHIFT }, + /* DRUPDATE */ { DRSELECT, IDLE }, + /* IRSELECT */ { RESET, IRCAPTURE }, + /* IRCAPTURE */ { IREXIT1, IRSHIFT }, + /* IRSHIFT */ { IREXIT1, IRSHIFT }, + /* IREXIT1 */ { IRUPDATE, IRPAUSE }, + /* IRPAUSE */ { IREXIT2, IRPAUSE }, + /* IREXIT2 */ { IRUPDATE, IRSHIFT }, + /* IRUPDATE */ { DRSELECT, IDLE } +}; + +/* + * This table contains the TMS value to be used to take the NEXT STEP on + * the path to the desired state. The array index is the current state, + * and the bit position is the desired endstate. To find out which state + * is used as the intermediate state, look up the TMS value in the + * altera_transitions[] table. + */ +static const u16 altera_jtag_path_map[16] = { + /* RST RTI SDRS CDR SDR E1DR PDR E2DR */ + 0x0001, 0xFFFD, 0xFE01, 0xFFE7, 0xFFEF, 0xFF0F, 0xFFBF, 0xFFFF, + /* UDR SIRS CIR SIR E1IR PIR E2IR UIR */ + 0xFEFD, 0x0001, 0xF3FF, 0xF7FF, 0x87FF, 0xDFFF, 0xFFFF, 0x7FFD +}; + +/* Flag bits for alt_jtag_io() function */ +#define TMS_HIGH 1 +#define TMS_LOW 0 +#define TDI_HIGH 1 +#define TDI_LOW 0 +#define READ_TDO 1 +#define IGNORE_TDO 0 + +int altera_jinit(struct altera_state *astate) +{ + struct altera_jtag *js = &astate->js; + + /* initial JTAG state is unknown */ + js->jtag_state = ILLEGAL_JTAG_STATE; + + /* initialize to default state */ + js->drstop_state = IDLE; + js->irstop_state = IDLE; + js->dr_pre = 0; + js->dr_post = 0; + js->ir_pre = 0; + js->ir_post = 0; + js->dr_length = 0; + js->ir_length = 0; + + js->dr_pre_data = NULL; + js->dr_post_data = NULL; + js->ir_pre_data = NULL; + js->ir_post_data = NULL; + js->dr_buffer = NULL; + js->ir_buffer = NULL; + + return 0; +} + +int altera_set_drstop(struct altera_jtag *js, enum altera_jtag_state state) +{ + js->drstop_state = state; + + return 0; +} + +int altera_set_irstop(struct altera_jtag *js, enum altera_jtag_state state) +{ + js->irstop_state = state; + + return 0; +} + +int altera_set_dr_pre(struct altera_jtag *js, + u32 count, u32 start_index, + u8 *preamble_data) +{ + int status = 0; + u32 i; + u32 j; + + if (count > js->dr_pre) { + kfree(js->dr_pre_data); + js->dr_pre_data = (u8 *)alt_malloc((count + 7) >> 3); + if (js->dr_pre_data == NULL) + status = -ENOMEM; + else + js->dr_pre = count; + } else + js->dr_pre = count; + + if (status == 0) { + for (i = 0; i < count; ++i) { + j = i + start_index; + + if (preamble_data == NULL) + js->dr_pre_data[i >> 3] |= (1 << (i & 7)); + else { + if (preamble_data[j >> 3] & (1 << (j & 7))) + js->dr_pre_data[i >> 3] |= + (1 << (i & 7)); + else + js->dr_pre_data[i >> 3] &= + ~(u32)(1 << (i & 7)); + + } + } + } + + return status; +} + +int altera_set_ir_pre(struct altera_jtag *js, u32 count, u32 start_index, + u8 *preamble_data) +{ + int status = 0; + u32 i; + u32 j; + + if (count > js->ir_pre) { + kfree(js->ir_pre_data); + js->ir_pre_data = (u8 *)alt_malloc((count + 7) >> 3); + if (js->ir_pre_data == NULL) + status = -ENOMEM; + else + js->ir_pre = count; + + } else + js->ir_pre = count; + + if (status == 0) { + for (i = 0; i < count; ++i) { + j = i + start_index; + if (preamble_data == NULL) + js->ir_pre_data[i >> 3] |= (1 << (i & 7)); + else { + if (preamble_data[j >> 3] & (1 << (j & 7))) + js->ir_pre_data[i >> 3] |= + (1 << (i & 7)); + else + js->ir_pre_data[i >> 3] &= + ~(u32)(1 << (i & 7)); + + } + } + } + + return status; +} + +int altera_set_dr_post(struct altera_jtag *js, u32 count, u32 start_index, + u8 *postamble_data) +{ + int status = 0; + u32 i; + u32 j; + + if (count > js->dr_post) { + kfree(js->dr_post_data); + js->dr_post_data = (u8 *)alt_malloc((count + 7) >> 3); + + if (js->dr_post_data == NULL) + status = -ENOMEM; + else + js->dr_post = count; + + } else + js->dr_post = count; + + if (status == 0) { + for (i = 0; i < count; ++i) { + j = i + start_index; + + if (postamble_data == NULL) + js->dr_post_data[i >> 3] |= (1 << (i & 7)); + else { + if (postamble_data[j >> 3] & (1 << (j & 7))) + js->dr_post_data[i >> 3] |= + (1 << (i & 7)); + else + js->dr_post_data[i >> 3] &= + ~(u32)(1 << (i & 7)); + + } + } + } + + return status; +} + +int altera_set_ir_post(struct altera_jtag *js, u32 count, u32 start_index, + u8 *postamble_data) +{ + int status = 0; + u32 i; + u32 j; + + if (count > js->ir_post) { + kfree(js->ir_post_data); + js->ir_post_data = (u8 *)alt_malloc((count + 7) >> 3); + if (js->ir_post_data == NULL) + status = -ENOMEM; + else + js->ir_post = count; + + } else + js->ir_post = count; + + if (status != 0) + return status; + + for (i = 0; i < count; ++i) { + j = i + start_index; + + if (postamble_data == NULL) + js->ir_post_data[i >> 3] |= (1 << (i & 7)); + else { + if (postamble_data[j >> 3] & (1 << (j & 7))) + js->ir_post_data[i >> 3] |= (1 << (i & 7)); + else + js->ir_post_data[i >> 3] &= + ~(u32)(1 << (i & 7)); + + } + } + + return status; +} + +static void altera_jreset_idle(struct altera_state *astate) +{ + struct altera_jtag *js = &astate->js; + int i; + /* Go to Test Logic Reset (no matter what the starting state may be) */ + for (i = 0; i < 5; ++i) + alt_jtag_io(TMS_HIGH, TDI_LOW, IGNORE_TDO); + + /* Now step to Run Test / Idle */ + alt_jtag_io(TMS_LOW, TDI_LOW, IGNORE_TDO); + js->jtag_state = IDLE; +} + +int altera_goto_jstate(struct altera_state *astate, + enum altera_jtag_state state) +{ + struct altera_jtag *js = &astate->js; + int tms; + int count = 0; + int status = 0; + + if (js->jtag_state == ILLEGAL_JTAG_STATE) + /* initialize JTAG chain to known state */ + altera_jreset_idle(astate); + + if (js->jtag_state == state) { + /* + * We are already in the desired state. + * If it is a stable state, loop here. + * Otherwise do nothing (no clock cycles). + */ + if ((state == IDLE) || (state == DRSHIFT) || + (state == DRPAUSE) || (state == IRSHIFT) || + (state == IRPAUSE)) { + alt_jtag_io(TMS_LOW, TDI_LOW, IGNORE_TDO); + } else if (state == RESET) + alt_jtag_io(TMS_HIGH, TDI_LOW, IGNORE_TDO); + + } else { + while ((js->jtag_state != state) && (count < 9)) { + /* Get TMS value to take a step toward desired state */ + tms = (altera_jtag_path_map[js->jtag_state] & + (1 << state)) + ? TMS_HIGH : TMS_LOW; + + /* Take a step */ + alt_jtag_io(tms, TDI_LOW, IGNORE_TDO); + + if (tms) + js->jtag_state = + altera_transitions[js->jtag_state].tms_high; + else + js->jtag_state = + altera_transitions[js->jtag_state].tms_low; + + ++count; + } + } + + if (js->jtag_state != state) + status = -EREMOTEIO; + + return status; +} + +int altera_wait_cycles(struct altera_state *astate, + s32 cycles, + enum altera_jtag_state wait_state) +{ + struct altera_jtag *js = &astate->js; + int tms; + s32 count; + int status = 0; + + if (js->jtag_state != wait_state) + status = altera_goto_jstate(astate, wait_state); + + if (status == 0) { + /* + * Set TMS high to loop in RESET state + * Set TMS low to loop in any other stable state + */ + tms = (wait_state == RESET) ? TMS_HIGH : TMS_LOW; + + for (count = 0L; count < cycles; count++) + alt_jtag_io(tms, TDI_LOW, IGNORE_TDO); + + } + + return status; +} + +int altera_wait_msecs(struct altera_state *astate, + s32 microseconds, enum altera_jtag_state wait_state) +/* + * Causes JTAG hardware to sit in the specified stable + * state for the specified duration of real time. If + * no JTAG operations have been performed yet, then only + * a delay is performed. This permits the WAIT USECS + * statement to be used in VECTOR programs without causing + * any JTAG operations. + * Returns 0 for success, else appropriate error code. + */ +{ + struct altera_jtag *js = &astate->js; + int status = 0; + + if ((js->jtag_state != ILLEGAL_JTAG_STATE) && + (js->jtag_state != wait_state)) + status = altera_goto_jstate(astate, wait_state); + + if (status == 0) + /* Wait for specified time interval */ + udelay(microseconds); + + return status; +} + +static void altera_concatenate_data(u8 *buffer, + u8 *preamble_data, + u32 preamble_count, + u8 *target_data, + u32 start_index, + u32 target_count, + u8 *postamble_data, + u32 postamble_count) +/* + * Copies preamble data, target data, and postamble data + * into one buffer for IR or DR scans. + */ +{ + u32 i, j, k; + + for (i = 0L; i < preamble_count; ++i) { + if (preamble_data[i >> 3L] & (1L << (i & 7L))) + buffer[i >> 3L] |= (1L << (i & 7L)); + else + buffer[i >> 3L] &= ~(u32)(1L << (i & 7L)); + + } + + j = start_index; + k = preamble_count + target_count; + for (; i < k; ++i, ++j) { + if (target_data[j >> 3L] & (1L << (j & 7L))) + buffer[i >> 3L] |= (1L << (i & 7L)); + else + buffer[i >> 3L] &= ~(u32)(1L << (i & 7L)); + + } + + j = 0L; + k = preamble_count + target_count + postamble_count; + for (; i < k; ++i, ++j) { + if (postamble_data[j >> 3L] & (1L << (j & 7L))) + buffer[i >> 3L] |= (1L << (i & 7L)); + else + buffer[i >> 3L] &= ~(u32)(1L << (i & 7L)); + + } +} + +static int alt_jtag_drscan(struct altera_state *astate, + int start_state, + int count, + u8 *tdi, + u8 *tdo) +{ + int i = 0; + int tdo_bit = 0; + int status = 1; + + /* First go to DRSHIFT state */ + switch (start_state) { + case 0: /* IDLE */ + alt_jtag_io(1, 0, 0); /* DRSELECT */ + alt_jtag_io(0, 0, 0); /* DRCAPTURE */ + alt_jtag_io(0, 0, 0); /* DRSHIFT */ + break; + + case 1: /* DRPAUSE */ + alt_jtag_io(1, 0, 0); /* DREXIT2 */ + alt_jtag_io(1, 0, 0); /* DRUPDATE */ + alt_jtag_io(1, 0, 0); /* DRSELECT */ + alt_jtag_io(0, 0, 0); /* DRCAPTURE */ + alt_jtag_io(0, 0, 0); /* DRSHIFT */ + break; + + case 2: /* IRPAUSE */ + alt_jtag_io(1, 0, 0); /* IREXIT2 */ + alt_jtag_io(1, 0, 0); /* IRUPDATE */ + alt_jtag_io(1, 0, 0); /* DRSELECT */ + alt_jtag_io(0, 0, 0); /* DRCAPTURE */ + alt_jtag_io(0, 0, 0); /* DRSHIFT */ + break; + + default: + status = 0; + } + + if (status) { + /* loop in the SHIFT-DR state */ + for (i = 0; i < count; i++) { + tdo_bit = alt_jtag_io( + (i == count - 1), + tdi[i >> 3] & (1 << (i & 7)), + (tdo != NULL)); + + if (tdo != NULL) { + if (tdo_bit) + tdo[i >> 3] |= (1 << (i & 7)); + else + tdo[i >> 3] &= ~(u32)(1 << (i & 7)); + + } + } + + alt_jtag_io(0, 0, 0); /* DRPAUSE */ + } + + return status; +} + +static int alt_jtag_irscan(struct altera_state *astate, + int start_state, + int count, + u8 *tdi, + u8 *tdo) +{ + int i = 0; + int tdo_bit = 0; + int status = 1; + + /* First go to IRSHIFT state */ + switch (start_state) { + case 0: /* IDLE */ + alt_jtag_io(1, 0, 0); /* DRSELECT */ + alt_jtag_io(1, 0, 0); /* IRSELECT */ + alt_jtag_io(0, 0, 0); /* IRCAPTURE */ + alt_jtag_io(0, 0, 0); /* IRSHIFT */ + break; + + case 1: /* DRPAUSE */ + alt_jtag_io(1, 0, 0); /* DREXIT2 */ + alt_jtag_io(1, 0, 0); /* DRUPDATE */ + alt_jtag_io(1, 0, 0); /* DRSELECT */ + alt_jtag_io(1, 0, 0); /* IRSELECT */ + alt_jtag_io(0, 0, 0); /* IRCAPTURE */ + alt_jtag_io(0, 0, 0); /* IRSHIFT */ + break; + + case 2: /* IRPAUSE */ + alt_jtag_io(1, 0, 0); /* IREXIT2 */ + alt_jtag_io(1, 0, 0); /* IRUPDATE */ + alt_jtag_io(1, 0, 0); /* DRSELECT */ + alt_jtag_io(1, 0, 0); /* IRSELECT */ + alt_jtag_io(0, 0, 0); /* IRCAPTURE */ + alt_jtag_io(0, 0, 0); /* IRSHIFT */ + break; + + default: + status = 0; + } + + if (status) { + /* loop in the SHIFT-IR state */ + for (i = 0; i < count; i++) { + tdo_bit = alt_jtag_io( + (i == count - 1), + tdi[i >> 3] & (1 << (i & 7)), + (tdo != NULL)); + if (tdo != NULL) { + if (tdo_bit) + tdo[i >> 3] |= (1 << (i & 7)); + else + tdo[i >> 3] &= ~(u32)(1 << (i & 7)); + + } + } + + alt_jtag_io(0, 0, 0); /* IRPAUSE */ + } + + return status; +} + +static void altera_extract_target_data(u8 *buffer, + u8 *target_data, + u32 start_index, + u32 preamble_count, + u32 target_count) +/* + * Copies target data from scan buffer, filtering out + * preamble and postamble data. + */ +{ + u32 i; + u32 j; + u32 k; + + j = preamble_count; + k = start_index + target_count; + for (i = start_index; i < k; ++i, ++j) { + if (buffer[j >> 3] & (1 << (j & 7))) + target_data[i >> 3] |= (1 << (i & 7)); + else + target_data[i >> 3] &= ~(u32)(1 << (i & 7)); + + } +} + +int altera_irscan(struct altera_state *astate, + u32 count, + u8 *tdi_data, + u32 start_index) +/* Shifts data into instruction register */ +{ + struct altera_jtag *js = &astate->js; + int start_code = 0; + u32 alloc_chars = 0; + u32 shift_count = js->ir_pre + count + js->ir_post; + int status = 0; + enum altera_jtag_state start_state = ILLEGAL_JTAG_STATE; + + switch (js->jtag_state) { + case ILLEGAL_JTAG_STATE: + case RESET: + case IDLE: + start_code = 0; + start_state = IDLE; + break; + + case DRSELECT: + case DRCAPTURE: + case DRSHIFT: + case DREXIT1: + case DRPAUSE: + case DREXIT2: + case DRUPDATE: + start_code = 1; + start_state = DRPAUSE; + break; + + case IRSELECT: + case IRCAPTURE: + case IRSHIFT: + case IREXIT1: + case IRPAUSE: + case IREXIT2: + case IRUPDATE: + start_code = 2; + start_state = IRPAUSE; + break; + + default: + status = -EREMOTEIO; + break; + } + + if (status == 0) + if (js->jtag_state != start_state) + status = altera_goto_jstate(astate, start_state); + + if (status == 0) { + if (shift_count > js->ir_length) { + alloc_chars = (shift_count + 7) >> 3; + kfree(js->ir_buffer); + js->ir_buffer = (u8 *)alt_malloc(alloc_chars); + if (js->ir_buffer == NULL) + status = -ENOMEM; + else + js->ir_length = alloc_chars * 8; + + } + } + + if (status == 0) { + /* + * Copy preamble data, IR data, + * and postamble data into a buffer + */ + altera_concatenate_data(js->ir_buffer, + js->ir_pre_data, + js->ir_pre, + tdi_data, + start_index, + count, + js->ir_post_data, + js->ir_post); + /* Do the IRSCAN */ + alt_jtag_irscan(astate, + start_code, + shift_count, + js->ir_buffer, + NULL); + + /* alt_jtag_irscan() always ends in IRPAUSE state */ + js->jtag_state = IRPAUSE; + } + + if (status == 0) + if (js->irstop_state != IRPAUSE) + status = altera_goto_jstate(astate, js->irstop_state); + + + return status; +} + +int altera_swap_ir(struct altera_state *astate, + u32 count, + u8 *in_data, + u32 in_index, + u8 *out_data, + u32 out_index) +/* Shifts data into instruction register, capturing output data */ +{ + struct altera_jtag *js = &astate->js; + int start_code = 0; + u32 alloc_chars = 0; + u32 shift_count = js->ir_pre + count + js->ir_post; + int status = 0; + enum altera_jtag_state start_state = ILLEGAL_JTAG_STATE; + + switch (js->jtag_state) { + case ILLEGAL_JTAG_STATE: + case RESET: + case IDLE: + start_code = 0; + start_state = IDLE; + break; + + case DRSELECT: + case DRCAPTURE: + case DRSHIFT: + case DREXIT1: + case DRPAUSE: + case DREXIT2: + case DRUPDATE: + start_code = 1; + start_state = DRPAUSE; + break; + + case IRSELECT: + case IRCAPTURE: + case IRSHIFT: + case IREXIT1: + case IRPAUSE: + case IREXIT2: + case IRUPDATE: + start_code = 2; + start_state = IRPAUSE; + break; + + default: + status = -EREMOTEIO; + break; + } + + if (status == 0) + if (js->jtag_state != start_state) + status = altera_goto_jstate(astate, start_state); + + if (status == 0) { + if (shift_count > js->ir_length) { + alloc_chars = (shift_count + 7) >> 3; + kfree(js->ir_buffer); + js->ir_buffer = (u8 *)alt_malloc(alloc_chars); + if (js->ir_buffer == NULL) + status = -ENOMEM; + else + js->ir_length = alloc_chars * 8; + + } + } + + if (status == 0) { + /* + * Copy preamble data, IR data, + * and postamble data into a buffer + */ + altera_concatenate_data(js->ir_buffer, + js->ir_pre_data, + js->ir_pre, + in_data, + in_index, + count, + js->ir_post_data, + js->ir_post); + + /* Do the IRSCAN */ + alt_jtag_irscan(astate, + start_code, + shift_count, + js->ir_buffer, + js->ir_buffer); + + /* alt_jtag_irscan() always ends in IRPAUSE state */ + js->jtag_state = IRPAUSE; + } + + if (status == 0) + if (js->irstop_state != IRPAUSE) + status = altera_goto_jstate(astate, js->irstop_state); + + + if (status == 0) + /* Now extract the returned data from the buffer */ + altera_extract_target_data(js->ir_buffer, + out_data, out_index, + js->ir_pre, count); + + return status; +} + +int altera_drscan(struct altera_state *astate, + u32 count, + u8 *tdi_data, + u32 start_index) +/* Shifts data into data register (ignoring output data) */ +{ + struct altera_jtag *js = &astate->js; + int start_code = 0; + u32 alloc_chars = 0; + u32 shift_count = js->dr_pre + count + js->dr_post; + int status = 0; + enum altera_jtag_state start_state = ILLEGAL_JTAG_STATE; + + switch (js->jtag_state) { + case ILLEGAL_JTAG_STATE: + case RESET: + case IDLE: + start_code = 0; + start_state = IDLE; + break; + + case DRSELECT: + case DRCAPTURE: + case DRSHIFT: + case DREXIT1: + case DRPAUSE: + case DREXIT2: + case DRUPDATE: + start_code = 1; + start_state = DRPAUSE; + break; + + case IRSELECT: + case IRCAPTURE: + case IRSHIFT: + case IREXIT1: + case IRPAUSE: + case IREXIT2: + case IRUPDATE: + start_code = 2; + start_state = IRPAUSE; + break; + + default: + status = -EREMOTEIO; + break; + } + + if (status == 0) + if (js->jtag_state != start_state) + status = altera_goto_jstate(astate, start_state); + + if (status == 0) { + if (shift_count > js->dr_length) { + alloc_chars = (shift_count + 7) >> 3; + kfree(js->dr_buffer); + js->dr_buffer = (u8 *)alt_malloc(alloc_chars); + if (js->dr_buffer == NULL) + status = -ENOMEM; + else + js->dr_length = alloc_chars * 8; + + } + } + + if (status == 0) { + /* + * Copy preamble data, DR data, + * and postamble data into a buffer + */ + altera_concatenate_data(js->dr_buffer, + js->dr_pre_data, + js->dr_pre, + tdi_data, + start_index, + count, + js->dr_post_data, + js->dr_post); + /* Do the DRSCAN */ + alt_jtag_drscan(astate, start_code, shift_count, + js->dr_buffer, NULL); + /* alt_jtag_drscan() always ends in DRPAUSE state */ + js->jtag_state = DRPAUSE; + } + + if (status == 0) + if (js->drstop_state != DRPAUSE) + status = altera_goto_jstate(astate, js->drstop_state); + + return status; +} + +int altera_swap_dr(struct altera_state *astate, u32 count, + u8 *in_data, u32 in_index, + u8 *out_data, u32 out_index) +/* Shifts data into data register, capturing output data */ +{ + struct altera_jtag *js = &astate->js; + int start_code = 0; + u32 alloc_chars = 0; + u32 shift_count = js->dr_pre + count + js->dr_post; + int status = 0; + enum altera_jtag_state start_state = ILLEGAL_JTAG_STATE; + + switch (js->jtag_state) { + case ILLEGAL_JTAG_STATE: + case RESET: + case IDLE: + start_code = 0; + start_state = IDLE; + break; + + case DRSELECT: + case DRCAPTURE: + case DRSHIFT: + case DREXIT1: + case DRPAUSE: + case DREXIT2: + case DRUPDATE: + start_code = 1; + start_state = DRPAUSE; + break; + + case IRSELECT: + case IRCAPTURE: + case IRSHIFT: + case IREXIT1: + case IRPAUSE: + case IREXIT2: + case IRUPDATE: + start_code = 2; + start_state = IRPAUSE; + break; + + default: + status = -EREMOTEIO; + break; + } + + if (status == 0) + if (js->jtag_state != start_state) + status = altera_goto_jstate(astate, start_state); + + if (status == 0) { + if (shift_count > js->dr_length) { + alloc_chars = (shift_count + 7) >> 3; + kfree(js->dr_buffer); + js->dr_buffer = (u8 *)alt_malloc(alloc_chars); + + if (js->dr_buffer == NULL) + status = -ENOMEM; + else + js->dr_length = alloc_chars * 8; + + } + } + + if (status == 0) { + /* + * Copy preamble data, DR data, + * and postamble data into a buffer + */ + altera_concatenate_data(js->dr_buffer, + js->dr_pre_data, + js->dr_pre, + in_data, + in_index, + count, + js->dr_post_data, + js->dr_post); + + /* Do the DRSCAN */ + alt_jtag_drscan(astate, + start_code, + shift_count, + js->dr_buffer, + js->dr_buffer); + + /* alt_jtag_drscan() always ends in DRPAUSE state */ + js->jtag_state = DRPAUSE; + } + + if (status == 0) + if (js->drstop_state != DRPAUSE) + status = altera_goto_jstate(astate, js->drstop_state); + + if (status == 0) + /* Now extract the returned data from the buffer */ + altera_extract_target_data(js->dr_buffer, + out_data, + out_index, + js->dr_pre, + count); + + return status; +} + +void altera_free_buffers(struct altera_state *astate) +{ + struct altera_jtag *js = &astate->js; + /* If the JTAG interface was used, reset it to TLR */ + if (js->jtag_state != ILLEGAL_JTAG_STATE) + altera_jreset_idle(astate); + + kfree(js->dr_pre_data); + js->dr_pre_data = NULL; + + kfree(js->dr_post_data); + js->dr_post_data = NULL; + + kfree(js->dr_buffer); + js->dr_buffer = NULL; + + kfree(js->ir_pre_data); + js->ir_pre_data = NULL; + + kfree(js->ir_post_data); + js->ir_post_data = NULL; + + kfree(js->ir_buffer); + js->ir_buffer = NULL; +} diff --git a/drivers/misc/altera-stapl/altera-jtag.h b/drivers/misc/altera-stapl/altera-jtag.h new file mode 100644 index 00000000000..2f97e36a2fb --- /dev/null +++ b/drivers/misc/altera-stapl/altera-jtag.h @@ -0,0 +1,113 @@ +/* + * altera-jtag.h + * + * altera FPGA driver + * + * Copyright (C) Altera Corporation 1998-2001 + * Copyright (C) 2010 NetUP Inc. + * Copyright (C) 2010 Igor M. Liplianin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef ALTERA_JTAG_H +#define ALTERA_JTAG_H + +/* Function Prototypes */ +enum altera_jtag_state { + ILLEGAL_JTAG_STATE = -1, + RESET = 0, + IDLE = 1, + DRSELECT = 2, + DRCAPTURE = 3, + DRSHIFT = 4, + DREXIT1 = 5, + DRPAUSE = 6, + DREXIT2 = 7, + DRUPDATE = 8, + IRSELECT = 9, + IRCAPTURE = 10, + IRSHIFT = 11, + IREXIT1 = 12, + IRPAUSE = 13, + IREXIT2 = 14, + IRUPDATE = 15 + +}; + +struct altera_jtag { + /* Global variable to store the current JTAG state */ + enum altera_jtag_state jtag_state; + + /* Store current stop-state for DR and IR scan commands */ + enum altera_jtag_state drstop_state; + enum altera_jtag_state irstop_state; + + /* Store current padding values */ + u32 dr_pre; + u32 dr_post; + u32 ir_pre; + u32 ir_post; + u32 dr_length; + u32 ir_length; + u8 *dr_pre_data; + u8 *dr_post_data; + u8 *ir_pre_data; + u8 *ir_post_data; + u8 *dr_buffer; + u8 *ir_buffer; +}; + +#define ALTERA_STACK_SIZE 128 +#define ALTERA_MESSAGE_LENGTH 1024 + +struct altera_state { + struct altera_config *config; + struct altera_jtag js; + char msg_buff[ALTERA_MESSAGE_LENGTH + 1]; + long stack[ALTERA_STACK_SIZE]; +}; + +int altera_jinit(struct altera_state *astate); +int altera_set_drstop(struct altera_jtag *js, enum altera_jtag_state state); +int altera_set_irstop(struct altera_jtag *js, enum altera_jtag_state state); +int altera_set_dr_pre(struct altera_jtag *js, u32 count, u32 start_index, + u8 *preamble_data); +int altera_set_ir_pre(struct altera_jtag *js, u32 count, u32 start_index, + u8 *preamble_data); +int altera_set_dr_post(struct altera_jtag *js, u32 count, u32 start_index, + u8 *postamble_data); +int altera_set_ir_post(struct altera_jtag *js, u32 count, u32 start_index, + u8 *postamble_data); +int altera_goto_jstate(struct altera_state *astate, + enum altera_jtag_state state); +int altera_wait_cycles(struct altera_state *astate, s32 cycles, + enum altera_jtag_state wait_state); +int altera_wait_msecs(struct altera_state *astate, s32 microseconds, + enum altera_jtag_state wait_state); +int altera_irscan(struct altera_state *astate, u32 count, + u8 *tdi_data, u32 start_index); +int altera_swap_ir(struct altera_state *astate, + u32 count, u8 *in_data, + u32 in_index, u8 *out_data, + u32 out_index); +int altera_drscan(struct altera_state *astate, u32 count, + u8 *tdi_data, u32 start_index); +int altera_swap_dr(struct altera_state *astate, u32 count, + u8 *in_data, u32 in_index, + u8 *out_data, u32 out_index); +void altera_free_buffers(struct altera_state *astate); +#endif /* ALTERA_JTAG_H */ diff --git a/drivers/misc/altera-stapl/altera-lpt.c b/drivers/misc/altera-stapl/altera-lpt.c new file mode 100644 index 00000000000..91456a03612 --- /dev/null +++ b/drivers/misc/altera-stapl/altera-lpt.c @@ -0,0 +1,70 @@ +/* + * altera-lpt.c + * + * altera FPGA driver + * + * Copyright (C) Altera Corporation 1998-2001 + * Copyright (C) 2010 NetUP Inc. + * Copyright (C) 2010 Abylay Ospan + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include "altera-exprt.h" + +static int lpt_hardware_initialized; + +static void byteblaster_write(int port, int data) +{ + outb((u8)data, (u16)(port + 0x378)); +}; + +static int byteblaster_read(int port) +{ + int data = 0; + data = inb((u16)(port + 0x378)); + return data & 0xff; +}; + +int netup_jtag_io_lpt(void *device, int tms, int tdi, int read_tdo) +{ + int data = 0; + int tdo = 0; + int initial_lpt_ctrl = 0; + + if (!lpt_hardware_initialized) { + initial_lpt_ctrl = byteblaster_read(2); + byteblaster_write(2, (initial_lpt_ctrl | 0x02) & 0xdf); + lpt_hardware_initialized = 1; + } + + data = ((tdi ? 0x40 : 0) | (tms ? 0x02 : 0)); + + byteblaster_write(0, data); + + if (read_tdo) { + tdo = byteblaster_read(1); + tdo = ((tdo & 0x80) ? 0 : 1); + } + + byteblaster_write(0, data | 0x01); + + byteblaster_write(0, data); + + return tdo; +} diff --git a/drivers/misc/altera-stapl/altera.c b/drivers/misc/altera-stapl/altera.c new file mode 100644 index 00000000000..1a2c50b82f9 --- /dev/null +++ b/drivers/misc/altera-stapl/altera.c @@ -0,0 +1,2536 @@ +/* + * altera.c + * + * altera FPGA driver + * + * Copyright (C) Altera Corporation 1998-2001 + * Copyright (C) 2010,2011 NetUP Inc. + * Copyright (C) 2010,2011 Igor M. Liplianin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include "altera-exprt.h" +#include "altera-jtag.h" + +static int debug = 1; +module_param(debug, int, 0644); +MODULE_PARM_DESC(debug, "enable debugging information"); + +MODULE_DESCRIPTION("altera FPGA kernel module"); +MODULE_AUTHOR("Igor M. Liplianin "); +MODULE_LICENSE("GPL"); + +#define dprintk(args...) \ + if (debug) { \ + printk(KERN_DEBUG args); \ + } + +enum altera_fpga_opcode { + OP_NOP = 0, + OP_DUP, + OP_SWP, + OP_ADD, + OP_SUB, + OP_MULT, + OP_DIV, + OP_MOD, + OP_SHL, + OP_SHR, + OP_NOT, + OP_AND, + OP_OR, + OP_XOR, + OP_INV, + OP_GT, + OP_LT, + OP_RET, + OP_CMPS, + OP_PINT, + OP_PRNT, + OP_DSS, + OP_DSSC, + OP_ISS, + OP_ISSC, + OP_DPR = 0x1c, + OP_DPRL, + OP_DPO, + OP_DPOL, + OP_IPR, + OP_IPRL, + OP_IPO, + OP_IPOL, + OP_PCHR, + OP_EXIT, + OP_EQU, + OP_POPT, + OP_ABS = 0x2c, + OP_BCH0, + OP_PSH0 = 0x2f, + OP_PSHL = 0x40, + OP_PSHV, + OP_JMP, + OP_CALL, + OP_NEXT, + OP_PSTR, + OP_SINT = 0x47, + OP_ST, + OP_ISTP, + OP_DSTP, + OP_SWPN, + OP_DUPN, + OP_POPV, + OP_POPE, + OP_POPA, + OP_JMPZ, + OP_DS, + OP_IS, + OP_DPRA, + OP_DPOA, + OP_IPRA, + OP_IPOA, + OP_EXPT, + OP_PSHE, + OP_PSHA, + OP_DYNA, + OP_EXPV = 0x5c, + OP_COPY = 0x80, + OP_REVA, + OP_DSC, + OP_ISC, + OP_WAIT, + OP_VS, + OP_CMPA = 0xc0, + OP_VSC, +}; + +struct altera_procinfo { + char *name; + u8 attrs; + struct altera_procinfo *next; +}; + +/* This function checks if enough parameters are available on the stack. */ +static int altera_check_stack(int stack_ptr, int count, int *status) +{ + if (stack_ptr < count) { + *status = -EOVERFLOW; + return 0; + } + + return 1; +} + +static void altera_export_int(char *key, s32 value) +{ + dprintk("Export: key = \"%s\", value = %d\n", key, value); +} + +#define HEX_LINE_CHARS 72 +#define HEX_LINE_BITS (HEX_LINE_CHARS * 4) + +static void altera_export_bool_array(char *key, u8 *data, s32 count) +{ + char string[HEX_LINE_CHARS + 1]; + s32 i, offset; + u32 size, line, lines, linebits, value, j, k; + + if (count > HEX_LINE_BITS) { + dprintk("Export: key = \"%s\", %d bits, value = HEX\n", + key, count); + lines = (count + (HEX_LINE_BITS - 1)) / HEX_LINE_BITS; + + for (line = 0; line < lines; ++line) { + if (line < (lines - 1)) { + linebits = HEX_LINE_BITS; + size = HEX_LINE_CHARS; + offset = count - ((line + 1) * HEX_LINE_BITS); + } else { + linebits = + count - ((lines - 1) * HEX_LINE_BITS); + size = (linebits + 3) / 4; + offset = 0L; + } + + string[size] = '\0'; + j = size - 1; + value = 0; + + for (k = 0; k < linebits; ++k) { + i = k + offset; + if (data[i >> 3] & (1 << (i & 7))) + value |= (1 << (i & 3)); + if ((i & 3) == 3) { + sprintf(&string[j], "%1x", value); + value = 0; + --j; + } + } + if ((k & 3) > 0) + sprintf(&string[j], "%1x", value); + + dprintk("%s\n", string); + } + + } else { + size = (count + 3) / 4; + string[size] = '\0'; + j = size - 1; + value = 0; + + for (i = 0; i < count; ++i) { + if (data[i >> 3] & (1 << (i & 7))) + value |= (1 << (i & 3)); + if ((i & 3) == 3) { + sprintf(&string[j], "%1x", value); + value = 0; + --j; + } + } + if ((i & 3) > 0) + sprintf(&string[j], "%1x", value); + + dprintk("Export: key = \"%s\", %d bits, value = HEX %s\n", + key, count, string); + } +} + +static int altera_execute(struct altera_state *astate, + u8 *p, + s32 program_size, + s32 *error_address, + int *exit_code, + int *format_version) +{ + struct altera_config *aconf = astate->config; + char *msg_buff = astate->msg_buff; + long *stack = astate->stack; + int status = 0; + u32 first_word = 0L; + u32 action_table = 0L; + u32 proc_table = 0L; + u32 str_table = 0L; + u32 sym_table = 0L; + u32 data_sect = 0L; + u32 code_sect = 0L; + u32 debug_sect = 0L; + u32 action_count = 0L; + u32 proc_count = 0L; + u32 sym_count = 0L; + long *vars = NULL; + s32 *var_size = NULL; + char *attrs = NULL; + u8 *proc_attributes = NULL; + u32 pc; + u32 opcode_address; + u32 args[3]; + u32 opcode; + u32 name_id; + u8 charbuf[4]; + long long_tmp; + u32 variable_id; + u8 *charptr_tmp; + u8 *charptr_tmp2; + long *longptr_tmp; + int version = 0; + int delta = 0; + int stack_ptr = 0; + u32 arg_count; + int done = 0; + int bad_opcode = 0; + u32 count; + u32 index; + u32 index2; + s32 long_count; + s32 long_idx; + s32 long_idx2; + u32 i; + u32 j; + u32 uncomp_size; + u32 offset; + u32 value; + int current_proc = 0; + int reverse; + + char *name; + + dprintk("%s\n", __func__); + + /* Read header information */ + if (program_size > 52L) { + first_word = get_unaligned_be32(&p[0]); + version = (first_word & 1L); + *format_version = version + 1; + delta = version * 8; + + action_table = get_unaligned_be32(&p[4]); + proc_table = get_unaligned_be32(&p[8]); + str_table = get_unaligned_be32(&p[4 + delta]); + sym_table = get_unaligned_be32(&p[16 + delta]); + data_sect = get_unaligned_be32(&p[20 + delta]); + code_sect = get_unaligned_be32(&p[24 + delta]); + debug_sect = get_unaligned_be32(&p[28 + delta]); + action_count = get_unaligned_be32(&p[40 + delta]); + proc_count = get_unaligned_be32(&p[44 + delta]); + sym_count = get_unaligned_be32(&p[48 + (2 * delta)]); + } + + if ((first_word != 0x4A414D00L) && (first_word != 0x4A414D01L)) { + done = 1; + status = -EIO; + goto exit_done; + } + + if (sym_count <= 0) + goto exit_done; + + vars = kzalloc(sym_count * sizeof(long), GFP_KERNEL); + + if (vars == NULL) + status = -ENOMEM; + + if (status == 0) { + var_size = kzalloc(sym_count * sizeof(s32), GFP_KERNEL); + + if (var_size == NULL) + status = -ENOMEM; + } + + if (status == 0) { + attrs = kzalloc(sym_count, GFP_KERNEL); + + if (attrs == NULL) + status = -ENOMEM; + } + + if ((status == 0) && (version > 0)) { + proc_attributes = kzalloc(proc_count, GFP_KERNEL); + + if (proc_attributes == NULL) + status = -ENOMEM; + } + + if (status != 0) + goto exit_done; + + delta = version * 2; + + for (i = 0; i < sym_count; ++i) { + offset = (sym_table + ((11 + delta) * i)); + + value = get_unaligned_be32(&p[offset + 3 + delta]); + + attrs[i] = p[offset]; + + /* + * use bit 7 of attribute byte to indicate that + * this buffer was dynamically allocated + * and should be freed later + */ + attrs[i] &= 0x7f; + + var_size[i] = get_unaligned_be32(&p[offset + 7 + delta]); + + /* + * Attribute bits: + * bit 0: 0 = read-only, 1 = read-write + * bit 1: 0 = not compressed, 1 = compressed + * bit 2: 0 = not initialized, 1 = initialized + * bit 3: 0 = scalar, 1 = array + * bit 4: 0 = Boolean, 1 = integer + * bit 5: 0 = declared variable, + * 1 = compiler created temporary variable + */ + + if ((attrs[i] & 0x0c) == 0x04) + /* initialized scalar variable */ + vars[i] = value; + else if ((attrs[i] & 0x1e) == 0x0e) { + /* initialized compressed Boolean array */ + uncomp_size = get_unaligned_le32(&p[data_sect + value]); + + /* allocate a buffer for the uncompressed data */ + vars[i] = (long)kzalloc(uncomp_size, GFP_KERNEL); + if (vars[i] == 0L) + status = -ENOMEM; + else { + /* set flag so buffer will be freed later */ + attrs[i] |= 0x80; + + /* uncompress the data */ + if (altera_shrink(&p[data_sect + value], + var_size[i], + (u8 *)vars[i], + uncomp_size, + version) != uncomp_size) + /* decompression failed */ + status = -EIO; + else + var_size[i] = uncomp_size * 8L; + + } + } else if ((attrs[i] & 0x1e) == 0x0c) { + /* initialized Boolean array */ + vars[i] = value + data_sect + (long)p; + } else if ((attrs[i] & 0x1c) == 0x1c) { + /* initialized integer array */ + vars[i] = value + data_sect; + } else if ((attrs[i] & 0x0c) == 0x08) { + /* uninitialized array */ + + /* flag attrs so that memory is freed */ + attrs[i] |= 0x80; + + if (var_size[i] > 0) { + u32 size; + + if (attrs[i] & 0x10) + /* integer array */ + size = (var_size[i] * sizeof(s32)); + else + /* Boolean array */ + size = ((var_size[i] + 7L) / 8L); + + vars[i] = (long)kzalloc(size, GFP_KERNEL); + + if (vars[i] == 0) { + status = -ENOMEM; + } else { + /* zero out memory */ + for (j = 0; j < size; ++j) + ((u8 *)(vars[i]))[j] = 0; + + } + } else + vars[i] = 0; + + } else + vars[i] = 0; + + } + +exit_done: + if (status != 0) + done = 1; + + altera_jinit(astate); + + pc = code_sect; + msg_buff[0] = '\0'; + + /* + * For JBC version 2, we will execute the procedures corresponding to + * the selected ACTION + */ + if (version > 0) { + if (aconf->action == NULL) { + status = -EINVAL; + done = 1; + } else { + int action_found = 0; + for (i = 0; (i < action_count) && !action_found; ++i) { + name_id = get_unaligned_be32(&p[action_table + + (12 * i)]); + + name = &p[str_table + name_id]; + + if (strnicmp(aconf->action, name, strlen(name)) == 0) { + action_found = 1; + current_proc = + get_unaligned_be32(&p[action_table + + (12 * i) + 8]); + } + } + + if (!action_found) { + status = -EINVAL; + done = 1; + } + } + + if (status == 0) { + int first_time = 1; + i = current_proc; + while ((i != 0) || first_time) { + first_time = 0; + /* check procedure attribute byte */ + proc_attributes[i] = + (p[proc_table + + (13 * i) + 8] & + 0x03); + + /* + * BIT0 - OPTIONAL + * BIT1 - RECOMMENDED + * BIT6 - FORCED OFF + * BIT7 - FORCED ON + */ + + i = get_unaligned_be32(&p[proc_table + + (13 * i) + 4]); + } + + /* + * Set current_proc to the first procedure + * to be executed + */ + i = current_proc; + while ((i != 0) && + ((proc_attributes[i] == 1) || + ((proc_attributes[i] & 0xc0) == 0x40))) { + i = get_unaligned_be32(&p[proc_table + + (13 * i) + 4]); + } + + if ((i != 0) || ((i == 0) && (current_proc == 0) && + ((proc_attributes[0] != 1) && + ((proc_attributes[0] & 0xc0) != 0x40)))) { + current_proc = i; + pc = code_sect + + get_unaligned_be32(&p[proc_table + + (13 * i) + 9]); + if ((pc < code_sect) || (pc >= debug_sect)) + status = -ERANGE; + } else + /* there are no procedures to execute! */ + done = 1; + + } + } + + msg_buff[0] = '\0'; + + while (!done) { + opcode = (p[pc] & 0xff); + opcode_address = pc; + ++pc; + + if (debug > 1) + printk("opcode: %02x\n", opcode); + + arg_count = (opcode >> 6) & 3; + for (i = 0; i < arg_count; ++i) { + args[i] = get_unaligned_be32(&p[pc]); + pc += 4; + } + + switch (opcode) { + case OP_NOP: + break; + case OP_DUP: + if (altera_check_stack(stack_ptr, 1, &status)) { + stack[stack_ptr] = stack[stack_ptr - 1]; + ++stack_ptr; + } + break; + case OP_SWP: + if (altera_check_stack(stack_ptr, 2, &status)) { + long_tmp = stack[stack_ptr - 2]; + stack[stack_ptr - 2] = stack[stack_ptr - 1]; + stack[stack_ptr - 1] = long_tmp; + } + break; + case OP_ADD: + if (altera_check_stack(stack_ptr, 2, &status)) { + --stack_ptr; + stack[stack_ptr - 1] += stack[stack_ptr]; + } + break; + case OP_SUB: + if (altera_check_stack(stack_ptr, 2, &status)) { + --stack_ptr; + stack[stack_ptr - 1] -= stack[stack_ptr]; + } + break; + case OP_MULT: + if (altera_check_stack(stack_ptr, 2, &status)) { + --stack_ptr; + stack[stack_ptr - 1] *= stack[stack_ptr]; + } + break; + case OP_DIV: + if (altera_check_stack(stack_ptr, 2, &status)) { + --stack_ptr; + stack[stack_ptr - 1] /= stack[stack_ptr]; + } + break; + case OP_MOD: + if (altera_check_stack(stack_ptr, 2, &status)) { + --stack_ptr; + stack[stack_ptr - 1] %= stack[stack_ptr]; + } + break; + case OP_SHL: + if (altera_check_stack(stack_ptr, 2, &status)) { + --stack_ptr; + stack[stack_ptr - 1] <<= stack[stack_ptr]; + } + break; + case OP_SHR: + if (altera_check_stack(stack_ptr, 2, &status)) { + --stack_ptr; + stack[stack_ptr - 1] >>= stack[stack_ptr]; + } + break; + case OP_NOT: + if (altera_check_stack(stack_ptr, 1, &status)) + stack[stack_ptr - 1] ^= (-1L); + + break; + case OP_AND: + if (altera_check_stack(stack_ptr, 2, &status)) { + --stack_ptr; + stack[stack_ptr - 1] &= stack[stack_ptr]; + } + break; + case OP_OR: + if (altera_check_stack(stack_ptr, 2, &status)) { + --stack_ptr; + stack[stack_ptr - 1] |= stack[stack_ptr]; + } + break; + case OP_XOR: + if (altera_check_stack(stack_ptr, 2, &status)) { + --stack_ptr; + stack[stack_ptr - 1] ^= stack[stack_ptr]; + } + break; + case OP_INV: + if (!altera_check_stack(stack_ptr, 1, &status)) + break; + stack[stack_ptr - 1] = stack[stack_ptr - 1] ? 0L : 1L; + break; + case OP_GT: + if (!altera_check_stack(stack_ptr, 2, &status)) + break; + --stack_ptr; + stack[stack_ptr - 1] = + (stack[stack_ptr - 1] > stack[stack_ptr]) ? + 1L : 0L; + + break; + case OP_LT: + if (!altera_check_stack(stack_ptr, 2, &status)) + break; + --stack_ptr; + stack[stack_ptr - 1] = + (stack[stack_ptr - 1] < stack[stack_ptr]) ? + 1L : 0L; + + break; + case OP_RET: + if ((version > 0) && (stack_ptr == 0)) { + /* + * We completed one of the main procedures + * of an ACTION. + * Find the next procedure + * to be executed and jump to it. + * If there are no more procedures, then EXIT. + */ + i = get_unaligned_be32(&p[proc_table + + (13 * current_proc) + 4]); + while ((i != 0) && + ((proc_attributes[i] == 1) || + ((proc_attributes[i] & 0xc0) == 0x40))) + i = get_unaligned_be32(&p[proc_table + + (13 * i) + 4]); + + if (i == 0) { + /* no procedures to execute! */ + done = 1; + *exit_code = 0; /* success */ + } else { + current_proc = i; + pc = code_sect + get_unaligned_be32( + &p[proc_table + + (13 * i) + 9]); + if ((pc < code_sect) || + (pc >= debug_sect)) + status = -ERANGE; + } + + } else + if (altera_check_stack(stack_ptr, 1, &status)) { + pc = stack[--stack_ptr] + code_sect; + if ((pc <= code_sect) || + (pc >= debug_sect)) + status = -ERANGE; + + } + + break; + case OP_CMPS: + /* + * Array short compare + * ...stack 0 is source 1 value + * ...stack 1 is source 2 value + * ...stack 2 is mask value + * ...stack 3 is count + */ + if (altera_check_stack(stack_ptr, 4, &status)) { + s32 a = stack[--stack_ptr]; + s32 b = stack[--stack_ptr]; + long_tmp = stack[--stack_ptr]; + count = stack[stack_ptr - 1]; + + if ((count < 1) || (count > 32)) + status = -ERANGE; + else { + long_tmp &= ((-1L) >> (32 - count)); + + stack[stack_ptr - 1] = + ((a & long_tmp) == (b & long_tmp)) + ? 1L : 0L; + } + } + break; + case OP_PINT: + /* + * PRINT add integer + * ...stack 0 is integer value + */ + if (!altera_check_stack(stack_ptr, 1, &status)) + break; + sprintf(&msg_buff[strlen(msg_buff)], + "%ld", stack[--stack_ptr]); + break; + case OP_PRNT: + /* PRINT finish */ + if (debug) + printk(msg_buff, "\n"); + + msg_buff[0] = '\0'; + break; + case OP_DSS: + /* + * DRSCAN short + * ...stack 0 is scan data + * ...stack 1 is count + */ + if (!altera_check_stack(stack_ptr, 2, &status)) + break; + long_tmp = stack[--stack_ptr]; + count = stack[--stack_ptr]; + put_unaligned_le32(long_tmp, &charbuf[0]); + status = altera_drscan(astate, count, charbuf, 0); + break; + case OP_DSSC: + /* + * DRSCAN short with capture + * ...stack 0 is scan data + * ...stack 1 is count + */ + if (!altera_check_stack(stack_ptr, 2, &status)) + break; + long_tmp = stack[--stack_ptr]; + count = stack[stack_ptr - 1]; + put_unaligned_le32(long_tmp, &charbuf[0]); + status = altera_swap_dr(astate, count, charbuf, + 0, charbuf, 0); + stack[stack_ptr - 1] = get_unaligned_le32(&charbuf[0]); + break; + case OP_ISS: + /* + * IRSCAN short + * ...stack 0 is scan data + * ...stack 1 is count + */ + if (!altera_check_stack(stack_ptr, 2, &status)) + break; + long_tmp = stack[--stack_ptr]; + count = stack[--stack_ptr]; + put_unaligned_le32(long_tmp, &charbuf[0]); + status = altera_irscan(astate, count, charbuf, 0); + break; + case OP_ISSC: + /* + * IRSCAN short with capture + * ...stack 0 is scan data + * ...stack 1 is count + */ + if (!altera_check_stack(stack_ptr, 2, &status)) + break; + long_tmp = stack[--stack_ptr]; + count = stack[stack_ptr - 1]; + put_unaligned_le32(long_tmp, &charbuf[0]); + status = altera_swap_ir(astate, count, charbuf, + 0, charbuf, 0); + stack[stack_ptr - 1] = get_unaligned_le32(&charbuf[0]); + break; + case OP_DPR: + if (!altera_check_stack(stack_ptr, 1, &status)) + break; + count = stack[--stack_ptr]; + status = altera_set_dr_pre(&astate->js, count, 0, NULL); + break; + case OP_DPRL: + /* + * DRPRE with literal data + * ...stack 0 is count + * ...stack 1 is literal data + */ + if (!altera_check_stack(stack_ptr, 2, &status)) + break; + count = stack[--stack_ptr]; + long_tmp = stack[--stack_ptr]; + put_unaligned_le32(long_tmp, &charbuf[0]); + status = altera_set_dr_pre(&astate->js, count, 0, + charbuf); + break; + case OP_DPO: + /* + * DRPOST + * ...stack 0 is count + */ + if (altera_check_stack(stack_ptr, 1, &status)) { + count = stack[--stack_ptr]; + status = altera_set_dr_post(&astate->js, count, + 0, NULL); + } + break; + case OP_DPOL: + /* + * DRPOST with literal data + * ...stack 0 is count + * ...stack 1 is literal data + */ + if (!altera_check_stack(stack_ptr, 2, &status)) + break; + count = stack[--stack_ptr]; + long_tmp = stack[--stack_ptr]; + put_unaligned_le32(long_tmp, &charbuf[0]); + status = altera_set_dr_post(&astate->js, count, 0, + charbuf); + break; + case OP_IPR: + if (altera_check_stack(stack_ptr, 1, &status)) { + count = stack[--stack_ptr]; + status = altera_set_ir_pre(&astate->js, count, + 0, NULL); + } + break; + case OP_IPRL: + /* + * IRPRE with literal data + * ...stack 0 is count + * ...stack 1 is literal data + */ + if (altera_check_stack(stack_ptr, 2, &status)) { + count = stack[--stack_ptr]; + long_tmp = stack[--stack_ptr]; + put_unaligned_le32(long_tmp, &charbuf[0]); + status = altera_set_ir_pre(&astate->js, count, + 0, charbuf); + } + break; + case OP_IPO: + /* + * IRPOST + * ...stack 0 is count + */ + if (altera_check_stack(stack_ptr, 1, &status)) { + count = stack[--stack_ptr]; + status = altera_set_ir_post(&astate->js, count, + 0, NULL); + } + break; + case OP_IPOL: + /* + * IRPOST with literal data + * ...stack 0 is count + * ...stack 1 is literal data + */ + if (!altera_check_stack(stack_ptr, 2, &status)) + break; + count = stack[--stack_ptr]; + long_tmp = stack[--stack_ptr]; + put_unaligned_le32(long_tmp, &charbuf[0]); + status = altera_set_ir_post(&astate->js, count, 0, + charbuf); + break; + case OP_PCHR: + if (altera_check_stack(stack_ptr, 1, &status)) { + u8 ch; + count = strlen(msg_buff); + ch = (char) stack[--stack_ptr]; + if ((ch < 1) || (ch > 127)) { + /* + * character code out of range + * instead of flagging an error, + * force the value to 127 + */ + ch = 127; + } + msg_buff[count] = ch; + msg_buff[count + 1] = '\0'; + } + break; + case OP_EXIT: + if (altera_check_stack(stack_ptr, 1, &status)) + *exit_code = stack[--stack_ptr]; + + done = 1; + break; + case OP_EQU: + if (!altera_check_stack(stack_ptr, 2, &status)) + break; + --stack_ptr; + stack[stack_ptr - 1] = + (stack[stack_ptr - 1] == stack[stack_ptr]) ? + 1L : 0L; + break; + case OP_POPT: + if (altera_check_stack(stack_ptr, 1, &status)) + --stack_ptr; + + break; + case OP_ABS: + if (!altera_check_stack(stack_ptr, 1, &status)) + break; + if (stack[stack_ptr - 1] < 0) + stack[stack_ptr - 1] = 0 - stack[stack_ptr - 1]; + + break; + case OP_BCH0: + /* + * Batch operation 0 + * SWP + * SWPN 7 + * SWP + * SWPN 6 + * DUPN 8 + * SWPN 2 + * SWP + * DUPN 6 + * DUPN 6 + */ + + /* SWP */ + if (altera_check_stack(stack_ptr, 2, &status)) { + long_tmp = stack[stack_ptr - 2]; + stack[stack_ptr - 2] = stack[stack_ptr - 1]; + stack[stack_ptr - 1] = long_tmp; + } + + /* SWPN 7 */ + index = 7 + 1; + if (altera_check_stack(stack_ptr, index, &status)) { + long_tmp = stack[stack_ptr - index]; + stack[stack_ptr - index] = stack[stack_ptr - 1]; + stack[stack_ptr - 1] = long_tmp; + } + + /* SWP */ + if (altera_check_stack(stack_ptr, 2, &status)) { + long_tmp = stack[stack_ptr - 2]; + stack[stack_ptr - 2] = stack[stack_ptr - 1]; + stack[stack_ptr - 1] = long_tmp; + } + + /* SWPN 6 */ + index = 6 + 1; + if (altera_check_stack(stack_ptr, index, &status)) { + long_tmp = stack[stack_ptr - index]; + stack[stack_ptr - index] = stack[stack_ptr - 1]; + stack[stack_ptr - 1] = long_tmp; + } + + /* DUPN 8 */ + index = 8 + 1; + if (altera_check_stack(stack_ptr, index, &status)) { + stack[stack_ptr] = stack[stack_ptr - index]; + ++stack_ptr; + } + + /* SWPN 2 */ + index = 2 + 1; + if (altera_check_stack(stack_ptr, index, &status)) { + long_tmp = stack[stack_ptr - index]; + stack[stack_ptr - index] = stack[stack_ptr - 1]; + stack[stack_ptr - 1] = long_tmp; + } + + /* SWP */ + if (altera_check_stack(stack_ptr, 2, &status)) { + long_tmp = stack[stack_ptr - 2]; + stack[stack_ptr - 2] = stack[stack_ptr - 1]; + stack[stack_ptr - 1] = long_tmp; + } + + /* DUPN 6 */ + index = 6 + 1; + if (altera_check_stack(stack_ptr, index, &status)) { + stack[stack_ptr] = stack[stack_ptr - index]; + ++stack_ptr; + } + + /* DUPN 6 */ + index = 6 + 1; + if (altera_check_stack(stack_ptr, index, &status)) { + stack[stack_ptr] = stack[stack_ptr - index]; + ++stack_ptr; + } + break; + case OP_PSH0: + stack[stack_ptr++] = 0; + break; + case OP_PSHL: + stack[stack_ptr++] = (s32) args[0]; + break; + case OP_PSHV: + stack[stack_ptr++] = vars[args[0]]; + break; + case OP_JMP: + pc = args[0] + code_sect; + if ((pc < code_sect) || (pc >= debug_sect)) + status = -ERANGE; + break; + case OP_CALL: + stack[stack_ptr++] = pc; + pc = args[0] + code_sect; + if ((pc < code_sect) || (pc >= debug_sect)) + status = -ERANGE; + break; + case OP_NEXT: + /* + * Process FOR / NEXT loop + * ...argument 0 is variable ID + * ...stack 0 is step value + * ...stack 1 is end value + * ...stack 2 is top address + */ + if (altera_check_stack(stack_ptr, 3, &status)) { + s32 step = stack[stack_ptr - 1]; + s32 end = stack[stack_ptr - 2]; + s32 top = stack[stack_ptr - 3]; + s32 iterator = vars[args[0]]; + int break_out = 0; + + if (step < 0) { + if (iterator <= end) + break_out = 1; + } else if (iterator >= end) + break_out = 1; + + if (break_out) { + stack_ptr -= 3; + } else { + vars[args[0]] = iterator + step; + pc = top + code_sect; + if ((pc < code_sect) || + (pc >= debug_sect)) + status = -ERANGE; + } + } + break; + case OP_PSTR: + /* + * PRINT add string + * ...argument 0 is string ID + */ + count = strlen(msg_buff); + strlcpy(&msg_buff[count], + &p[str_table + args[0]], + ALTERA_MESSAGE_LENGTH - count); + break; + case OP_SINT: + /* + * STATE intermediate state + * ...argument 0 is state code + */ + status = altera_goto_jstate(astate, args[0]); + break; + case OP_ST: + /* + * STATE final state + * ...argument 0 is state code + */ + status = altera_goto_jstate(astate, args[0]); + break; + case OP_ISTP: + /* + * IRSTOP state + * ...argument 0 is state code + */ + status = altera_set_irstop(&astate->js, args[0]); + break; + case OP_DSTP: + /* + * DRSTOP state + * ...argument 0 is state code + */ + status = altera_set_drstop(&astate->js, args[0]); + break; + + case OP_SWPN: + /* + * Exchange top with Nth stack value + * ...argument 0 is 0-based stack entry + * to swap with top element + */ + index = (args[0]) + 1; + if (altera_check_stack(stack_ptr, index, &status)) { + long_tmp = stack[stack_ptr - index]; + stack[stack_ptr - index] = stack[stack_ptr - 1]; + stack[stack_ptr - 1] = long_tmp; + } + break; + case OP_DUPN: + /* + * Duplicate Nth stack value + * ...argument 0 is 0-based stack entry to duplicate + */ + index = (args[0]) + 1; + if (altera_check_stack(stack_ptr, index, &status)) { + stack[stack_ptr] = stack[stack_ptr - index]; + ++stack_ptr; + } + break; + case OP_POPV: + /* + * Pop stack into scalar variable + * ...argument 0 is variable ID + * ...stack 0 is value + */ + if (altera_check_stack(stack_ptr, 1, &status)) + vars[args[0]] = stack[--stack_ptr]; + + break; + case OP_POPE: + /* + * Pop stack into integer array element + * ...argument 0 is variable ID + * ...stack 0 is array index + * ...stack 1 is value + */ + if (!altera_check_stack(stack_ptr, 2, &status)) + break; + variable_id = args[0]; + + /* + * If variable is read-only, + * convert to writable array + */ + if ((version > 0) && + ((attrs[variable_id] & 0x9c) == 0x1c)) { + /* Allocate a writable buffer for this array */ + count = var_size[variable_id]; + long_tmp = vars[variable_id]; + longptr_tmp = kzalloc(count * sizeof(long), + GFP_KERNEL); + vars[variable_id] = (long)longptr_tmp; + + if (vars[variable_id] == 0) { + status = -ENOMEM; + break; + } + + /* copy previous contents into buffer */ + for (i = 0; i < count; ++i) { + longptr_tmp[i] = + get_unaligned_be32(&p[long_tmp]); + long_tmp += sizeof(long); + } + + /* + * set bit 7 - buffer was + * dynamically allocated + */ + attrs[variable_id] |= 0x80; + + /* clear bit 2 - variable is writable */ + attrs[variable_id] &= ~0x04; + attrs[variable_id] |= 0x01; + + } + + /* check that variable is a writable integer array */ + if ((attrs[variable_id] & 0x1c) != 0x18) + status = -ERANGE; + else { + longptr_tmp = (long *)vars[variable_id]; + + /* pop the array index */ + index = stack[--stack_ptr]; + + /* pop the value and store it into the array */ + longptr_tmp[index] = stack[--stack_ptr]; + } + + break; + case OP_POPA: + /* + * Pop stack into Boolean array + * ...argument 0 is variable ID + * ...stack 0 is count + * ...stack 1 is array index + * ...stack 2 is value + */ + if (!altera_check_stack(stack_ptr, 3, &status)) + break; + variable_id = args[0]; + + /* + * If variable is read-only, + * convert to writable array + */ + if ((version > 0) && + ((attrs[variable_id] & 0x9c) == 0x0c)) { + /* Allocate a writable buffer for this array */ + long_tmp = + (var_size[variable_id] + 7L) >> 3L; + charptr_tmp2 = (u8 *)vars[variable_id]; + charptr_tmp = + kzalloc(long_tmp, GFP_KERNEL); + vars[variable_id] = (long)charptr_tmp; + + if (vars[variable_id] == 0) { + status = -ENOMEM; + break; + } + + /* zero the buffer */ + for (long_idx = 0L; + long_idx < long_tmp; + ++long_idx) { + charptr_tmp[long_idx] = 0; + } + + /* copy previous contents into buffer */ + for (long_idx = 0L; + long_idx < var_size[variable_id]; + ++long_idx) { + long_idx2 = long_idx; + + if (charptr_tmp2[long_idx2 >> 3] & + (1 << (long_idx2 & 7))) { + charptr_tmp[long_idx >> 3] |= + (1 << (long_idx & 7)); + } + } + + /* + * set bit 7 - buffer was + * dynamically allocated + */ + attrs[variable_id] |= 0x80; + + /* clear bit 2 - variable is writable */ + attrs[variable_id] &= ~0x04; + attrs[variable_id] |= 0x01; + + } + + /* + * check that variable is + * a writable Boolean array + */ + if ((attrs[variable_id] & 0x1c) != 0x08) { + status = -ERANGE; + break; + } + + charptr_tmp = (u8 *)vars[variable_id]; + + /* pop the count (number of bits to copy) */ + long_count = stack[--stack_ptr]; + + /* pop the array index */ + long_idx = stack[--stack_ptr]; + + reverse = 0; + + if (version > 0) { + /* + * stack 0 = array right index + * stack 1 = array left index + */ + + if (long_idx > long_count) { + reverse = 1; + long_tmp = long_count; + long_count = 1 + long_idx - + long_count; + long_idx = long_tmp; + + /* reverse POPA is not supported */ + status = -ERANGE; + break; + } else + long_count = 1 + long_count - + long_idx; + + } + + /* pop the data */ + long_tmp = stack[--stack_ptr]; + + if (long_count < 1) { + status = -ERANGE; + break; + } + + for (i = 0; i < long_count; ++i) { + if (long_tmp & (1L << (s32) i)) + charptr_tmp[long_idx >> 3L] |= + (1L << (long_idx & 7L)); + else + charptr_tmp[long_idx >> 3L] &= + ~(1L << (long_idx & 7L)); + + ++long_idx; + } + + break; + case OP_JMPZ: + /* + * Pop stack and branch if zero + * ...argument 0 is address + * ...stack 0 is condition value + */ + if (altera_check_stack(stack_ptr, 1, &status)) { + if (stack[--stack_ptr] == 0) { + pc = args[0] + code_sect; + if ((pc < code_sect) || + (pc >= debug_sect)) + status = -ERANGE; + } + } + break; + case OP_DS: + case OP_IS: + /* + * DRSCAN + * IRSCAN + * ...argument 0 is scan data variable ID + * ...stack 0 is array index + * ...stack 1 is count + */ + if (!altera_check_stack(stack_ptr, 2, &status)) + break; + long_idx = stack[--stack_ptr]; + long_count = stack[--stack_ptr]; + reverse = 0; + if (version > 0) { + /* + * stack 0 = array right index + * stack 1 = array left index + * stack 2 = count + */ + long_tmp = long_count; + long_count = stack[--stack_ptr]; + + if (long_idx > long_tmp) { + reverse = 1; + long_idx = long_tmp; + } + } + + charptr_tmp = (u8 *)vars[args[0]]; + + if (reverse) { + /* + * allocate a buffer + * and reverse the data order + */ + charptr_tmp2 = charptr_tmp; + charptr_tmp = kzalloc((long_count >> 3) + 1, + GFP_KERNEL); + if (charptr_tmp == NULL) { + status = -ENOMEM; + break; + } + + long_tmp = long_idx + long_count - 1; + long_idx2 = 0; + while (long_idx2 < long_count) { + if (charptr_tmp2[long_tmp >> 3] & + (1 << (long_tmp & 7))) + charptr_tmp[long_idx2 >> 3] |= + (1 << (long_idx2 & 7)); + else + charptr_tmp[long_idx2 >> 3] &= + ~(1 << (long_idx2 & 7)); + + --long_tmp; + ++long_idx2; + } + } + + if (opcode == 0x51) /* DS */ + status = altera_drscan(astate, long_count, + charptr_tmp, long_idx); + else /* IS */ + status = altera_irscan(astate, long_count, + charptr_tmp, long_idx); + + if (reverse) + kfree(charptr_tmp); + + break; + case OP_DPRA: + /* + * DRPRE with array data + * ...argument 0 is variable ID + * ...stack 0 is array index + * ...stack 1 is count + */ + if (!altera_check_stack(stack_ptr, 2, &status)) + break; + index = stack[--stack_ptr]; + count = stack[--stack_ptr]; + + if (version > 0) + /* + * stack 0 = array right index + * stack 1 = array left index + */ + count = 1 + count - index; + + charptr_tmp = (u8 *)vars[args[0]]; + status = altera_set_dr_pre(&astate->js, count, index, + charptr_tmp); + break; + case OP_DPOA: + /* + * DRPOST with array data + * ...argument 0 is variable ID + * ...stack 0 is array index + * ...stack 1 is count + */ + if (!altera_check_stack(stack_ptr, 2, &status)) + break; + index = stack[--stack_ptr]; + count = stack[--stack_ptr]; + + if (version > 0) + /* + * stack 0 = array right index + * stack 1 = array left index + */ + count = 1 + count - index; + + charptr_tmp = (u8 *)vars[args[0]]; + status = altera_set_dr_post(&astate->js, count, index, + charptr_tmp); + break; + case OP_IPRA: + /* + * IRPRE with array data + * ...argument 0 is variable ID + * ...stack 0 is array index + * ...stack 1 is count + */ + if (!altera_check_stack(stack_ptr, 2, &status)) + break; + index = stack[--stack_ptr]; + count = stack[--stack_ptr]; + + if (version > 0) + /* + * stack 0 = array right index + * stack 1 = array left index + */ + count = 1 + count - index; + + charptr_tmp = (u8 *)vars[args[0]]; + status = altera_set_ir_pre(&astate->js, count, index, + charptr_tmp); + + break; + case OP_IPOA: + /* + * IRPOST with array data + * ...argument 0 is variable ID + * ...stack 0 is array index + * ...stack 1 is count + */ + if (!altera_check_stack(stack_ptr, 2, &status)) + break; + index = stack[--stack_ptr]; + count = stack[--stack_ptr]; + + if (version > 0) + /* + * stack 0 = array right index + * stack 1 = array left index + */ + count = 1 + count - index; + + charptr_tmp = (u8 *)vars[args[0]]; + status = altera_set_ir_post(&astate->js, count, index, + charptr_tmp); + + break; + case OP_EXPT: + /* + * EXPORT + * ...argument 0 is string ID + * ...stack 0 is integer expression + */ + if (altera_check_stack(stack_ptr, 1, &status)) { + name = &p[str_table + args[0]]; + long_tmp = stack[--stack_ptr]; + altera_export_int(name, long_tmp); + } + break; + case OP_PSHE: + /* + * Push integer array element + * ...argument 0 is variable ID + * ...stack 0 is array index + */ + if (!altera_check_stack(stack_ptr, 1, &status)) + break; + variable_id = args[0]; + index = stack[stack_ptr - 1]; + + /* check variable type */ + if ((attrs[variable_id] & 0x1f) == 0x19) { + /* writable integer array */ + longptr_tmp = (long *)vars[variable_id]; + stack[stack_ptr - 1] = longptr_tmp[index]; + } else if ((attrs[variable_id] & 0x1f) == 0x1c) { + /* read-only integer array */ + long_tmp = vars[variable_id] + + (index * sizeof(long)); + stack[stack_ptr - 1] = + get_unaligned_be32(&p[long_tmp]); + } else + status = -ERANGE; + + break; + case OP_PSHA: + /* + * Push Boolean array + * ...argument 0 is variable ID + * ...stack 0 is count + * ...stack 1 is array index + */ + if (!altera_check_stack(stack_ptr, 2, &status)) + break; + variable_id = args[0]; + + /* check that variable is a Boolean array */ + if ((attrs[variable_id] & 0x18) != 0x08) { + status = -ERANGE; + break; + } + + charptr_tmp = (u8 *)vars[variable_id]; + + /* pop the count (number of bits to copy) */ + count = stack[--stack_ptr]; + + /* pop the array index */ + index = stack[stack_ptr - 1]; + + if (version > 0) + /* + * stack 0 = array right index + * stack 1 = array left index + */ + count = 1 + count - index; + + if ((count < 1) || (count > 32)) { + status = -ERANGE; + break; + } + + long_tmp = 0L; + + for (i = 0; i < count; ++i) + if (charptr_tmp[(i + index) >> 3] & + (1 << ((i + index) & 7))) + long_tmp |= (1L << i); + + stack[stack_ptr - 1] = long_tmp; + + break; + case OP_DYNA: + /* + * Dynamically change size of array + * ...argument 0 is variable ID + * ...stack 0 is new size + */ + if (!altera_check_stack(stack_ptr, 1, &status)) + break; + variable_id = args[0]; + long_tmp = stack[--stack_ptr]; + + if (long_tmp > var_size[variable_id]) { + var_size[variable_id] = long_tmp; + + if (attrs[variable_id] & 0x10) + /* allocate integer array */ + long_tmp *= sizeof(long); + else + /* allocate Boolean array */ + long_tmp = (long_tmp + 7) >> 3; + + /* + * If the buffer was previously allocated, + * free it + */ + if (attrs[variable_id] & 0x80) { + kfree((void *)vars[variable_id]); + vars[variable_id] = 0; + } + + /* + * Allocate a new buffer + * of the requested size + */ + vars[variable_id] = (long) + kzalloc(long_tmp, GFP_KERNEL); + + if (vars[variable_id] == 0) { + status = -ENOMEM; + break; + } + + /* + * Set the attribute bit to indicate that + * this buffer was dynamically allocated and + * should be freed later + */ + attrs[variable_id] |= 0x80; + + /* zero out memory */ + count = ((var_size[variable_id] + 7L) / + 8L); + charptr_tmp = (u8 *)(vars[variable_id]); + for (index = 0; index < count; ++index) + charptr_tmp[index] = 0; + + } + + break; + case OP_EXPV: + /* + * Export Boolean array + * ...argument 0 is string ID + * ...stack 0 is variable ID + * ...stack 1 is array right index + * ...stack 2 is array left index + */ + if (!altera_check_stack(stack_ptr, 3, &status)) + break; + if (version == 0) { + /* EXPV is not supported in JBC 1.0 */ + bad_opcode = 1; + break; + } + name = &p[str_table + args[0]]; + variable_id = stack[--stack_ptr]; + long_idx = stack[--stack_ptr];/* right indx */ + long_idx2 = stack[--stack_ptr];/* left indx */ + + if (long_idx > long_idx2) { + /* reverse indices not supported */ + status = -ERANGE; + break; + } + + long_count = 1 + long_idx2 - long_idx; + + charptr_tmp = (u8 *)vars[variable_id]; + charptr_tmp2 = NULL; + + if ((long_idx & 7L) != 0) { + s32 k = long_idx; + charptr_tmp2 = + kzalloc(((long_count + 7L) / 8L), + GFP_KERNEL); + if (charptr_tmp2 == NULL) { + status = -ENOMEM; + break; + } + + for (i = 0; i < long_count; ++i) { + if (charptr_tmp[k >> 3] & + (1 << (k & 7))) + charptr_tmp2[i >> 3] |= + (1 << (i & 7)); + else + charptr_tmp2[i >> 3] &= + ~(1 << (i & 7)); + + ++k; + } + charptr_tmp = charptr_tmp2; + + } else if (long_idx != 0) + charptr_tmp = &charptr_tmp[long_idx >> 3]; + + altera_export_bool_array(name, charptr_tmp, + long_count); + + /* free allocated buffer */ + if ((long_idx & 7L) != 0) + kfree(charptr_tmp2); + + break; + case OP_COPY: { + /* + * Array copy + * ...argument 0 is dest ID + * ...argument 1 is source ID + * ...stack 0 is count + * ...stack 1 is dest index + * ...stack 2 is source index + */ + s32 copy_count; + s32 copy_index; + s32 copy_index2; + s32 destleft; + s32 src_count; + s32 dest_count; + int src_reverse = 0; + int dest_reverse = 0; + + if (!altera_check_stack(stack_ptr, 3, &status)) + break; + + copy_count = stack[--stack_ptr]; + copy_index = stack[--stack_ptr]; + copy_index2 = stack[--stack_ptr]; + reverse = 0; + + if (version > 0) { + /* + * stack 0 = source right index + * stack 1 = source left index + * stack 2 = destination right index + * stack 3 = destination left index + */ + destleft = stack[--stack_ptr]; + + if (copy_count > copy_index) { + src_reverse = 1; + reverse = 1; + src_count = 1 + copy_count - copy_index; + /* copy_index = source start index */ + } else { + src_count = 1 + copy_index - copy_count; + /* source start index */ + copy_index = copy_count; + } + + if (copy_index2 > destleft) { + dest_reverse = 1; + reverse = !reverse; + dest_count = 1 + copy_index2 - destleft; + /* destination start index */ + copy_index2 = destleft; + } else + dest_count = 1 + destleft - copy_index2; + + copy_count = (src_count < dest_count) ? + src_count : dest_count; + + if ((src_reverse || dest_reverse) && + (src_count != dest_count)) + /* + * If either the source or destination + * is reversed, we can't tolerate + * a length mismatch, because we + * "left justify" arrays when copying. + * This won't work correctly + * with reversed arrays. + */ + status = -ERANGE; + + } + + count = copy_count; + index = copy_index; + index2 = copy_index2; + + /* + * If destination is a read-only array, + * allocate a buffer and convert it to a writable array + */ + variable_id = args[1]; + if ((version > 0) && + ((attrs[variable_id] & 0x9c) == 0x0c)) { + /* Allocate a writable buffer for this array */ + long_tmp = + (var_size[variable_id] + 7L) >> 3L; + charptr_tmp2 = (u8 *)vars[variable_id]; + charptr_tmp = + kzalloc(long_tmp, GFP_KERNEL); + vars[variable_id] = (long)charptr_tmp; + + if (vars[variable_id] == 0) { + status = -ENOMEM; + break; + } + + /* zero the buffer */ + for (long_idx = 0L; long_idx < long_tmp; + ++long_idx) + charptr_tmp[long_idx] = 0; + + /* copy previous contents into buffer */ + for (long_idx = 0L; + long_idx < var_size[variable_id]; + ++long_idx) { + long_idx2 = long_idx; + + if (charptr_tmp2[long_idx2 >> 3] & + (1 << (long_idx2 & 7))) + charptr_tmp[long_idx >> 3] |= + (1 << (long_idx & 7)); + + } + + /* + set bit 7 - buffer was dynamically allocated */ + attrs[variable_id] |= 0x80; + + /* clear bit 2 - variable is writable */ + attrs[variable_id] &= ~0x04; + attrs[variable_id] |= 0x01; + } + + charptr_tmp = (u8 *)vars[args[1]]; + charptr_tmp2 = (u8 *)vars[args[0]]; + + /* check if destination is a writable Boolean array */ + if ((attrs[args[1]] & 0x1c) != 0x08) { + status = -ERANGE; + break; + } + + if (count < 1) { + status = -ERANGE; + break; + } + + if (reverse) + index2 += (count - 1); + + for (i = 0; i < count; ++i) { + if (charptr_tmp2[index >> 3] & + (1 << (index & 7))) + charptr_tmp[index2 >> 3] |= + (1 << (index2 & 7)); + else + charptr_tmp[index2 >> 3] &= + ~(1 << (index2 & 7)); + + ++index; + if (reverse) + --index2; + else + ++index2; + } + + break; + } + case OP_DSC: + case OP_ISC: { + /* + * DRSCAN with capture + * IRSCAN with capture + * ...argument 0 is scan data variable ID + * ...argument 1 is capture variable ID + * ...stack 0 is capture index + * ...stack 1 is scan data index + * ...stack 2 is count + */ + s32 scan_right, scan_left; + s32 capture_count = 0; + s32 scan_count = 0; + s32 capture_index; + s32 scan_index; + + if (!altera_check_stack(stack_ptr, 3, &status)) + break; + + capture_index = stack[--stack_ptr]; + scan_index = stack[--stack_ptr]; + + if (version > 0) { + /* + * stack 0 = capture right index + * stack 1 = capture left index + * stack 2 = scan right index + * stack 3 = scan left index + * stack 4 = count + */ + scan_right = stack[--stack_ptr]; + scan_left = stack[--stack_ptr]; + capture_count = 1 + scan_index - capture_index; + scan_count = 1 + scan_left - scan_right; + scan_index = scan_right; + } + + long_count = stack[--stack_ptr]; + /* + * If capture array is read-only, allocate a buffer + * and convert it to a writable array + */ + variable_id = args[1]; + if ((version > 0) && + ((attrs[variable_id] & 0x9c) == 0x0c)) { + /* Allocate a writable buffer for this array */ + long_tmp = + (var_size[variable_id] + 7L) >> 3L; + charptr_tmp2 = (u8 *)vars[variable_id]; + charptr_tmp = + kzalloc(long_tmp, GFP_KERNEL); + vars[variable_id] = (long)charptr_tmp; + + if (vars[variable_id] == 0) { + status = -ENOMEM; + break; + } + + /* zero the buffer */ + for (long_idx = 0L; long_idx < long_tmp; + ++long_idx) + charptr_tmp[long_idx] = 0; + + /* copy previous contents into buffer */ + for (long_idx = 0L; + long_idx < var_size[variable_id]; + ++long_idx) { + long_idx2 = long_idx; + + if (charptr_tmp2[long_idx2 >> 3] & + (1 << (long_idx2 & 7))) + charptr_tmp[long_idx >> 3] |= + (1 << (long_idx & 7)); + + } + + /* + * set bit 7 - buffer was + * dynamically allocated + */ + attrs[variable_id] |= 0x80; + + /* clear bit 2 - variable is writable */ + attrs[variable_id] &= ~0x04; + attrs[variable_id] |= 0x01; + + } + + charptr_tmp = (u8 *)vars[args[0]]; + charptr_tmp2 = (u8 *)vars[args[1]]; + + if ((version > 0) && + ((long_count > capture_count) || + (long_count > scan_count))) { + status = -ERANGE; + break; + } + + /* + * check that capture array + * is a writable Boolean array + */ + if ((attrs[args[1]] & 0x1c) != 0x08) { + status = -ERANGE; + break; + } + + if (status == 0) { + if (opcode == 0x82) /* DSC */ + status = altera_swap_dr(astate, + long_count, + charptr_tmp, + scan_index, + charptr_tmp2, + capture_index); + else /* ISC */ + status = altera_swap_ir(astate, + long_count, + charptr_tmp, + scan_index, + charptr_tmp2, + capture_index); + + } + + break; + } + case OP_WAIT: + /* + * WAIT + * ...argument 0 is wait state + * ...argument 1 is end state + * ...stack 0 is cycles + * ...stack 1 is microseconds + */ + if (!altera_check_stack(stack_ptr, 2, &status)) + break; + long_tmp = stack[--stack_ptr]; + + if (long_tmp != 0L) + status = altera_wait_cycles(astate, long_tmp, + args[0]); + + long_tmp = stack[--stack_ptr]; + + if ((status == 0) && (long_tmp != 0L)) + status = altera_wait_msecs(astate, + long_tmp, + args[0]); + + if ((status == 0) && (args[1] != args[0])) + status = altera_goto_jstate(astate, + args[1]); + + if (version > 0) { + --stack_ptr; /* throw away MAX cycles */ + --stack_ptr; /* throw away MAX microseconds */ + } + break; + case OP_CMPA: { + /* + * Array compare + * ...argument 0 is source 1 ID + * ...argument 1 is source 2 ID + * ...argument 2 is mask ID + * ...stack 0 is source 1 index + * ...stack 1 is source 2 index + * ...stack 2 is mask index + * ...stack 3 is count + */ + s32 a, b; + u8 *source1 = (u8 *)vars[args[0]]; + u8 *source2 = (u8 *)vars[args[1]]; + u8 *mask = (u8 *)vars[args[2]]; + u32 index1; + u32 index2; + u32 mask_index; + + if (!altera_check_stack(stack_ptr, 4, &status)) + break; + + index1 = stack[--stack_ptr]; + index2 = stack[--stack_ptr]; + mask_index = stack[--stack_ptr]; + long_count = stack[--stack_ptr]; + + if (version > 0) { + /* + * stack 0 = source 1 right index + * stack 1 = source 1 left index + * stack 2 = source 2 right index + * stack 3 = source 2 left index + * stack 4 = mask right index + * stack 5 = mask left index + */ + s32 mask_right = stack[--stack_ptr]; + s32 mask_left = stack[--stack_ptr]; + /* source 1 count */ + a = 1 + index2 - index1; + /* source 2 count */ + b = 1 + long_count - mask_index; + a = (a < b) ? a : b; + /* mask count */ + b = 1 + mask_left - mask_right; + a = (a < b) ? a : b; + /* source 2 start index */ + index2 = mask_index; + /* mask start index */ + mask_index = mask_right; + long_count = a; + } + + long_tmp = 1L; + + if (long_count < 1) + status = -ERANGE; + else { + count = long_count; + + for (i = 0; i < count; ++i) { + if (mask[mask_index >> 3] & + (1 << (mask_index & 7))) { + a = source1[index1 >> 3] & + (1 << (index1 & 7)) + ? 1 : 0; + b = source2[index2 >> 3] & + (1 << (index2 & 7)) + ? 1 : 0; + + if (a != b) /* failure */ + long_tmp = 0L; + } + ++index1; + ++index2; + ++mask_index; + } + } + + stack[stack_ptr++] = long_tmp; + + break; + } + default: + /* Unrecognized opcode -- ERROR! */ + bad_opcode = 1; + break; + } + + if (bad_opcode) + status = -ENOSYS; + + if ((stack_ptr < 0) || (stack_ptr >= ALTERA_STACK_SIZE)) + status = -EOVERFLOW; + + if (status != 0) { + done = 1; + *error_address = (s32)(opcode_address - code_sect); + } + } + + altera_free_buffers(astate); + + /* Free all dynamically allocated arrays */ + if ((attrs != NULL) && (vars != NULL)) + for (i = 0; i < sym_count; ++i) + if (attrs[i] & 0x80) + kfree((void *)vars[i]); + + kfree(vars); + kfree(var_size); + kfree(attrs); + kfree(proc_attributes); + + return status; +} + +static int altera_get_note(u8 *p, s32 program_size, + s32 *offset, char *key, char *value, int length) +/* + * Gets key and value of NOTE fields in the JBC file. + * Can be called in two modes: if offset pointer is NULL, + * then the function searches for note fields which match + * the key string provided. If offset is not NULL, then + * the function finds the next note field of any key, + * starting at the offset specified by the offset pointer. + * Returns 0 for success, else appropriate error code + */ +{ + int status = -ENODATA; + u32 note_strings = 0L; + u32 note_table = 0L; + u32 note_count = 0L; + u32 first_word = 0L; + int version = 0; + int delta = 0; + char *key_ptr; + char *value_ptr; + int i; + + /* Read header information */ + if (program_size > 52L) { + first_word = get_unaligned_be32(&p[0]); + version = (first_word & 1L); + delta = version * 8; + + note_strings = get_unaligned_be32(&p[8 + delta]); + note_table = get_unaligned_be32(&p[12 + delta]); + note_count = get_unaligned_be32(&p[44 + (2 * delta)]); + } + + if ((first_word != 0x4A414D00L) && (first_word != 0x4A414D01L)) + return -EIO; + + if (note_count <= 0L) + return status; + + if (offset == NULL) { + /* + * We will search for the first note with a specific key, + * and return only the value + */ + for (i = 0; (i < note_count) && + (status != 0); ++i) { + key_ptr = &p[note_strings + + get_unaligned_be32( + &p[note_table + (8 * i)])]; + if ((strnicmp(key, key_ptr, strlen(key_ptr)) == 0) && + (key != NULL)) { + status = 0; + + value_ptr = &p[note_strings + + get_unaligned_be32( + &p[note_table + (8 * i) + 4])]; + + if (value != NULL) + strlcpy(value, value_ptr, length); + + } + } + } else { + /* + * We will search for the next note, regardless of the key, + * and return both the value and the key + */ + + i = *offset; + + if ((i >= 0) && (i < note_count)) { + status = 0; + + if (key != NULL) + strlcpy(key, &p[note_strings + + get_unaligned_be32( + &p[note_table + (8 * i)])], + length); + + if (value != NULL) + strlcpy(value, &p[note_strings + + get_unaligned_be32( + &p[note_table + (8 * i) + 4])], + length); + + *offset = i + 1; + } + } + + return status; +} + +static int altera_check_crc(u8 *p, s32 program_size) +{ + int status = 0; + u16 local_expected = 0, + local_actual = 0, + shift_reg = 0xffff; + int bit, feedback; + u8 databyte; + u32 i; + u32 crc_section = 0L; + u32 first_word = 0L; + int version = 0; + int delta = 0; + + if (program_size > 52L) { + first_word = get_unaligned_be32(&p[0]); + version = (first_word & 1L); + delta = version * 8; + + crc_section = get_unaligned_be32(&p[32 + delta]); + } + + if ((first_word != 0x4A414D00L) && (first_word != 0x4A414D01L)) + status = -EIO; + + if (crc_section >= program_size) + status = -EIO; + + if (status == 0) { + local_expected = (u16)get_unaligned_be16(&p[crc_section]); + + for (i = 0; i < crc_section; ++i) { + databyte = p[i]; + for (bit = 0; bit < 8; bit++) { + feedback = (databyte ^ shift_reg) & 0x01; + shift_reg >>= 1; + if (feedback) + shift_reg ^= 0x8408; + + databyte >>= 1; + } + } + + local_actual = (u16)~shift_reg; + + if (local_expected != local_actual) + status = -EILSEQ; + + } + + if (debug || status) { + switch (status) { + case 0: + printk(KERN_INFO "%s: CRC matched: %04x\n", __func__, + local_actual); + break; + case -EILSEQ: + printk(KERN_ERR "%s: CRC mismatch: expected %04x, " + "actual %04x\n", __func__, local_expected, + local_actual); + break; + case -ENODATA: + printk(KERN_ERR "%s: expected CRC not found, " + "actual CRC = %04x\n", __func__, + local_actual); + break; + case -EIO: + printk(KERN_ERR "%s: error: format isn't " + "recognized.\n", __func__); + break; + default: + printk(KERN_ERR "%s: CRC function returned error " + "code %d\n", __func__, status); + break; + } + } + + return status; +} + +static int altera_get_file_info(u8 *p, + s32 program_size, + int *format_version, + int *action_count, + int *procedure_count) +{ + int status = -EIO; + u32 first_word = 0; + int version = 0; + + if (program_size <= 52L) + return status; + + first_word = get_unaligned_be32(&p[0]); + + if ((first_word == 0x4A414D00L) || (first_word == 0x4A414D01L)) { + status = 0; + + version = (first_word & 1L); + *format_version = version + 1; + + if (version > 0) { + *action_count = get_unaligned_be32(&p[48]); + *procedure_count = get_unaligned_be32(&p[52]); + } + } + + return status; +} + +static int altera_get_act_info(u8 *p, + s32 program_size, + int index, + char **name, + char **description, + struct altera_procinfo **proc_list) +{ + int status = -EIO; + struct altera_procinfo *procptr = NULL; + struct altera_procinfo *tmpptr = NULL; + u32 first_word = 0L; + u32 action_table = 0L; + u32 proc_table = 0L; + u32 str_table = 0L; + u32 note_strings = 0L; + u32 action_count = 0L; + u32 proc_count = 0L; + u32 act_name_id = 0L; + u32 act_desc_id = 0L; + u32 act_proc_id = 0L; + u32 act_proc_name = 0L; + u8 act_proc_attribute = 0; + + if (program_size <= 52L) + return status; + /* Read header information */ + first_word = get_unaligned_be32(&p[0]); + + if (first_word != 0x4A414D01L) + return status; + + action_table = get_unaligned_be32(&p[4]); + proc_table = get_unaligned_be32(&p[8]); + str_table = get_unaligned_be32(&p[12]); + note_strings = get_unaligned_be32(&p[16]); + action_count = get_unaligned_be32(&p[48]); + proc_count = get_unaligned_be32(&p[52]); + + if (index >= action_count) + return status; + + act_name_id = get_unaligned_be32(&p[action_table + (12 * index)]); + act_desc_id = get_unaligned_be32(&p[action_table + (12 * index) + 4]); + act_proc_id = get_unaligned_be32(&p[action_table + (12 * index) + 8]); + + *name = &p[str_table + act_name_id]; + + if (act_desc_id < (note_strings - str_table)) + *description = &p[str_table + act_desc_id]; + + do { + act_proc_name = get_unaligned_be32( + &p[proc_table + (13 * act_proc_id)]); + act_proc_attribute = + (p[proc_table + (13 * act_proc_id) + 8] & 0x03); + + procptr = (struct altera_procinfo *) + kzalloc(sizeof(struct altera_procinfo), + GFP_KERNEL); + + if (procptr == NULL) + status = -ENOMEM; + else { + procptr->name = &p[str_table + act_proc_name]; + procptr->attrs = act_proc_attribute; + procptr->next = NULL; + + /* add record to end of linked list */ + if (*proc_list == NULL) + *proc_list = procptr; + else { + tmpptr = *proc_list; + while (tmpptr->next != NULL) + tmpptr = tmpptr->next; + tmpptr->next = procptr; + } + } + + act_proc_id = get_unaligned_be32( + &p[proc_table + (13 * act_proc_id) + 4]); + } while ((act_proc_id != 0) && (act_proc_id < proc_count)); + + return status; +} + +int altera_init(struct altera_config *config, const struct firmware *fw) +{ + struct altera_state *astate = NULL; + struct altera_procinfo *proc_list = NULL; + struct altera_procinfo *procptr = NULL; + char *key = NULL; + char *value = NULL; + char *action_name = NULL; + char *description = NULL; + int exec_result = 0; + int exit_code = 0; + int format_version = 0; + int action_count = 0; + int procedure_count = 0; + int index = 0; + s32 offset = 0L; + s32 error_address = 0L; + int retval = 0; + + key = kzalloc(33, GFP_KERNEL); + if (!key) { + retval = -ENOMEM; + goto out; + } + value = kzalloc(257, GFP_KERNEL); + if (!value) { + retval = -ENOMEM; + goto free_key; + } + astate = kzalloc(sizeof(struct altera_state), GFP_KERNEL); + if (!astate) { + retval = -ENOMEM; + goto free_value; + } + + astate->config = config; + if (!astate->config->jtag_io) { + dprintk(KERN_INFO "%s: using byteblaster!\n", __func__); + astate->config->jtag_io = netup_jtag_io_lpt; + } + + altera_check_crc((u8 *)fw->data, fw->size); + + if (debug) { + altera_get_file_info((u8 *)fw->data, fw->size, &format_version, + &action_count, &procedure_count); + printk(KERN_INFO "%s: File format is %s ByteCode format\n", + __func__, (format_version == 2) ? "Jam STAPL" : + "pre-standardized Jam 1.1"); + while (altera_get_note((u8 *)fw->data, fw->size, + &offset, key, value, 256) == 0) + printk(KERN_INFO "%s: NOTE \"%s\" = \"%s\"\n", + __func__, key, value); + } + + if (debug && (format_version == 2) && (action_count > 0)) { + printk(KERN_INFO "%s: Actions available:\n", __func__); + for (index = 0; index < action_count; ++index) { + altera_get_act_info((u8 *)fw->data, fw->size, + index, &action_name, + &description, + &proc_list); + + if (description == NULL) + printk(KERN_INFO "%s: %s\n", + __func__, + action_name); + else + printk(KERN_INFO "%s: %s \"%s\"\n", + __func__, + action_name, + description); + + procptr = proc_list; + while (procptr != NULL) { + if (procptr->attrs != 0) + printk(KERN_INFO "%s: %s (%s)\n", + __func__, + procptr->name, + (procptr->attrs == 1) ? + "optional" : "recommended"); + + proc_list = procptr->next; + kfree(procptr); + procptr = proc_list; + } + } + + printk(KERN_INFO "\n"); + } + + exec_result = altera_execute(astate, (u8 *)fw->data, fw->size, + &error_address, &exit_code, &format_version); + + if (exit_code) + exec_result = -EREMOTEIO; + + if ((format_version == 2) && (exec_result == -EINVAL)) { + if (astate->config->action == NULL) + printk(KERN_ERR "%s: error: no action specified for " + "Jam STAPL file.\nprogram terminated.\n", + __func__); + else + printk(KERN_ERR "%s: error: action \"%s\"" + " is not supported " + "for this Jam STAPL file.\n" + "Program terminated.\n", __func__, + astate->config->action); + + } else if (exec_result) + printk(KERN_ERR "%s: error %d\n", __func__, exec_result); + + kfree(astate); +free_value: + kfree(value); +free_key: + kfree(key); +out: + return retval; +} +EXPORT_SYMBOL(altera_init); diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig index 720927742eb..e9aa6889270 100644 --- a/drivers/staging/Kconfig +++ b/drivers/staging/Kconfig @@ -142,8 +142,6 @@ source "drivers/staging/ste_rmi4/Kconfig" source "drivers/staging/gma500/Kconfig" -source "drivers/staging/altera-stapl/Kconfig" - source "drivers/staging/mei/Kconfig" source "drivers/staging/nvec/Kconfig" diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile index d44d25ed6cf..a2e77cf1dcb 100644 --- a/drivers/staging/Makefile +++ b/drivers/staging/Makefile @@ -59,7 +59,6 @@ obj-$(CONFIG_BCM_WIMAX) += bcm/ obj-$(CONFIG_FT1000) += ft1000/ obj-$(CONFIG_SND_INTEL_SST) += intel_sst/ obj-$(CONFIG_SPEAKUP) += speakup/ -obj-$(CONFIG_ALTERA_STAPL) +=altera-stapl/ obj-$(CONFIG_TOUCHSCREEN_CLEARPAD_TM1217) += cptm1217/ obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4) += ste_rmi4/ obj-$(CONFIG_DRM_PSB) += gma500/ diff --git a/drivers/staging/altera-stapl/Kconfig b/drivers/staging/altera-stapl/Kconfig deleted file mode 100644 index b6537321ed7..00000000000 --- a/drivers/staging/altera-stapl/Kconfig +++ /dev/null @@ -1,6 +0,0 @@ -config ALTERA_STAPL - tristate "Altera FPGA firmware download module" - depends on I2C - default n - help - An Altera FPGA module. Say Y when you want to support this tool. diff --git a/drivers/staging/altera-stapl/Makefile b/drivers/staging/altera-stapl/Makefile deleted file mode 100644 index ddeede3c4b9..00000000000 --- a/drivers/staging/altera-stapl/Makefile +++ /dev/null @@ -1,3 +0,0 @@ -altera-stapl-y := altera-lpt.o altera-jtag.o altera-comp.o altera.o - -obj-$(CONFIG_ALTERA_STAPL) += altera-stapl.o diff --git a/drivers/staging/altera-stapl/altera-comp.c b/drivers/staging/altera-stapl/altera-comp.c deleted file mode 100644 index 49b103bedaa..00000000000 --- a/drivers/staging/altera-stapl/altera-comp.c +++ /dev/null @@ -1,142 +0,0 @@ -/* - * altera-comp.c - * - * altera FPGA driver - * - * Copyright (C) Altera Corporation 1998-2001 - * Copyright (C) 2010 NetUP Inc. - * Copyright (C) 2010 Igor M. Liplianin - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include "altera-exprt.h" - -#define SHORT_BITS 16 -#define CHAR_BITS 8 -#define DATA_BLOB_LENGTH 3 -#define MATCH_DATA_LENGTH 8192 -#define ALTERA_REQUEST_SIZE 1024 -#define ALTERA_BUFFER_SIZE (MATCH_DATA_LENGTH + ALTERA_REQUEST_SIZE) - -static u32 altera_bits_req(u32 n) -{ - u32 result = SHORT_BITS; - - if (n == 0) - result = 1; - else { - /* Look for the highest non-zero bit position */ - while ((n & (1 << (SHORT_BITS - 1))) == 0) { - n <<= 1; - --result; - } - } - - return result; -} - -static u32 altera_read_packed(u8 *buffer, u32 bits, u32 *bits_avail, - u32 *in_index) -{ - u32 result = 0; - u32 shift = 0; - u32 databyte = 0; - - while (bits > 0) { - databyte = buffer[*in_index]; - result |= (((databyte >> (CHAR_BITS - *bits_avail)) - & (0xff >> (CHAR_BITS - *bits_avail))) << shift); - - if (bits <= *bits_avail) { - result &= (0xffff >> (SHORT_BITS - (bits + shift))); - *bits_avail -= bits; - bits = 0; - } else { - ++(*in_index); - shift += *bits_avail; - bits -= *bits_avail; - *bits_avail = CHAR_BITS; - } - } - - return result; -} - -u32 altera_shrink(u8 *in, u32 in_length, u8 *out, u32 out_length, s32 version) -{ - u32 i, j, data_length = 0L; - u32 offset, length; - u32 match_data_length = MATCH_DATA_LENGTH; - u32 bits_avail = CHAR_BITS; - u32 in_index = 0L; - - if (version > 0) - --match_data_length; - - for (i = 0; i < out_length; ++i) - out[i] = 0; - - /* Read number of bytes in data. */ - for (i = 0; i < sizeof(in_length); ++i) { - data_length = data_length | ( - altera_read_packed(in, - CHAR_BITS, - &bits_avail, - &in_index) << (i * CHAR_BITS)); - } - - if (data_length > out_length) { - data_length = 0L; - return data_length; - } - - i = 0; - while (i < data_length) { - /* A 0 bit indicates literal data. */ - if (altera_read_packed(in, 1, &bits_avail, - &in_index) == 0) { - for (j = 0; j < DATA_BLOB_LENGTH; ++j) { - if (i < data_length) { - out[i] = (u8)altera_read_packed(in, - CHAR_BITS, - &bits_avail, - &in_index); - i++; - } - } - } else { - /* A 1 bit indicates offset/length to follow. */ - offset = altera_read_packed(in, altera_bits_req((s16) - (i > match_data_length ? - match_data_length : i)), - &bits_avail, - &in_index); - length = altera_read_packed(in, CHAR_BITS, - &bits_avail, - &in_index); - for (j = 0; j < length; ++j) { - if (i < data_length) { - out[i] = out[i - offset]; - i++; - } - } - } - } - - return data_length; -} diff --git a/drivers/staging/altera-stapl/altera-exprt.h b/drivers/staging/altera-stapl/altera-exprt.h deleted file mode 100644 index 39c38d84a67..00000000000 --- a/drivers/staging/altera-stapl/altera-exprt.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * altera-exprt.h - * - * altera FPGA driver - * - * Copyright (C) Altera Corporation 1998-2001 - * Copyright (C) 2010 NetUP Inc. - * Copyright (C) 2010 Igor M. Liplianin - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#ifndef ALTERA_EXPRT_H -#define ALTERA_EXPRT_H - - -u32 altera_shrink(u8 *in, u32 in_length, u8 *out, u32 out_length, s32 version); -int netup_jtag_io_lpt(void *device, int tms, int tdi, int read_tdo); - -#endif /* ALTERA_EXPRT_H */ diff --git a/drivers/staging/altera-stapl/altera-jtag.c b/drivers/staging/altera-stapl/altera-jtag.c deleted file mode 100644 index 8b1620b1b2d..00000000000 --- a/drivers/staging/altera-stapl/altera-jtag.c +++ /dev/null @@ -1,1021 +0,0 @@ -/* - * altera-jtag.c - * - * altera FPGA driver - * - * Copyright (C) Altera Corporation 1998-2001 - * Copyright (C) 2010 NetUP Inc. - * Copyright (C) 2010 Igor M. Liplianin - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include -#include -#include "altera.h" -#include "altera-exprt.h" -#include "altera-jtag.h" - -#define alt_jtag_io(a, b, c)\ - astate->config->jtag_io(astate->config->dev, a, b, c); - -#define alt_malloc(a) kzalloc(a, GFP_KERNEL); - -/* - * This structure shows, for each JTAG state, which state is reached after - * a single TCK clock cycle with TMS high or TMS low, respectively. This - * describes all possible state transitions in the JTAG state machine. - */ -struct altera_jtag_machine { - enum altera_jtag_state tms_high; - enum altera_jtag_state tms_low; -}; - -static const struct altera_jtag_machine altera_transitions[] = { - /* RESET */ { RESET, IDLE }, - /* IDLE */ { DRSELECT, IDLE }, - /* DRSELECT */ { IRSELECT, DRCAPTURE }, - /* DRCAPTURE */ { DREXIT1, DRSHIFT }, - /* DRSHIFT */ { DREXIT1, DRSHIFT }, - /* DREXIT1 */ { DRUPDATE, DRPAUSE }, - /* DRPAUSE */ { DREXIT2, DRPAUSE }, - /* DREXIT2 */ { DRUPDATE, DRSHIFT }, - /* DRUPDATE */ { DRSELECT, IDLE }, - /* IRSELECT */ { RESET, IRCAPTURE }, - /* IRCAPTURE */ { IREXIT1, IRSHIFT }, - /* IRSHIFT */ { IREXIT1, IRSHIFT }, - /* IREXIT1 */ { IRUPDATE, IRPAUSE }, - /* IRPAUSE */ { IREXIT2, IRPAUSE }, - /* IREXIT2 */ { IRUPDATE, IRSHIFT }, - /* IRUPDATE */ { DRSELECT, IDLE } -}; - -/* - * This table contains the TMS value to be used to take the NEXT STEP on - * the path to the desired state. The array index is the current state, - * and the bit position is the desired endstate. To find out which state - * is used as the intermediate state, look up the TMS value in the - * altera_transitions[] table. - */ -static const u16 altera_jtag_path_map[16] = { - /* RST RTI SDRS CDR SDR E1DR PDR E2DR */ - 0x0001, 0xFFFD, 0xFE01, 0xFFE7, 0xFFEF, 0xFF0F, 0xFFBF, 0xFFFF, - /* UDR SIRS CIR SIR E1IR PIR E2IR UIR */ - 0xFEFD, 0x0001, 0xF3FF, 0xF7FF, 0x87FF, 0xDFFF, 0xFFFF, 0x7FFD -}; - -/* Flag bits for alt_jtag_io() function */ -#define TMS_HIGH 1 -#define TMS_LOW 0 -#define TDI_HIGH 1 -#define TDI_LOW 0 -#define READ_TDO 1 -#define IGNORE_TDO 0 - -int altera_jinit(struct altera_state *astate) -{ - struct altera_jtag *js = &astate->js; - - /* initial JTAG state is unknown */ - js->jtag_state = ILLEGAL_JTAG_STATE; - - /* initialize to default state */ - js->drstop_state = IDLE; - js->irstop_state = IDLE; - js->dr_pre = 0; - js->dr_post = 0; - js->ir_pre = 0; - js->ir_post = 0; - js->dr_length = 0; - js->ir_length = 0; - - js->dr_pre_data = NULL; - js->dr_post_data = NULL; - js->ir_pre_data = NULL; - js->ir_post_data = NULL; - js->dr_buffer = NULL; - js->ir_buffer = NULL; - - return 0; -} - -int altera_set_drstop(struct altera_jtag *js, enum altera_jtag_state state) -{ - js->drstop_state = state; - - return 0; -} - -int altera_set_irstop(struct altera_jtag *js, enum altera_jtag_state state) -{ - js->irstop_state = state; - - return 0; -} - -int altera_set_dr_pre(struct altera_jtag *js, - u32 count, u32 start_index, - u8 *preamble_data) -{ - int status = 0; - u32 i; - u32 j; - - if (count > js->dr_pre) { - kfree(js->dr_pre_data); - js->dr_pre_data = (u8 *)alt_malloc((count + 7) >> 3); - if (js->dr_pre_data == NULL) - status = -ENOMEM; - else - js->dr_pre = count; - } else - js->dr_pre = count; - - if (status == 0) { - for (i = 0; i < count; ++i) { - j = i + start_index; - - if (preamble_data == NULL) - js->dr_pre_data[i >> 3] |= (1 << (i & 7)); - else { - if (preamble_data[j >> 3] & (1 << (j & 7))) - js->dr_pre_data[i >> 3] |= - (1 << (i & 7)); - else - js->dr_pre_data[i >> 3] &= - ~(u32)(1 << (i & 7)); - - } - } - } - - return status; -} - -int altera_set_ir_pre(struct altera_jtag *js, u32 count, u32 start_index, - u8 *preamble_data) -{ - int status = 0; - u32 i; - u32 j; - - if (count > js->ir_pre) { - kfree(js->ir_pre_data); - js->ir_pre_data = (u8 *)alt_malloc((count + 7) >> 3); - if (js->ir_pre_data == NULL) - status = -ENOMEM; - else - js->ir_pre = count; - - } else - js->ir_pre = count; - - if (status == 0) { - for (i = 0; i < count; ++i) { - j = i + start_index; - if (preamble_data == NULL) - js->ir_pre_data[i >> 3] |= (1 << (i & 7)); - else { - if (preamble_data[j >> 3] & (1 << (j & 7))) - js->ir_pre_data[i >> 3] |= - (1 << (i & 7)); - else - js->ir_pre_data[i >> 3] &= - ~(u32)(1 << (i & 7)); - - } - } - } - - return status; -} - -int altera_set_dr_post(struct altera_jtag *js, u32 count, u32 start_index, - u8 *postamble_data) -{ - int status = 0; - u32 i; - u32 j; - - if (count > js->dr_post) { - kfree(js->dr_post_data); - js->dr_post_data = (u8 *)alt_malloc((count + 7) >> 3); - - if (js->dr_post_data == NULL) - status = -ENOMEM; - else - js->dr_post = count; - - } else - js->dr_post = count; - - if (status == 0) { - for (i = 0; i < count; ++i) { - j = i + start_index; - - if (postamble_data == NULL) - js->dr_post_data[i >> 3] |= (1 << (i & 7)); - else { - if (postamble_data[j >> 3] & (1 << (j & 7))) - js->dr_post_data[i >> 3] |= - (1 << (i & 7)); - else - js->dr_post_data[i >> 3] &= - ~(u32)(1 << (i & 7)); - - } - } - } - - return status; -} - -int altera_set_ir_post(struct altera_jtag *js, u32 count, u32 start_index, - u8 *postamble_data) -{ - int status = 0; - u32 i; - u32 j; - - if (count > js->ir_post) { - kfree(js->ir_post_data); - js->ir_post_data = (u8 *)alt_malloc((count + 7) >> 3); - if (js->ir_post_data == NULL) - status = -ENOMEM; - else - js->ir_post = count; - - } else - js->ir_post = count; - - if (status != 0) - return status; - - for (i = 0; i < count; ++i) { - j = i + start_index; - - if (postamble_data == NULL) - js->ir_post_data[i >> 3] |= (1 << (i & 7)); - else { - if (postamble_data[j >> 3] & (1 << (j & 7))) - js->ir_post_data[i >> 3] |= (1 << (i & 7)); - else - js->ir_post_data[i >> 3] &= - ~(u32)(1 << (i & 7)); - - } - } - - return status; -} - -static void altera_jreset_idle(struct altera_state *astate) -{ - struct altera_jtag *js = &astate->js; - int i; - /* Go to Test Logic Reset (no matter what the starting state may be) */ - for (i = 0; i < 5; ++i) - alt_jtag_io(TMS_HIGH, TDI_LOW, IGNORE_TDO); - - /* Now step to Run Test / Idle */ - alt_jtag_io(TMS_LOW, TDI_LOW, IGNORE_TDO); - js->jtag_state = IDLE; -} - -int altera_goto_jstate(struct altera_state *astate, - enum altera_jtag_state state) -{ - struct altera_jtag *js = &astate->js; - int tms; - int count = 0; - int status = 0; - - if (js->jtag_state == ILLEGAL_JTAG_STATE) - /* initialize JTAG chain to known state */ - altera_jreset_idle(astate); - - if (js->jtag_state == state) { - /* - * We are already in the desired state. - * If it is a stable state, loop here. - * Otherwise do nothing (no clock cycles). - */ - if ((state == IDLE) || (state == DRSHIFT) || - (state == DRPAUSE) || (state == IRSHIFT) || - (state == IRPAUSE)) { - alt_jtag_io(TMS_LOW, TDI_LOW, IGNORE_TDO); - } else if (state == RESET) - alt_jtag_io(TMS_HIGH, TDI_LOW, IGNORE_TDO); - - } else { - while ((js->jtag_state != state) && (count < 9)) { - /* Get TMS value to take a step toward desired state */ - tms = (altera_jtag_path_map[js->jtag_state] & - (1 << state)) - ? TMS_HIGH : TMS_LOW; - - /* Take a step */ - alt_jtag_io(tms, TDI_LOW, IGNORE_TDO); - - if (tms) - js->jtag_state = - altera_transitions[js->jtag_state].tms_high; - else - js->jtag_state = - altera_transitions[js->jtag_state].tms_low; - - ++count; - } - } - - if (js->jtag_state != state) - status = -EREMOTEIO; - - return status; -} - -int altera_wait_cycles(struct altera_state *astate, - s32 cycles, - enum altera_jtag_state wait_state) -{ - struct altera_jtag *js = &astate->js; - int tms; - s32 count; - int status = 0; - - if (js->jtag_state != wait_state) - status = altera_goto_jstate(astate, wait_state); - - if (status == 0) { - /* - * Set TMS high to loop in RESET state - * Set TMS low to loop in any other stable state - */ - tms = (wait_state == RESET) ? TMS_HIGH : TMS_LOW; - - for (count = 0L; count < cycles; count++) - alt_jtag_io(tms, TDI_LOW, IGNORE_TDO); - - } - - return status; -} - -int altera_wait_msecs(struct altera_state *astate, - s32 microseconds, enum altera_jtag_state wait_state) -/* - * Causes JTAG hardware to sit in the specified stable - * state for the specified duration of real time. If - * no JTAG operations have been performed yet, then only - * a delay is performed. This permits the WAIT USECS - * statement to be used in VECTOR programs without causing - * any JTAG operations. - * Returns 0 for success, else appropriate error code. - */ -{ - struct altera_jtag *js = &astate->js; - int status = 0; - - if ((js->jtag_state != ILLEGAL_JTAG_STATE) && - (js->jtag_state != wait_state)) - status = altera_goto_jstate(astate, wait_state); - - if (status == 0) - /* Wait for specified time interval */ - udelay(microseconds); - - return status; -} - -static void altera_concatenate_data(u8 *buffer, - u8 *preamble_data, - u32 preamble_count, - u8 *target_data, - u32 start_index, - u32 target_count, - u8 *postamble_data, - u32 postamble_count) -/* - * Copies preamble data, target data, and postamble data - * into one buffer for IR or DR scans. - */ -{ - u32 i, j, k; - - for (i = 0L; i < preamble_count; ++i) { - if (preamble_data[i >> 3L] & (1L << (i & 7L))) - buffer[i >> 3L] |= (1L << (i & 7L)); - else - buffer[i >> 3L] &= ~(u32)(1L << (i & 7L)); - - } - - j = start_index; - k = preamble_count + target_count; - for (; i < k; ++i, ++j) { - if (target_data[j >> 3L] & (1L << (j & 7L))) - buffer[i >> 3L] |= (1L << (i & 7L)); - else - buffer[i >> 3L] &= ~(u32)(1L << (i & 7L)); - - } - - j = 0L; - k = preamble_count + target_count + postamble_count; - for (; i < k; ++i, ++j) { - if (postamble_data[j >> 3L] & (1L << (j & 7L))) - buffer[i >> 3L] |= (1L << (i & 7L)); - else - buffer[i >> 3L] &= ~(u32)(1L << (i & 7L)); - - } -} - -static int alt_jtag_drscan(struct altera_state *astate, - int start_state, - int count, - u8 *tdi, - u8 *tdo) -{ - int i = 0; - int tdo_bit = 0; - int status = 1; - - /* First go to DRSHIFT state */ - switch (start_state) { - case 0: /* IDLE */ - alt_jtag_io(1, 0, 0); /* DRSELECT */ - alt_jtag_io(0, 0, 0); /* DRCAPTURE */ - alt_jtag_io(0, 0, 0); /* DRSHIFT */ - break; - - case 1: /* DRPAUSE */ - alt_jtag_io(1, 0, 0); /* DREXIT2 */ - alt_jtag_io(1, 0, 0); /* DRUPDATE */ - alt_jtag_io(1, 0, 0); /* DRSELECT */ - alt_jtag_io(0, 0, 0); /* DRCAPTURE */ - alt_jtag_io(0, 0, 0); /* DRSHIFT */ - break; - - case 2: /* IRPAUSE */ - alt_jtag_io(1, 0, 0); /* IREXIT2 */ - alt_jtag_io(1, 0, 0); /* IRUPDATE */ - alt_jtag_io(1, 0, 0); /* DRSELECT */ - alt_jtag_io(0, 0, 0); /* DRCAPTURE */ - alt_jtag_io(0, 0, 0); /* DRSHIFT */ - break; - - default: - status = 0; - } - - if (status) { - /* loop in the SHIFT-DR state */ - for (i = 0; i < count; i++) { - tdo_bit = alt_jtag_io( - (i == count - 1), - tdi[i >> 3] & (1 << (i & 7)), - (tdo != NULL)); - - if (tdo != NULL) { - if (tdo_bit) - tdo[i >> 3] |= (1 << (i & 7)); - else - tdo[i >> 3] &= ~(u32)(1 << (i & 7)); - - } - } - - alt_jtag_io(0, 0, 0); /* DRPAUSE */ - } - - return status; -} - -static int alt_jtag_irscan(struct altera_state *astate, - int start_state, - int count, - u8 *tdi, - u8 *tdo) -{ - int i = 0; - int tdo_bit = 0; - int status = 1; - - /* First go to IRSHIFT state */ - switch (start_state) { - case 0: /* IDLE */ - alt_jtag_io(1, 0, 0); /* DRSELECT */ - alt_jtag_io(1, 0, 0); /* IRSELECT */ - alt_jtag_io(0, 0, 0); /* IRCAPTURE */ - alt_jtag_io(0, 0, 0); /* IRSHIFT */ - break; - - case 1: /* DRPAUSE */ - alt_jtag_io(1, 0, 0); /* DREXIT2 */ - alt_jtag_io(1, 0, 0); /* DRUPDATE */ - alt_jtag_io(1, 0, 0); /* DRSELECT */ - alt_jtag_io(1, 0, 0); /* IRSELECT */ - alt_jtag_io(0, 0, 0); /* IRCAPTURE */ - alt_jtag_io(0, 0, 0); /* IRSHIFT */ - break; - - case 2: /* IRPAUSE */ - alt_jtag_io(1, 0, 0); /* IREXIT2 */ - alt_jtag_io(1, 0, 0); /* IRUPDATE */ - alt_jtag_io(1, 0, 0); /* DRSELECT */ - alt_jtag_io(1, 0, 0); /* IRSELECT */ - alt_jtag_io(0, 0, 0); /* IRCAPTURE */ - alt_jtag_io(0, 0, 0); /* IRSHIFT */ - break; - - default: - status = 0; - } - - if (status) { - /* loop in the SHIFT-IR state */ - for (i = 0; i < count; i++) { - tdo_bit = alt_jtag_io( - (i == count - 1), - tdi[i >> 3] & (1 << (i & 7)), - (tdo != NULL)); - if (tdo != NULL) { - if (tdo_bit) - tdo[i >> 3] |= (1 << (i & 7)); - else - tdo[i >> 3] &= ~(u32)(1 << (i & 7)); - - } - } - - alt_jtag_io(0, 0, 0); /* IRPAUSE */ - } - - return status; -} - -static void altera_extract_target_data(u8 *buffer, - u8 *target_data, - u32 start_index, - u32 preamble_count, - u32 target_count) -/* - * Copies target data from scan buffer, filtering out - * preamble and postamble data. - */ -{ - u32 i; - u32 j; - u32 k; - - j = preamble_count; - k = start_index + target_count; - for (i = start_index; i < k; ++i, ++j) { - if (buffer[j >> 3] & (1 << (j & 7))) - target_data[i >> 3] |= (1 << (i & 7)); - else - target_data[i >> 3] &= ~(u32)(1 << (i & 7)); - - } -} - -int altera_irscan(struct altera_state *astate, - u32 count, - u8 *tdi_data, - u32 start_index) -/* Shifts data into instruction register */ -{ - struct altera_jtag *js = &astate->js; - int start_code = 0; - u32 alloc_chars = 0; - u32 shift_count = js->ir_pre + count + js->ir_post; - int status = 0; - enum altera_jtag_state start_state = ILLEGAL_JTAG_STATE; - - switch (js->jtag_state) { - case ILLEGAL_JTAG_STATE: - case RESET: - case IDLE: - start_code = 0; - start_state = IDLE; - break; - - case DRSELECT: - case DRCAPTURE: - case DRSHIFT: - case DREXIT1: - case DRPAUSE: - case DREXIT2: - case DRUPDATE: - start_code = 1; - start_state = DRPAUSE; - break; - - case IRSELECT: - case IRCAPTURE: - case IRSHIFT: - case IREXIT1: - case IRPAUSE: - case IREXIT2: - case IRUPDATE: - start_code = 2; - start_state = IRPAUSE; - break; - - default: - status = -EREMOTEIO; - break; - } - - if (status == 0) - if (js->jtag_state != start_state) - status = altera_goto_jstate(astate, start_state); - - if (status == 0) { - if (shift_count > js->ir_length) { - alloc_chars = (shift_count + 7) >> 3; - kfree(js->ir_buffer); - js->ir_buffer = (u8 *)alt_malloc(alloc_chars); - if (js->ir_buffer == NULL) - status = -ENOMEM; - else - js->ir_length = alloc_chars * 8; - - } - } - - if (status == 0) { - /* - * Copy preamble data, IR data, - * and postamble data into a buffer - */ - altera_concatenate_data(js->ir_buffer, - js->ir_pre_data, - js->ir_pre, - tdi_data, - start_index, - count, - js->ir_post_data, - js->ir_post); - /* Do the IRSCAN */ - alt_jtag_irscan(astate, - start_code, - shift_count, - js->ir_buffer, - NULL); - - /* alt_jtag_irscan() always ends in IRPAUSE state */ - js->jtag_state = IRPAUSE; - } - - if (status == 0) - if (js->irstop_state != IRPAUSE) - status = altera_goto_jstate(astate, js->irstop_state); - - - return status; -} - -int altera_swap_ir(struct altera_state *astate, - u32 count, - u8 *in_data, - u32 in_index, - u8 *out_data, - u32 out_index) -/* Shifts data into instruction register, capturing output data */ -{ - struct altera_jtag *js = &astate->js; - int start_code = 0; - u32 alloc_chars = 0; - u32 shift_count = js->ir_pre + count + js->ir_post; - int status = 0; - enum altera_jtag_state start_state = ILLEGAL_JTAG_STATE; - - switch (js->jtag_state) { - case ILLEGAL_JTAG_STATE: - case RESET: - case IDLE: - start_code = 0; - start_state = IDLE; - break; - - case DRSELECT: - case DRCAPTURE: - case DRSHIFT: - case DREXIT1: - case DRPAUSE: - case DREXIT2: - case DRUPDATE: - start_code = 1; - start_state = DRPAUSE; - break; - - case IRSELECT: - case IRCAPTURE: - case IRSHIFT: - case IREXIT1: - case IRPAUSE: - case IREXIT2: - case IRUPDATE: - start_code = 2; - start_state = IRPAUSE; - break; - - default: - status = -EREMOTEIO; - break; - } - - if (status == 0) - if (js->jtag_state != start_state) - status = altera_goto_jstate(astate, start_state); - - if (status == 0) { - if (shift_count > js->ir_length) { - alloc_chars = (shift_count + 7) >> 3; - kfree(js->ir_buffer); - js->ir_buffer = (u8 *)alt_malloc(alloc_chars); - if (js->ir_buffer == NULL) - status = -ENOMEM; - else - js->ir_length = alloc_chars * 8; - - } - } - - if (status == 0) { - /* - * Copy preamble data, IR data, - * and postamble data into a buffer - */ - altera_concatenate_data(js->ir_buffer, - js->ir_pre_data, - js->ir_pre, - in_data, - in_index, - count, - js->ir_post_data, - js->ir_post); - - /* Do the IRSCAN */ - alt_jtag_irscan(astate, - start_code, - shift_count, - js->ir_buffer, - js->ir_buffer); - - /* alt_jtag_irscan() always ends in IRPAUSE state */ - js->jtag_state = IRPAUSE; - } - - if (status == 0) - if (js->irstop_state != IRPAUSE) - status = altera_goto_jstate(astate, js->irstop_state); - - - if (status == 0) - /* Now extract the returned data from the buffer */ - altera_extract_target_data(js->ir_buffer, - out_data, out_index, - js->ir_pre, count); - - return status; -} - -int altera_drscan(struct altera_state *astate, - u32 count, - u8 *tdi_data, - u32 start_index) -/* Shifts data into data register (ignoring output data) */ -{ - struct altera_jtag *js = &astate->js; - int start_code = 0; - u32 alloc_chars = 0; - u32 shift_count = js->dr_pre + count + js->dr_post; - int status = 0; - enum altera_jtag_state start_state = ILLEGAL_JTAG_STATE; - - switch (js->jtag_state) { - case ILLEGAL_JTAG_STATE: - case RESET: - case IDLE: - start_code = 0; - start_state = IDLE; - break; - - case DRSELECT: - case DRCAPTURE: - case DRSHIFT: - case DREXIT1: - case DRPAUSE: - case DREXIT2: - case DRUPDATE: - start_code = 1; - start_state = DRPAUSE; - break; - - case IRSELECT: - case IRCAPTURE: - case IRSHIFT: - case IREXIT1: - case IRPAUSE: - case IREXIT2: - case IRUPDATE: - start_code = 2; - start_state = IRPAUSE; - break; - - default: - status = -EREMOTEIO; - break; - } - - if (status == 0) - if (js->jtag_state != start_state) - status = altera_goto_jstate(astate, start_state); - - if (status == 0) { - if (shift_count > js->dr_length) { - alloc_chars = (shift_count + 7) >> 3; - kfree(js->dr_buffer); - js->dr_buffer = (u8 *)alt_malloc(alloc_chars); - if (js->dr_buffer == NULL) - status = -ENOMEM; - else - js->dr_length = alloc_chars * 8; - - } - } - - if (status == 0) { - /* - * Copy preamble data, DR data, - * and postamble data into a buffer - */ - altera_concatenate_data(js->dr_buffer, - js->dr_pre_data, - js->dr_pre, - tdi_data, - start_index, - count, - js->dr_post_data, - js->dr_post); - /* Do the DRSCAN */ - alt_jtag_drscan(astate, start_code, shift_count, - js->dr_buffer, NULL); - /* alt_jtag_drscan() always ends in DRPAUSE state */ - js->jtag_state = DRPAUSE; - } - - if (status == 0) - if (js->drstop_state != DRPAUSE) - status = altera_goto_jstate(astate, js->drstop_state); - - return status; -} - -int altera_swap_dr(struct altera_state *astate, u32 count, - u8 *in_data, u32 in_index, - u8 *out_data, u32 out_index) -/* Shifts data into data register, capturing output data */ -{ - struct altera_jtag *js = &astate->js; - int start_code = 0; - u32 alloc_chars = 0; - u32 shift_count = js->dr_pre + count + js->dr_post; - int status = 0; - enum altera_jtag_state start_state = ILLEGAL_JTAG_STATE; - - switch (js->jtag_state) { - case ILLEGAL_JTAG_STATE: - case RESET: - case IDLE: - start_code = 0; - start_state = IDLE; - break; - - case DRSELECT: - case DRCAPTURE: - case DRSHIFT: - case DREXIT1: - case DRPAUSE: - case DREXIT2: - case DRUPDATE: - start_code = 1; - start_state = DRPAUSE; - break; - - case IRSELECT: - case IRCAPTURE: - case IRSHIFT: - case IREXIT1: - case IRPAUSE: - case IREXIT2: - case IRUPDATE: - start_code = 2; - start_state = IRPAUSE; - break; - - default: - status = -EREMOTEIO; - break; - } - - if (status == 0) - if (js->jtag_state != start_state) - status = altera_goto_jstate(astate, start_state); - - if (status == 0) { - if (shift_count > js->dr_length) { - alloc_chars = (shift_count + 7) >> 3; - kfree(js->dr_buffer); - js->dr_buffer = (u8 *)alt_malloc(alloc_chars); - - if (js->dr_buffer == NULL) - status = -ENOMEM; - else - js->dr_length = alloc_chars * 8; - - } - } - - if (status == 0) { - /* - * Copy preamble data, DR data, - * and postamble data into a buffer - */ - altera_concatenate_data(js->dr_buffer, - js->dr_pre_data, - js->dr_pre, - in_data, - in_index, - count, - js->dr_post_data, - js->dr_post); - - /* Do the DRSCAN */ - alt_jtag_drscan(astate, - start_code, - shift_count, - js->dr_buffer, - js->dr_buffer); - - /* alt_jtag_drscan() always ends in DRPAUSE state */ - js->jtag_state = DRPAUSE; - } - - if (status == 0) - if (js->drstop_state != DRPAUSE) - status = altera_goto_jstate(astate, js->drstop_state); - - if (status == 0) - /* Now extract the returned data from the buffer */ - altera_extract_target_data(js->dr_buffer, - out_data, - out_index, - js->dr_pre, - count); - - return status; -} - -void altera_free_buffers(struct altera_state *astate) -{ - struct altera_jtag *js = &astate->js; - /* If the JTAG interface was used, reset it to TLR */ - if (js->jtag_state != ILLEGAL_JTAG_STATE) - altera_jreset_idle(astate); - - kfree(js->dr_pre_data); - js->dr_pre_data = NULL; - - kfree(js->dr_post_data); - js->dr_post_data = NULL; - - kfree(js->dr_buffer); - js->dr_buffer = NULL; - - kfree(js->ir_pre_data); - js->ir_pre_data = NULL; - - kfree(js->ir_post_data); - js->ir_post_data = NULL; - - kfree(js->ir_buffer); - js->ir_buffer = NULL; -} diff --git a/drivers/staging/altera-stapl/altera-jtag.h b/drivers/staging/altera-stapl/altera-jtag.h deleted file mode 100644 index 2f97e36a2fb..00000000000 --- a/drivers/staging/altera-stapl/altera-jtag.h +++ /dev/null @@ -1,113 +0,0 @@ -/* - * altera-jtag.h - * - * altera FPGA driver - * - * Copyright (C) Altera Corporation 1998-2001 - * Copyright (C) 2010 NetUP Inc. - * Copyright (C) 2010 Igor M. Liplianin - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#ifndef ALTERA_JTAG_H -#define ALTERA_JTAG_H - -/* Function Prototypes */ -enum altera_jtag_state { - ILLEGAL_JTAG_STATE = -1, - RESET = 0, - IDLE = 1, - DRSELECT = 2, - DRCAPTURE = 3, - DRSHIFT = 4, - DREXIT1 = 5, - DRPAUSE = 6, - DREXIT2 = 7, - DRUPDATE = 8, - IRSELECT = 9, - IRCAPTURE = 10, - IRSHIFT = 11, - IREXIT1 = 12, - IRPAUSE = 13, - IREXIT2 = 14, - IRUPDATE = 15 - -}; - -struct altera_jtag { - /* Global variable to store the current JTAG state */ - enum altera_jtag_state jtag_state; - - /* Store current stop-state for DR and IR scan commands */ - enum altera_jtag_state drstop_state; - enum altera_jtag_state irstop_state; - - /* Store current padding values */ - u32 dr_pre; - u32 dr_post; - u32 ir_pre; - u32 ir_post; - u32 dr_length; - u32 ir_length; - u8 *dr_pre_data; - u8 *dr_post_data; - u8 *ir_pre_data; - u8 *ir_post_data; - u8 *dr_buffer; - u8 *ir_buffer; -}; - -#define ALTERA_STACK_SIZE 128 -#define ALTERA_MESSAGE_LENGTH 1024 - -struct altera_state { - struct altera_config *config; - struct altera_jtag js; - char msg_buff[ALTERA_MESSAGE_LENGTH + 1]; - long stack[ALTERA_STACK_SIZE]; -}; - -int altera_jinit(struct altera_state *astate); -int altera_set_drstop(struct altera_jtag *js, enum altera_jtag_state state); -int altera_set_irstop(struct altera_jtag *js, enum altera_jtag_state state); -int altera_set_dr_pre(struct altera_jtag *js, u32 count, u32 start_index, - u8 *preamble_data); -int altera_set_ir_pre(struct altera_jtag *js, u32 count, u32 start_index, - u8 *preamble_data); -int altera_set_dr_post(struct altera_jtag *js, u32 count, u32 start_index, - u8 *postamble_data); -int altera_set_ir_post(struct altera_jtag *js, u32 count, u32 start_index, - u8 *postamble_data); -int altera_goto_jstate(struct altera_state *astate, - enum altera_jtag_state state); -int altera_wait_cycles(struct altera_state *astate, s32 cycles, - enum altera_jtag_state wait_state); -int altera_wait_msecs(struct altera_state *astate, s32 microseconds, - enum altera_jtag_state wait_state); -int altera_irscan(struct altera_state *astate, u32 count, - u8 *tdi_data, u32 start_index); -int altera_swap_ir(struct altera_state *astate, - u32 count, u8 *in_data, - u32 in_index, u8 *out_data, - u32 out_index); -int altera_drscan(struct altera_state *astate, u32 count, - u8 *tdi_data, u32 start_index); -int altera_swap_dr(struct altera_state *astate, u32 count, - u8 *in_data, u32 in_index, - u8 *out_data, u32 out_index); -void altera_free_buffers(struct altera_state *astate); -#endif /* ALTERA_JTAG_H */ diff --git a/drivers/staging/altera-stapl/altera-lpt.c b/drivers/staging/altera-stapl/altera-lpt.c deleted file mode 100644 index 91456a03612..00000000000 --- a/drivers/staging/altera-stapl/altera-lpt.c +++ /dev/null @@ -1,70 +0,0 @@ -/* - * altera-lpt.c - * - * altera FPGA driver - * - * Copyright (C) Altera Corporation 1998-2001 - * Copyright (C) 2010 NetUP Inc. - * Copyright (C) 2010 Abylay Ospan - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include -#include "altera-exprt.h" - -static int lpt_hardware_initialized; - -static void byteblaster_write(int port, int data) -{ - outb((u8)data, (u16)(port + 0x378)); -}; - -static int byteblaster_read(int port) -{ - int data = 0; - data = inb((u16)(port + 0x378)); - return data & 0xff; -}; - -int netup_jtag_io_lpt(void *device, int tms, int tdi, int read_tdo) -{ - int data = 0; - int tdo = 0; - int initial_lpt_ctrl = 0; - - if (!lpt_hardware_initialized) { - initial_lpt_ctrl = byteblaster_read(2); - byteblaster_write(2, (initial_lpt_ctrl | 0x02) & 0xdf); - lpt_hardware_initialized = 1; - } - - data = ((tdi ? 0x40 : 0) | (tms ? 0x02 : 0)); - - byteblaster_write(0, data); - - if (read_tdo) { - tdo = byteblaster_read(1); - tdo = ((tdo & 0x80) ? 0 : 1); - } - - byteblaster_write(0, data | 0x01); - - byteblaster_write(0, data); - - return tdo; -} diff --git a/drivers/staging/altera-stapl/altera.c b/drivers/staging/altera-stapl/altera.c deleted file mode 100644 index 8d73a864273..00000000000 --- a/drivers/staging/altera-stapl/altera.c +++ /dev/null @@ -1,2536 +0,0 @@ -/* - * altera.c - * - * altera FPGA driver - * - * Copyright (C) Altera Corporation 1998-2001 - * Copyright (C) 2010,2011 NetUP Inc. - * Copyright (C) 2010,2011 Igor M. Liplianin - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include -#include -#include -#include -#include "altera.h" -#include "altera-exprt.h" -#include "altera-jtag.h" - -static int debug = 1; -module_param(debug, int, 0644); -MODULE_PARM_DESC(debug, "enable debugging information"); - -MODULE_DESCRIPTION("altera FPGA kernel module"); -MODULE_AUTHOR("Igor M. Liplianin "); -MODULE_LICENSE("GPL"); - -#define dprintk(args...) \ - if (debug) { \ - printk(KERN_DEBUG args); \ - } - -enum altera_fpga_opcode { - OP_NOP = 0, - OP_DUP, - OP_SWP, - OP_ADD, - OP_SUB, - OP_MULT, - OP_DIV, - OP_MOD, - OP_SHL, - OP_SHR, - OP_NOT, - OP_AND, - OP_OR, - OP_XOR, - OP_INV, - OP_GT, - OP_LT, - OP_RET, - OP_CMPS, - OP_PINT, - OP_PRNT, - OP_DSS, - OP_DSSC, - OP_ISS, - OP_ISSC, - OP_DPR = 0x1c, - OP_DPRL, - OP_DPO, - OP_DPOL, - OP_IPR, - OP_IPRL, - OP_IPO, - OP_IPOL, - OP_PCHR, - OP_EXIT, - OP_EQU, - OP_POPT, - OP_ABS = 0x2c, - OP_BCH0, - OP_PSH0 = 0x2f, - OP_PSHL = 0x40, - OP_PSHV, - OP_JMP, - OP_CALL, - OP_NEXT, - OP_PSTR, - OP_SINT = 0x47, - OP_ST, - OP_ISTP, - OP_DSTP, - OP_SWPN, - OP_DUPN, - OP_POPV, - OP_POPE, - OP_POPA, - OP_JMPZ, - OP_DS, - OP_IS, - OP_DPRA, - OP_DPOA, - OP_IPRA, - OP_IPOA, - OP_EXPT, - OP_PSHE, - OP_PSHA, - OP_DYNA, - OP_EXPV = 0x5c, - OP_COPY = 0x80, - OP_REVA, - OP_DSC, - OP_ISC, - OP_WAIT, - OP_VS, - OP_CMPA = 0xc0, - OP_VSC, -}; - -struct altera_procinfo { - char *name; - u8 attrs; - struct altera_procinfo *next; -}; - -/* This function checks if enough parameters are available on the stack. */ -static int altera_check_stack(int stack_ptr, int count, int *status) -{ - if (stack_ptr < count) { - *status = -EOVERFLOW; - return 0; - } - - return 1; -} - -static void altera_export_int(char *key, s32 value) -{ - dprintk("Export: key = \"%s\", value = %d\n", key, value); -} - -#define HEX_LINE_CHARS 72 -#define HEX_LINE_BITS (HEX_LINE_CHARS * 4) - -static void altera_export_bool_array(char *key, u8 *data, s32 count) -{ - char string[HEX_LINE_CHARS + 1]; - s32 i, offset; - u32 size, line, lines, linebits, value, j, k; - - if (count > HEX_LINE_BITS) { - dprintk("Export: key = \"%s\", %d bits, value = HEX\n", - key, count); - lines = (count + (HEX_LINE_BITS - 1)) / HEX_LINE_BITS; - - for (line = 0; line < lines; ++line) { - if (line < (lines - 1)) { - linebits = HEX_LINE_BITS; - size = HEX_LINE_CHARS; - offset = count - ((line + 1) * HEX_LINE_BITS); - } else { - linebits = - count - ((lines - 1) * HEX_LINE_BITS); - size = (linebits + 3) / 4; - offset = 0L; - } - - string[size] = '\0'; - j = size - 1; - value = 0; - - for (k = 0; k < linebits; ++k) { - i = k + offset; - if (data[i >> 3] & (1 << (i & 7))) - value |= (1 << (i & 3)); - if ((i & 3) == 3) { - sprintf(&string[j], "%1x", value); - value = 0; - --j; - } - } - if ((k & 3) > 0) - sprintf(&string[j], "%1x", value); - - dprintk("%s\n", string); - } - - } else { - size = (count + 3) / 4; - string[size] = '\0'; - j = size - 1; - value = 0; - - for (i = 0; i < count; ++i) { - if (data[i >> 3] & (1 << (i & 7))) - value |= (1 << (i & 3)); - if ((i & 3) == 3) { - sprintf(&string[j], "%1x", value); - value = 0; - --j; - } - } - if ((i & 3) > 0) - sprintf(&string[j], "%1x", value); - - dprintk("Export: key = \"%s\", %d bits, value = HEX %s\n", - key, count, string); - } -} - -static int altera_execute(struct altera_state *astate, - u8 *p, - s32 program_size, - s32 *error_address, - int *exit_code, - int *format_version) -{ - struct altera_config *aconf = astate->config; - char *msg_buff = astate->msg_buff; - long *stack = astate->stack; - int status = 0; - u32 first_word = 0L; - u32 action_table = 0L; - u32 proc_table = 0L; - u32 str_table = 0L; - u32 sym_table = 0L; - u32 data_sect = 0L; - u32 code_sect = 0L; - u32 debug_sect = 0L; - u32 action_count = 0L; - u32 proc_count = 0L; - u32 sym_count = 0L; - long *vars = NULL; - s32 *var_size = NULL; - char *attrs = NULL; - u8 *proc_attributes = NULL; - u32 pc; - u32 opcode_address; - u32 args[3]; - u32 opcode; - u32 name_id; - u8 charbuf[4]; - long long_tmp; - u32 variable_id; - u8 *charptr_tmp; - u8 *charptr_tmp2; - long *longptr_tmp; - int version = 0; - int delta = 0; - int stack_ptr = 0; - u32 arg_count; - int done = 0; - int bad_opcode = 0; - u32 count; - u32 index; - u32 index2; - s32 long_count; - s32 long_idx; - s32 long_idx2; - u32 i; - u32 j; - u32 uncomp_size; - u32 offset; - u32 value; - int current_proc = 0; - int reverse; - - char *name; - - dprintk("%s\n", __func__); - - /* Read header information */ - if (program_size > 52L) { - first_word = get_unaligned_be32(&p[0]); - version = (first_word & 1L); - *format_version = version + 1; - delta = version * 8; - - action_table = get_unaligned_be32(&p[4]); - proc_table = get_unaligned_be32(&p[8]); - str_table = get_unaligned_be32(&p[4 + delta]); - sym_table = get_unaligned_be32(&p[16 + delta]); - data_sect = get_unaligned_be32(&p[20 + delta]); - code_sect = get_unaligned_be32(&p[24 + delta]); - debug_sect = get_unaligned_be32(&p[28 + delta]); - action_count = get_unaligned_be32(&p[40 + delta]); - proc_count = get_unaligned_be32(&p[44 + delta]); - sym_count = get_unaligned_be32(&p[48 + (2 * delta)]); - } - - if ((first_word != 0x4A414D00L) && (first_word != 0x4A414D01L)) { - done = 1; - status = -EIO; - goto exit_done; - } - - if (sym_count <= 0) - goto exit_done; - - vars = kzalloc(sym_count * sizeof(long), GFP_KERNEL); - - if (vars == NULL) - status = -ENOMEM; - - if (status == 0) { - var_size = kzalloc(sym_count * sizeof(s32), GFP_KERNEL); - - if (var_size == NULL) - status = -ENOMEM; - } - - if (status == 0) { - attrs = kzalloc(sym_count, GFP_KERNEL); - - if (attrs == NULL) - status = -ENOMEM; - } - - if ((status == 0) && (version > 0)) { - proc_attributes = kzalloc(proc_count, GFP_KERNEL); - - if (proc_attributes == NULL) - status = -ENOMEM; - } - - if (status != 0) - goto exit_done; - - delta = version * 2; - - for (i = 0; i < sym_count; ++i) { - offset = (sym_table + ((11 + delta) * i)); - - value = get_unaligned_be32(&p[offset + 3 + delta]); - - attrs[i] = p[offset]; - - /* - * use bit 7 of attribute byte to indicate that - * this buffer was dynamically allocated - * and should be freed later - */ - attrs[i] &= 0x7f; - - var_size[i] = get_unaligned_be32(&p[offset + 7 + delta]); - - /* - * Attribute bits: - * bit 0: 0 = read-only, 1 = read-write - * bit 1: 0 = not compressed, 1 = compressed - * bit 2: 0 = not initialized, 1 = initialized - * bit 3: 0 = scalar, 1 = array - * bit 4: 0 = Boolean, 1 = integer - * bit 5: 0 = declared variable, - * 1 = compiler created temporary variable - */ - - if ((attrs[i] & 0x0c) == 0x04) - /* initialized scalar variable */ - vars[i] = value; - else if ((attrs[i] & 0x1e) == 0x0e) { - /* initialized compressed Boolean array */ - uncomp_size = get_unaligned_le32(&p[data_sect + value]); - - /* allocate a buffer for the uncompressed data */ - vars[i] = (long)kzalloc(uncomp_size, GFP_KERNEL); - if (vars[i] == 0L) - status = -ENOMEM; - else { - /* set flag so buffer will be freed later */ - attrs[i] |= 0x80; - - /* uncompress the data */ - if (altera_shrink(&p[data_sect + value], - var_size[i], - (u8 *)vars[i], - uncomp_size, - version) != uncomp_size) - /* decompression failed */ - status = -EIO; - else - var_size[i] = uncomp_size * 8L; - - } - } else if ((attrs[i] & 0x1e) == 0x0c) { - /* initialized Boolean array */ - vars[i] = value + data_sect + (long)p; - } else if ((attrs[i] & 0x1c) == 0x1c) { - /* initialized integer array */ - vars[i] = value + data_sect; - } else if ((attrs[i] & 0x0c) == 0x08) { - /* uninitialized array */ - - /* flag attrs so that memory is freed */ - attrs[i] |= 0x80; - - if (var_size[i] > 0) { - u32 size; - - if (attrs[i] & 0x10) - /* integer array */ - size = (var_size[i] * sizeof(s32)); - else - /* Boolean array */ - size = ((var_size[i] + 7L) / 8L); - - vars[i] = (long)kzalloc(size, GFP_KERNEL); - - if (vars[i] == 0) { - status = -ENOMEM; - } else { - /* zero out memory */ - for (j = 0; j < size; ++j) - ((u8 *)(vars[i]))[j] = 0; - - } - } else - vars[i] = 0; - - } else - vars[i] = 0; - - } - -exit_done: - if (status != 0) - done = 1; - - altera_jinit(astate); - - pc = code_sect; - msg_buff[0] = '\0'; - - /* - * For JBC version 2, we will execute the procedures corresponding to - * the selected ACTION - */ - if (version > 0) { - if (aconf->action == NULL) { - status = -EINVAL; - done = 1; - } else { - int action_found = 0; - for (i = 0; (i < action_count) && !action_found; ++i) { - name_id = get_unaligned_be32(&p[action_table + - (12 * i)]); - - name = &p[str_table + name_id]; - - if (strnicmp(aconf->action, name, strlen(name)) == 0) { - action_found = 1; - current_proc = - get_unaligned_be32(&p[action_table + - (12 * i) + 8]); - } - } - - if (!action_found) { - status = -EINVAL; - done = 1; - } - } - - if (status == 0) { - int first_time = 1; - i = current_proc; - while ((i != 0) || first_time) { - first_time = 0; - /* check procedure attribute byte */ - proc_attributes[i] = - (p[proc_table + - (13 * i) + 8] & - 0x03); - - /* - * BIT0 - OPTIONAL - * BIT1 - RECOMMENDED - * BIT6 - FORCED OFF - * BIT7 - FORCED ON - */ - - i = get_unaligned_be32(&p[proc_table + - (13 * i) + 4]); - } - - /* - * Set current_proc to the first procedure - * to be executed - */ - i = current_proc; - while ((i != 0) && - ((proc_attributes[i] == 1) || - ((proc_attributes[i] & 0xc0) == 0x40))) { - i = get_unaligned_be32(&p[proc_table + - (13 * i) + 4]); - } - - if ((i != 0) || ((i == 0) && (current_proc == 0) && - ((proc_attributes[0] != 1) && - ((proc_attributes[0] & 0xc0) != 0x40)))) { - current_proc = i; - pc = code_sect + - get_unaligned_be32(&p[proc_table + - (13 * i) + 9]); - if ((pc < code_sect) || (pc >= debug_sect)) - status = -ERANGE; - } else - /* there are no procedures to execute! */ - done = 1; - - } - } - - msg_buff[0] = '\0'; - - while (!done) { - opcode = (p[pc] & 0xff); - opcode_address = pc; - ++pc; - - if (debug > 1) - printk("opcode: %02x\n", opcode); - - arg_count = (opcode >> 6) & 3; - for (i = 0; i < arg_count; ++i) { - args[i] = get_unaligned_be32(&p[pc]); - pc += 4; - } - - switch (opcode) { - case OP_NOP: - break; - case OP_DUP: - if (altera_check_stack(stack_ptr, 1, &status)) { - stack[stack_ptr] = stack[stack_ptr - 1]; - ++stack_ptr; - } - break; - case OP_SWP: - if (altera_check_stack(stack_ptr, 2, &status)) { - long_tmp = stack[stack_ptr - 2]; - stack[stack_ptr - 2] = stack[stack_ptr - 1]; - stack[stack_ptr - 1] = long_tmp; - } - break; - case OP_ADD: - if (altera_check_stack(stack_ptr, 2, &status)) { - --stack_ptr; - stack[stack_ptr - 1] += stack[stack_ptr]; - } - break; - case OP_SUB: - if (altera_check_stack(stack_ptr, 2, &status)) { - --stack_ptr; - stack[stack_ptr - 1] -= stack[stack_ptr]; - } - break; - case OP_MULT: - if (altera_check_stack(stack_ptr, 2, &status)) { - --stack_ptr; - stack[stack_ptr - 1] *= stack[stack_ptr]; - } - break; - case OP_DIV: - if (altera_check_stack(stack_ptr, 2, &status)) { - --stack_ptr; - stack[stack_ptr - 1] /= stack[stack_ptr]; - } - break; - case OP_MOD: - if (altera_check_stack(stack_ptr, 2, &status)) { - --stack_ptr; - stack[stack_ptr - 1] %= stack[stack_ptr]; - } - break; - case OP_SHL: - if (altera_check_stack(stack_ptr, 2, &status)) { - --stack_ptr; - stack[stack_ptr - 1] <<= stack[stack_ptr]; - } - break; - case OP_SHR: - if (altera_check_stack(stack_ptr, 2, &status)) { - --stack_ptr; - stack[stack_ptr - 1] >>= stack[stack_ptr]; - } - break; - case OP_NOT: - if (altera_check_stack(stack_ptr, 1, &status)) - stack[stack_ptr - 1] ^= (-1L); - - break; - case OP_AND: - if (altera_check_stack(stack_ptr, 2, &status)) { - --stack_ptr; - stack[stack_ptr - 1] &= stack[stack_ptr]; - } - break; - case OP_OR: - if (altera_check_stack(stack_ptr, 2, &status)) { - --stack_ptr; - stack[stack_ptr - 1] |= stack[stack_ptr]; - } - break; - case OP_XOR: - if (altera_check_stack(stack_ptr, 2, &status)) { - --stack_ptr; - stack[stack_ptr - 1] ^= stack[stack_ptr]; - } - break; - case OP_INV: - if (!altera_check_stack(stack_ptr, 1, &status)) - break; - stack[stack_ptr - 1] = stack[stack_ptr - 1] ? 0L : 1L; - break; - case OP_GT: - if (!altera_check_stack(stack_ptr, 2, &status)) - break; - --stack_ptr; - stack[stack_ptr - 1] = - (stack[stack_ptr - 1] > stack[stack_ptr]) ? - 1L : 0L; - - break; - case OP_LT: - if (!altera_check_stack(stack_ptr, 2, &status)) - break; - --stack_ptr; - stack[stack_ptr - 1] = - (stack[stack_ptr - 1] < stack[stack_ptr]) ? - 1L : 0L; - - break; - case OP_RET: - if ((version > 0) && (stack_ptr == 0)) { - /* - * We completed one of the main procedures - * of an ACTION. - * Find the next procedure - * to be executed and jump to it. - * If there are no more procedures, then EXIT. - */ - i = get_unaligned_be32(&p[proc_table + - (13 * current_proc) + 4]); - while ((i != 0) && - ((proc_attributes[i] == 1) || - ((proc_attributes[i] & 0xc0) == 0x40))) - i = get_unaligned_be32(&p[proc_table + - (13 * i) + 4]); - - if (i == 0) { - /* no procedures to execute! */ - done = 1; - *exit_code = 0; /* success */ - } else { - current_proc = i; - pc = code_sect + get_unaligned_be32( - &p[proc_table + - (13 * i) + 9]); - if ((pc < code_sect) || - (pc >= debug_sect)) - status = -ERANGE; - } - - } else - if (altera_check_stack(stack_ptr, 1, &status)) { - pc = stack[--stack_ptr] + code_sect; - if ((pc <= code_sect) || - (pc >= debug_sect)) - status = -ERANGE; - - } - - break; - case OP_CMPS: - /* - * Array short compare - * ...stack 0 is source 1 value - * ...stack 1 is source 2 value - * ...stack 2 is mask value - * ...stack 3 is count - */ - if (altera_check_stack(stack_ptr, 4, &status)) { - s32 a = stack[--stack_ptr]; - s32 b = stack[--stack_ptr]; - long_tmp = stack[--stack_ptr]; - count = stack[stack_ptr - 1]; - - if ((count < 1) || (count > 32)) - status = -ERANGE; - else { - long_tmp &= ((-1L) >> (32 - count)); - - stack[stack_ptr - 1] = - ((a & long_tmp) == (b & long_tmp)) - ? 1L : 0L; - } - } - break; - case OP_PINT: - /* - * PRINT add integer - * ...stack 0 is integer value - */ - if (!altera_check_stack(stack_ptr, 1, &status)) - break; - sprintf(&msg_buff[strlen(msg_buff)], - "%ld", stack[--stack_ptr]); - break; - case OP_PRNT: - /* PRINT finish */ - if (debug) - printk(msg_buff, "\n"); - - msg_buff[0] = '\0'; - break; - case OP_DSS: - /* - * DRSCAN short - * ...stack 0 is scan data - * ...stack 1 is count - */ - if (!altera_check_stack(stack_ptr, 2, &status)) - break; - long_tmp = stack[--stack_ptr]; - count = stack[--stack_ptr]; - put_unaligned_le32(long_tmp, &charbuf[0]); - status = altera_drscan(astate, count, charbuf, 0); - break; - case OP_DSSC: - /* - * DRSCAN short with capture - * ...stack 0 is scan data - * ...stack 1 is count - */ - if (!altera_check_stack(stack_ptr, 2, &status)) - break; - long_tmp = stack[--stack_ptr]; - count = stack[stack_ptr - 1]; - put_unaligned_le32(long_tmp, &charbuf[0]); - status = altera_swap_dr(astate, count, charbuf, - 0, charbuf, 0); - stack[stack_ptr - 1] = get_unaligned_le32(&charbuf[0]); - break; - case OP_ISS: - /* - * IRSCAN short - * ...stack 0 is scan data - * ...stack 1 is count - */ - if (!altera_check_stack(stack_ptr, 2, &status)) - break; - long_tmp = stack[--stack_ptr]; - count = stack[--stack_ptr]; - put_unaligned_le32(long_tmp, &charbuf[0]); - status = altera_irscan(astate, count, charbuf, 0); - break; - case OP_ISSC: - /* - * IRSCAN short with capture - * ...stack 0 is scan data - * ...stack 1 is count - */ - if (!altera_check_stack(stack_ptr, 2, &status)) - break; - long_tmp = stack[--stack_ptr]; - count = stack[stack_ptr - 1]; - put_unaligned_le32(long_tmp, &charbuf[0]); - status = altera_swap_ir(astate, count, charbuf, - 0, charbuf, 0); - stack[stack_ptr - 1] = get_unaligned_le32(&charbuf[0]); - break; - case OP_DPR: - if (!altera_check_stack(stack_ptr, 1, &status)) - break; - count = stack[--stack_ptr]; - status = altera_set_dr_pre(&astate->js, count, 0, NULL); - break; - case OP_DPRL: - /* - * DRPRE with literal data - * ...stack 0 is count - * ...stack 1 is literal data - */ - if (!altera_check_stack(stack_ptr, 2, &status)) - break; - count = stack[--stack_ptr]; - long_tmp = stack[--stack_ptr]; - put_unaligned_le32(long_tmp, &charbuf[0]); - status = altera_set_dr_pre(&astate->js, count, 0, - charbuf); - break; - case OP_DPO: - /* - * DRPOST - * ...stack 0 is count - */ - if (altera_check_stack(stack_ptr, 1, &status)) { - count = stack[--stack_ptr]; - status = altera_set_dr_post(&astate->js, count, - 0, NULL); - } - break; - case OP_DPOL: - /* - * DRPOST with literal data - * ...stack 0 is count - * ...stack 1 is literal data - */ - if (!altera_check_stack(stack_ptr, 2, &status)) - break; - count = stack[--stack_ptr]; - long_tmp = stack[--stack_ptr]; - put_unaligned_le32(long_tmp, &charbuf[0]); - status = altera_set_dr_post(&astate->js, count, 0, - charbuf); - break; - case OP_IPR: - if (altera_check_stack(stack_ptr, 1, &status)) { - count = stack[--stack_ptr]; - status = altera_set_ir_pre(&astate->js, count, - 0, NULL); - } - break; - case OP_IPRL: - /* - * IRPRE with literal data - * ...stack 0 is count - * ...stack 1 is literal data - */ - if (altera_check_stack(stack_ptr, 2, &status)) { - count = stack[--stack_ptr]; - long_tmp = stack[--stack_ptr]; - put_unaligned_le32(long_tmp, &charbuf[0]); - status = altera_set_ir_pre(&astate->js, count, - 0, charbuf); - } - break; - case OP_IPO: - /* - * IRPOST - * ...stack 0 is count - */ - if (altera_check_stack(stack_ptr, 1, &status)) { - count = stack[--stack_ptr]; - status = altera_set_ir_post(&astate->js, count, - 0, NULL); - } - break; - case OP_IPOL: - /* - * IRPOST with literal data - * ...stack 0 is count - * ...stack 1 is literal data - */ - if (!altera_check_stack(stack_ptr, 2, &status)) - break; - count = stack[--stack_ptr]; - long_tmp = stack[--stack_ptr]; - put_unaligned_le32(long_tmp, &charbuf[0]); - status = altera_set_ir_post(&astate->js, count, 0, - charbuf); - break; - case OP_PCHR: - if (altera_check_stack(stack_ptr, 1, &status)) { - u8 ch; - count = strlen(msg_buff); - ch = (char) stack[--stack_ptr]; - if ((ch < 1) || (ch > 127)) { - /* - * character code out of range - * instead of flagging an error, - * force the value to 127 - */ - ch = 127; - } - msg_buff[count] = ch; - msg_buff[count + 1] = '\0'; - } - break; - case OP_EXIT: - if (altera_check_stack(stack_ptr, 1, &status)) - *exit_code = stack[--stack_ptr]; - - done = 1; - break; - case OP_EQU: - if (!altera_check_stack(stack_ptr, 2, &status)) - break; - --stack_ptr; - stack[stack_ptr - 1] = - (stack[stack_ptr - 1] == stack[stack_ptr]) ? - 1L : 0L; - break; - case OP_POPT: - if (altera_check_stack(stack_ptr, 1, &status)) - --stack_ptr; - - break; - case OP_ABS: - if (!altera_check_stack(stack_ptr, 1, &status)) - break; - if (stack[stack_ptr - 1] < 0) - stack[stack_ptr - 1] = 0 - stack[stack_ptr - 1]; - - break; - case OP_BCH0: - /* - * Batch operation 0 - * SWP - * SWPN 7 - * SWP - * SWPN 6 - * DUPN 8 - * SWPN 2 - * SWP - * DUPN 6 - * DUPN 6 - */ - - /* SWP */ - if (altera_check_stack(stack_ptr, 2, &status)) { - long_tmp = stack[stack_ptr - 2]; - stack[stack_ptr - 2] = stack[stack_ptr - 1]; - stack[stack_ptr - 1] = long_tmp; - } - - /* SWPN 7 */ - index = 7 + 1; - if (altera_check_stack(stack_ptr, index, &status)) { - long_tmp = stack[stack_ptr - index]; - stack[stack_ptr - index] = stack[stack_ptr - 1]; - stack[stack_ptr - 1] = long_tmp; - } - - /* SWP */ - if (altera_check_stack(stack_ptr, 2, &status)) { - long_tmp = stack[stack_ptr - 2]; - stack[stack_ptr - 2] = stack[stack_ptr - 1]; - stack[stack_ptr - 1] = long_tmp; - } - - /* SWPN 6 */ - index = 6 + 1; - if (altera_check_stack(stack_ptr, index, &status)) { - long_tmp = stack[stack_ptr - index]; - stack[stack_ptr - index] = stack[stack_ptr - 1]; - stack[stack_ptr - 1] = long_tmp; - } - - /* DUPN 8 */ - index = 8 + 1; - if (altera_check_stack(stack_ptr, index, &status)) { - stack[stack_ptr] = stack[stack_ptr - index]; - ++stack_ptr; - } - - /* SWPN 2 */ - index = 2 + 1; - if (altera_check_stack(stack_ptr, index, &status)) { - long_tmp = stack[stack_ptr - index]; - stack[stack_ptr - index] = stack[stack_ptr - 1]; - stack[stack_ptr - 1] = long_tmp; - } - - /* SWP */ - if (altera_check_stack(stack_ptr, 2, &status)) { - long_tmp = stack[stack_ptr - 2]; - stack[stack_ptr - 2] = stack[stack_ptr - 1]; - stack[stack_ptr - 1] = long_tmp; - } - - /* DUPN 6 */ - index = 6 + 1; - if (altera_check_stack(stack_ptr, index, &status)) { - stack[stack_ptr] = stack[stack_ptr - index]; - ++stack_ptr; - } - - /* DUPN 6 */ - index = 6 + 1; - if (altera_check_stack(stack_ptr, index, &status)) { - stack[stack_ptr] = stack[stack_ptr - index]; - ++stack_ptr; - } - break; - case OP_PSH0: - stack[stack_ptr++] = 0; - break; - case OP_PSHL: - stack[stack_ptr++] = (s32) args[0]; - break; - case OP_PSHV: - stack[stack_ptr++] = vars[args[0]]; - break; - case OP_JMP: - pc = args[0] + code_sect; - if ((pc < code_sect) || (pc >= debug_sect)) - status = -ERANGE; - break; - case OP_CALL: - stack[stack_ptr++] = pc; - pc = args[0] + code_sect; - if ((pc < code_sect) || (pc >= debug_sect)) - status = -ERANGE; - break; - case OP_NEXT: - /* - * Process FOR / NEXT loop - * ...argument 0 is variable ID - * ...stack 0 is step value - * ...stack 1 is end value - * ...stack 2 is top address - */ - if (altera_check_stack(stack_ptr, 3, &status)) { - s32 step = stack[stack_ptr - 1]; - s32 end = stack[stack_ptr - 2]; - s32 top = stack[stack_ptr - 3]; - s32 iterator = vars[args[0]]; - int break_out = 0; - - if (step < 0) { - if (iterator <= end) - break_out = 1; - } else if (iterator >= end) - break_out = 1; - - if (break_out) { - stack_ptr -= 3; - } else { - vars[args[0]] = iterator + step; - pc = top + code_sect; - if ((pc < code_sect) || - (pc >= debug_sect)) - status = -ERANGE; - } - } - break; - case OP_PSTR: - /* - * PRINT add string - * ...argument 0 is string ID - */ - count = strlen(msg_buff); - strlcpy(&msg_buff[count], - &p[str_table + args[0]], - ALTERA_MESSAGE_LENGTH - count); - break; - case OP_SINT: - /* - * STATE intermediate state - * ...argument 0 is state code - */ - status = altera_goto_jstate(astate, args[0]); - break; - case OP_ST: - /* - * STATE final state - * ...argument 0 is state code - */ - status = altera_goto_jstate(astate, args[0]); - break; - case OP_ISTP: - /* - * IRSTOP state - * ...argument 0 is state code - */ - status = altera_set_irstop(&astate->js, args[0]); - break; - case OP_DSTP: - /* - * DRSTOP state - * ...argument 0 is state code - */ - status = altera_set_drstop(&astate->js, args[0]); - break; - - case OP_SWPN: - /* - * Exchange top with Nth stack value - * ...argument 0 is 0-based stack entry - * to swap with top element - */ - index = (args[0]) + 1; - if (altera_check_stack(stack_ptr, index, &status)) { - long_tmp = stack[stack_ptr - index]; - stack[stack_ptr - index] = stack[stack_ptr - 1]; - stack[stack_ptr - 1] = long_tmp; - } - break; - case OP_DUPN: - /* - * Duplicate Nth stack value - * ...argument 0 is 0-based stack entry to duplicate - */ - index = (args[0]) + 1; - if (altera_check_stack(stack_ptr, index, &status)) { - stack[stack_ptr] = stack[stack_ptr - index]; - ++stack_ptr; - } - break; - case OP_POPV: - /* - * Pop stack into scalar variable - * ...argument 0 is variable ID - * ...stack 0 is value - */ - if (altera_check_stack(stack_ptr, 1, &status)) - vars[args[0]] = stack[--stack_ptr]; - - break; - case OP_POPE: - /* - * Pop stack into integer array element - * ...argument 0 is variable ID - * ...stack 0 is array index - * ...stack 1 is value - */ - if (!altera_check_stack(stack_ptr, 2, &status)) - break; - variable_id = args[0]; - - /* - * If variable is read-only, - * convert to writable array - */ - if ((version > 0) && - ((attrs[variable_id] & 0x9c) == 0x1c)) { - /* Allocate a writable buffer for this array */ - count = var_size[variable_id]; - long_tmp = vars[variable_id]; - longptr_tmp = kzalloc(count * sizeof(long), - GFP_KERNEL); - vars[variable_id] = (long)longptr_tmp; - - if (vars[variable_id] == 0) { - status = -ENOMEM; - break; - } - - /* copy previous contents into buffer */ - for (i = 0; i < count; ++i) { - longptr_tmp[i] = - get_unaligned_be32(&p[long_tmp]); - long_tmp += sizeof(long); - } - - /* - * set bit 7 - buffer was - * dynamically allocated - */ - attrs[variable_id] |= 0x80; - - /* clear bit 2 - variable is writable */ - attrs[variable_id] &= ~0x04; - attrs[variable_id] |= 0x01; - - } - - /* check that variable is a writable integer array */ - if ((attrs[variable_id] & 0x1c) != 0x18) - status = -ERANGE; - else { - longptr_tmp = (long *)vars[variable_id]; - - /* pop the array index */ - index = stack[--stack_ptr]; - - /* pop the value and store it into the array */ - longptr_tmp[index] = stack[--stack_ptr]; - } - - break; - case OP_POPA: - /* - * Pop stack into Boolean array - * ...argument 0 is variable ID - * ...stack 0 is count - * ...stack 1 is array index - * ...stack 2 is value - */ - if (!altera_check_stack(stack_ptr, 3, &status)) - break; - variable_id = args[0]; - - /* - * If variable is read-only, - * convert to writable array - */ - if ((version > 0) && - ((attrs[variable_id] & 0x9c) == 0x0c)) { - /* Allocate a writable buffer for this array */ - long_tmp = - (var_size[variable_id] + 7L) >> 3L; - charptr_tmp2 = (u8 *)vars[variable_id]; - charptr_tmp = - kzalloc(long_tmp, GFP_KERNEL); - vars[variable_id] = (long)charptr_tmp; - - if (vars[variable_id] == 0) { - status = -ENOMEM; - break; - } - - /* zero the buffer */ - for (long_idx = 0L; - long_idx < long_tmp; - ++long_idx) { - charptr_tmp[long_idx] = 0; - } - - /* copy previous contents into buffer */ - for (long_idx = 0L; - long_idx < var_size[variable_id]; - ++long_idx) { - long_idx2 = long_idx; - - if (charptr_tmp2[long_idx2 >> 3] & - (1 << (long_idx2 & 7))) { - charptr_tmp[long_idx >> 3] |= - (1 << (long_idx & 7)); - } - } - - /* - * set bit 7 - buffer was - * dynamically allocated - */ - attrs[variable_id] |= 0x80; - - /* clear bit 2 - variable is writable */ - attrs[variable_id] &= ~0x04; - attrs[variable_id] |= 0x01; - - } - - /* - * check that variable is - * a writable Boolean array - */ - if ((attrs[variable_id] & 0x1c) != 0x08) { - status = -ERANGE; - break; - } - - charptr_tmp = (u8 *)vars[variable_id]; - - /* pop the count (number of bits to copy) */ - long_count = stack[--stack_ptr]; - - /* pop the array index */ - long_idx = stack[--stack_ptr]; - - reverse = 0; - - if (version > 0) { - /* - * stack 0 = array right index - * stack 1 = array left index - */ - - if (long_idx > long_count) { - reverse = 1; - long_tmp = long_count; - long_count = 1 + long_idx - - long_count; - long_idx = long_tmp; - - /* reverse POPA is not supported */ - status = -ERANGE; - break; - } else - long_count = 1 + long_count - - long_idx; - - } - - /* pop the data */ - long_tmp = stack[--stack_ptr]; - - if (long_count < 1) { - status = -ERANGE; - break; - } - - for (i = 0; i < long_count; ++i) { - if (long_tmp & (1L << (s32) i)) - charptr_tmp[long_idx >> 3L] |= - (1L << (long_idx & 7L)); - else - charptr_tmp[long_idx >> 3L] &= - ~(1L << (long_idx & 7L)); - - ++long_idx; - } - - break; - case OP_JMPZ: - /* - * Pop stack and branch if zero - * ...argument 0 is address - * ...stack 0 is condition value - */ - if (altera_check_stack(stack_ptr, 1, &status)) { - if (stack[--stack_ptr] == 0) { - pc = args[0] + code_sect; - if ((pc < code_sect) || - (pc >= debug_sect)) - status = -ERANGE; - } - } - break; - case OP_DS: - case OP_IS: - /* - * DRSCAN - * IRSCAN - * ...argument 0 is scan data variable ID - * ...stack 0 is array index - * ...stack 1 is count - */ - if (!altera_check_stack(stack_ptr, 2, &status)) - break; - long_idx = stack[--stack_ptr]; - long_count = stack[--stack_ptr]; - reverse = 0; - if (version > 0) { - /* - * stack 0 = array right index - * stack 1 = array left index - * stack 2 = count - */ - long_tmp = long_count; - long_count = stack[--stack_ptr]; - - if (long_idx > long_tmp) { - reverse = 1; - long_idx = long_tmp; - } - } - - charptr_tmp = (u8 *)vars[args[0]]; - - if (reverse) { - /* - * allocate a buffer - * and reverse the data order - */ - charptr_tmp2 = charptr_tmp; - charptr_tmp = kzalloc((long_count >> 3) + 1, - GFP_KERNEL); - if (charptr_tmp == NULL) { - status = -ENOMEM; - break; - } - - long_tmp = long_idx + long_count - 1; - long_idx2 = 0; - while (long_idx2 < long_count) { - if (charptr_tmp2[long_tmp >> 3] & - (1 << (long_tmp & 7))) - charptr_tmp[long_idx2 >> 3] |= - (1 << (long_idx2 & 7)); - else - charptr_tmp[long_idx2 >> 3] &= - ~(1 << (long_idx2 & 7)); - - --long_tmp; - ++long_idx2; - } - } - - if (opcode == 0x51) /* DS */ - status = altera_drscan(astate, long_count, - charptr_tmp, long_idx); - else /* IS */ - status = altera_irscan(astate, long_count, - charptr_tmp, long_idx); - - if (reverse) - kfree(charptr_tmp); - - break; - case OP_DPRA: - /* - * DRPRE with array data - * ...argument 0 is variable ID - * ...stack 0 is array index - * ...stack 1 is count - */ - if (!altera_check_stack(stack_ptr, 2, &status)) - break; - index = stack[--stack_ptr]; - count = stack[--stack_ptr]; - - if (version > 0) - /* - * stack 0 = array right index - * stack 1 = array left index - */ - count = 1 + count - index; - - charptr_tmp = (u8 *)vars[args[0]]; - status = altera_set_dr_pre(&astate->js, count, index, - charptr_tmp); - break; - case OP_DPOA: - /* - * DRPOST with array data - * ...argument 0 is variable ID - * ...stack 0 is array index - * ...stack 1 is count - */ - if (!altera_check_stack(stack_ptr, 2, &status)) - break; - index = stack[--stack_ptr]; - count = stack[--stack_ptr]; - - if (version > 0) - /* - * stack 0 = array right index - * stack 1 = array left index - */ - count = 1 + count - index; - - charptr_tmp = (u8 *)vars[args[0]]; - status = altera_set_dr_post(&astate->js, count, index, - charptr_tmp); - break; - case OP_IPRA: - /* - * IRPRE with array data - * ...argument 0 is variable ID - * ...stack 0 is array index - * ...stack 1 is count - */ - if (!altera_check_stack(stack_ptr, 2, &status)) - break; - index = stack[--stack_ptr]; - count = stack[--stack_ptr]; - - if (version > 0) - /* - * stack 0 = array right index - * stack 1 = array left index - */ - count = 1 + count - index; - - charptr_tmp = (u8 *)vars[args[0]]; - status = altera_set_ir_pre(&astate->js, count, index, - charptr_tmp); - - break; - case OP_IPOA: - /* - * IRPOST with array data - * ...argument 0 is variable ID - * ...stack 0 is array index - * ...stack 1 is count - */ - if (!altera_check_stack(stack_ptr, 2, &status)) - break; - index = stack[--stack_ptr]; - count = stack[--stack_ptr]; - - if (version > 0) - /* - * stack 0 = array right index - * stack 1 = array left index - */ - count = 1 + count - index; - - charptr_tmp = (u8 *)vars[args[0]]; - status = altera_set_ir_post(&astate->js, count, index, - charptr_tmp); - - break; - case OP_EXPT: - /* - * EXPORT - * ...argument 0 is string ID - * ...stack 0 is integer expression - */ - if (altera_check_stack(stack_ptr, 1, &status)) { - name = &p[str_table + args[0]]; - long_tmp = stack[--stack_ptr]; - altera_export_int(name, long_tmp); - } - break; - case OP_PSHE: - /* - * Push integer array element - * ...argument 0 is variable ID - * ...stack 0 is array index - */ - if (!altera_check_stack(stack_ptr, 1, &status)) - break; - variable_id = args[0]; - index = stack[stack_ptr - 1]; - - /* check variable type */ - if ((attrs[variable_id] & 0x1f) == 0x19) { - /* writable integer array */ - longptr_tmp = (long *)vars[variable_id]; - stack[stack_ptr - 1] = longptr_tmp[index]; - } else if ((attrs[variable_id] & 0x1f) == 0x1c) { - /* read-only integer array */ - long_tmp = vars[variable_id] + - (index * sizeof(long)); - stack[stack_ptr - 1] = - get_unaligned_be32(&p[long_tmp]); - } else - status = -ERANGE; - - break; - case OP_PSHA: - /* - * Push Boolean array - * ...argument 0 is variable ID - * ...stack 0 is count - * ...stack 1 is array index - */ - if (!altera_check_stack(stack_ptr, 2, &status)) - break; - variable_id = args[0]; - - /* check that variable is a Boolean array */ - if ((attrs[variable_id] & 0x18) != 0x08) { - status = -ERANGE; - break; - } - - charptr_tmp = (u8 *)vars[variable_id]; - - /* pop the count (number of bits to copy) */ - count = stack[--stack_ptr]; - - /* pop the array index */ - index = stack[stack_ptr - 1]; - - if (version > 0) - /* - * stack 0 = array right index - * stack 1 = array left index - */ - count = 1 + count - index; - - if ((count < 1) || (count > 32)) { - status = -ERANGE; - break; - } - - long_tmp = 0L; - - for (i = 0; i < count; ++i) - if (charptr_tmp[(i + index) >> 3] & - (1 << ((i + index) & 7))) - long_tmp |= (1L << i); - - stack[stack_ptr - 1] = long_tmp; - - break; - case OP_DYNA: - /* - * Dynamically change size of array - * ...argument 0 is variable ID - * ...stack 0 is new size - */ - if (!altera_check_stack(stack_ptr, 1, &status)) - break; - variable_id = args[0]; - long_tmp = stack[--stack_ptr]; - - if (long_tmp > var_size[variable_id]) { - var_size[variable_id] = long_tmp; - - if (attrs[variable_id] & 0x10) - /* allocate integer array */ - long_tmp *= sizeof(long); - else - /* allocate Boolean array */ - long_tmp = (long_tmp + 7) >> 3; - - /* - * If the buffer was previously allocated, - * free it - */ - if (attrs[variable_id] & 0x80) { - kfree((void *)vars[variable_id]); - vars[variable_id] = 0; - } - - /* - * Allocate a new buffer - * of the requested size - */ - vars[variable_id] = (long) - kzalloc(long_tmp, GFP_KERNEL); - - if (vars[variable_id] == 0) { - status = -ENOMEM; - break; - } - - /* - * Set the attribute bit to indicate that - * this buffer was dynamically allocated and - * should be freed later - */ - attrs[variable_id] |= 0x80; - - /* zero out memory */ - count = ((var_size[variable_id] + 7L) / - 8L); - charptr_tmp = (u8 *)(vars[variable_id]); - for (index = 0; index < count; ++index) - charptr_tmp[index] = 0; - - } - - break; - case OP_EXPV: - /* - * Export Boolean array - * ...argument 0 is string ID - * ...stack 0 is variable ID - * ...stack 1 is array right index - * ...stack 2 is array left index - */ - if (!altera_check_stack(stack_ptr, 3, &status)) - break; - if (version == 0) { - /* EXPV is not supported in JBC 1.0 */ - bad_opcode = 1; - break; - } - name = &p[str_table + args[0]]; - variable_id = stack[--stack_ptr]; - long_idx = stack[--stack_ptr];/* right indx */ - long_idx2 = stack[--stack_ptr];/* left indx */ - - if (long_idx > long_idx2) { - /* reverse indices not supported */ - status = -ERANGE; - break; - } - - long_count = 1 + long_idx2 - long_idx; - - charptr_tmp = (u8 *)vars[variable_id]; - charptr_tmp2 = NULL; - - if ((long_idx & 7L) != 0) { - s32 k = long_idx; - charptr_tmp2 = - kzalloc(((long_count + 7L) / 8L), - GFP_KERNEL); - if (charptr_tmp2 == NULL) { - status = -ENOMEM; - break; - } - - for (i = 0; i < long_count; ++i) { - if (charptr_tmp[k >> 3] & - (1 << (k & 7))) - charptr_tmp2[i >> 3] |= - (1 << (i & 7)); - else - charptr_tmp2[i >> 3] &= - ~(1 << (i & 7)); - - ++k; - } - charptr_tmp = charptr_tmp2; - - } else if (long_idx != 0) - charptr_tmp = &charptr_tmp[long_idx >> 3]; - - altera_export_bool_array(name, charptr_tmp, - long_count); - - /* free allocated buffer */ - if ((long_idx & 7L) != 0) - kfree(charptr_tmp2); - - break; - case OP_COPY: { - /* - * Array copy - * ...argument 0 is dest ID - * ...argument 1 is source ID - * ...stack 0 is count - * ...stack 1 is dest index - * ...stack 2 is source index - */ - s32 copy_count; - s32 copy_index; - s32 copy_index2; - s32 destleft; - s32 src_count; - s32 dest_count; - int src_reverse = 0; - int dest_reverse = 0; - - if (!altera_check_stack(stack_ptr, 3, &status)) - break; - - copy_count = stack[--stack_ptr]; - copy_index = stack[--stack_ptr]; - copy_index2 = stack[--stack_ptr]; - reverse = 0; - - if (version > 0) { - /* - * stack 0 = source right index - * stack 1 = source left index - * stack 2 = destination right index - * stack 3 = destination left index - */ - destleft = stack[--stack_ptr]; - - if (copy_count > copy_index) { - src_reverse = 1; - reverse = 1; - src_count = 1 + copy_count - copy_index; - /* copy_index = source start index */ - } else { - src_count = 1 + copy_index - copy_count; - /* source start index */ - copy_index = copy_count; - } - - if (copy_index2 > destleft) { - dest_reverse = 1; - reverse = !reverse; - dest_count = 1 + copy_index2 - destleft; - /* destination start index */ - copy_index2 = destleft; - } else - dest_count = 1 + destleft - copy_index2; - - copy_count = (src_count < dest_count) ? - src_count : dest_count; - - if ((src_reverse || dest_reverse) && - (src_count != dest_count)) - /* - * If either the source or destination - * is reversed, we can't tolerate - * a length mismatch, because we - * "left justify" arrays when copying. - * This won't work correctly - * with reversed arrays. - */ - status = -ERANGE; - - } - - count = copy_count; - index = copy_index; - index2 = copy_index2; - - /* - * If destination is a read-only array, - * allocate a buffer and convert it to a writable array - */ - variable_id = args[1]; - if ((version > 0) && - ((attrs[variable_id] & 0x9c) == 0x0c)) { - /* Allocate a writable buffer for this array */ - long_tmp = - (var_size[variable_id] + 7L) >> 3L; - charptr_tmp2 = (u8 *)vars[variable_id]; - charptr_tmp = - kzalloc(long_tmp, GFP_KERNEL); - vars[variable_id] = (long)charptr_tmp; - - if (vars[variable_id] == 0) { - status = -ENOMEM; - break; - } - - /* zero the buffer */ - for (long_idx = 0L; long_idx < long_tmp; - ++long_idx) - charptr_tmp[long_idx] = 0; - - /* copy previous contents into buffer */ - for (long_idx = 0L; - long_idx < var_size[variable_id]; - ++long_idx) { - long_idx2 = long_idx; - - if (charptr_tmp2[long_idx2 >> 3] & - (1 << (long_idx2 & 7))) - charptr_tmp[long_idx >> 3] |= - (1 << (long_idx & 7)); - - } - - /* - set bit 7 - buffer was dynamically allocated */ - attrs[variable_id] |= 0x80; - - /* clear bit 2 - variable is writable */ - attrs[variable_id] &= ~0x04; - attrs[variable_id] |= 0x01; - } - - charptr_tmp = (u8 *)vars[args[1]]; - charptr_tmp2 = (u8 *)vars[args[0]]; - - /* check if destination is a writable Boolean array */ - if ((attrs[args[1]] & 0x1c) != 0x08) { - status = -ERANGE; - break; - } - - if (count < 1) { - status = -ERANGE; - break; - } - - if (reverse) - index2 += (count - 1); - - for (i = 0; i < count; ++i) { - if (charptr_tmp2[index >> 3] & - (1 << (index & 7))) - charptr_tmp[index2 >> 3] |= - (1 << (index2 & 7)); - else - charptr_tmp[index2 >> 3] &= - ~(1 << (index2 & 7)); - - ++index; - if (reverse) - --index2; - else - ++index2; - } - - break; - } - case OP_DSC: - case OP_ISC: { - /* - * DRSCAN with capture - * IRSCAN with capture - * ...argument 0 is scan data variable ID - * ...argument 1 is capture variable ID - * ...stack 0 is capture index - * ...stack 1 is scan data index - * ...stack 2 is count - */ - s32 scan_right, scan_left; - s32 capture_count = 0; - s32 scan_count = 0; - s32 capture_index; - s32 scan_index; - - if (!altera_check_stack(stack_ptr, 3, &status)) - break; - - capture_index = stack[--stack_ptr]; - scan_index = stack[--stack_ptr]; - - if (version > 0) { - /* - * stack 0 = capture right index - * stack 1 = capture left index - * stack 2 = scan right index - * stack 3 = scan left index - * stack 4 = count - */ - scan_right = stack[--stack_ptr]; - scan_left = stack[--stack_ptr]; - capture_count = 1 + scan_index - capture_index; - scan_count = 1 + scan_left - scan_right; - scan_index = scan_right; - } - - long_count = stack[--stack_ptr]; - /* - * If capture array is read-only, allocate a buffer - * and convert it to a writable array - */ - variable_id = args[1]; - if ((version > 0) && - ((attrs[variable_id] & 0x9c) == 0x0c)) { - /* Allocate a writable buffer for this array */ - long_tmp = - (var_size[variable_id] + 7L) >> 3L; - charptr_tmp2 = (u8 *)vars[variable_id]; - charptr_tmp = - kzalloc(long_tmp, GFP_KERNEL); - vars[variable_id] = (long)charptr_tmp; - - if (vars[variable_id] == 0) { - status = -ENOMEM; - break; - } - - /* zero the buffer */ - for (long_idx = 0L; long_idx < long_tmp; - ++long_idx) - charptr_tmp[long_idx] = 0; - - /* copy previous contents into buffer */ - for (long_idx = 0L; - long_idx < var_size[variable_id]; - ++long_idx) { - long_idx2 = long_idx; - - if (charptr_tmp2[long_idx2 >> 3] & - (1 << (long_idx2 & 7))) - charptr_tmp[long_idx >> 3] |= - (1 << (long_idx & 7)); - - } - - /* - * set bit 7 - buffer was - * dynamically allocated - */ - attrs[variable_id] |= 0x80; - - /* clear bit 2 - variable is writable */ - attrs[variable_id] &= ~0x04; - attrs[variable_id] |= 0x01; - - } - - charptr_tmp = (u8 *)vars[args[0]]; - charptr_tmp2 = (u8 *)vars[args[1]]; - - if ((version > 0) && - ((long_count > capture_count) || - (long_count > scan_count))) { - status = -ERANGE; - break; - } - - /* - * check that capture array - * is a writable Boolean array - */ - if ((attrs[args[1]] & 0x1c) != 0x08) { - status = -ERANGE; - break; - } - - if (status == 0) { - if (opcode == 0x82) /* DSC */ - status = altera_swap_dr(astate, - long_count, - charptr_tmp, - scan_index, - charptr_tmp2, - capture_index); - else /* ISC */ - status = altera_swap_ir(astate, - long_count, - charptr_tmp, - scan_index, - charptr_tmp2, - capture_index); - - } - - break; - } - case OP_WAIT: - /* - * WAIT - * ...argument 0 is wait state - * ...argument 1 is end state - * ...stack 0 is cycles - * ...stack 1 is microseconds - */ - if (!altera_check_stack(stack_ptr, 2, &status)) - break; - long_tmp = stack[--stack_ptr]; - - if (long_tmp != 0L) - status = altera_wait_cycles(astate, long_tmp, - args[0]); - - long_tmp = stack[--stack_ptr]; - - if ((status == 0) && (long_tmp != 0L)) - status = altera_wait_msecs(astate, - long_tmp, - args[0]); - - if ((status == 0) && (args[1] != args[0])) - status = altera_goto_jstate(astate, - args[1]); - - if (version > 0) { - --stack_ptr; /* throw away MAX cycles */ - --stack_ptr; /* throw away MAX microseconds */ - } - break; - case OP_CMPA: { - /* - * Array compare - * ...argument 0 is source 1 ID - * ...argument 1 is source 2 ID - * ...argument 2 is mask ID - * ...stack 0 is source 1 index - * ...stack 1 is source 2 index - * ...stack 2 is mask index - * ...stack 3 is count - */ - s32 a, b; - u8 *source1 = (u8 *)vars[args[0]]; - u8 *source2 = (u8 *)vars[args[1]]; - u8 *mask = (u8 *)vars[args[2]]; - u32 index1; - u32 index2; - u32 mask_index; - - if (!altera_check_stack(stack_ptr, 4, &status)) - break; - - index1 = stack[--stack_ptr]; - index2 = stack[--stack_ptr]; - mask_index = stack[--stack_ptr]; - long_count = stack[--stack_ptr]; - - if (version > 0) { - /* - * stack 0 = source 1 right index - * stack 1 = source 1 left index - * stack 2 = source 2 right index - * stack 3 = source 2 left index - * stack 4 = mask right index - * stack 5 = mask left index - */ - s32 mask_right = stack[--stack_ptr]; - s32 mask_left = stack[--stack_ptr]; - /* source 1 count */ - a = 1 + index2 - index1; - /* source 2 count */ - b = 1 + long_count - mask_index; - a = (a < b) ? a : b; - /* mask count */ - b = 1 + mask_left - mask_right; - a = (a < b) ? a : b; - /* source 2 start index */ - index2 = mask_index; - /* mask start index */ - mask_index = mask_right; - long_count = a; - } - - long_tmp = 1L; - - if (long_count < 1) - status = -ERANGE; - else { - count = long_count; - - for (i = 0; i < count; ++i) { - if (mask[mask_index >> 3] & - (1 << (mask_index & 7))) { - a = source1[index1 >> 3] & - (1 << (index1 & 7)) - ? 1 : 0; - b = source2[index2 >> 3] & - (1 << (index2 & 7)) - ? 1 : 0; - - if (a != b) /* failure */ - long_tmp = 0L; - } - ++index1; - ++index2; - ++mask_index; - } - } - - stack[stack_ptr++] = long_tmp; - - break; - } - default: - /* Unrecognized opcode -- ERROR! */ - bad_opcode = 1; - break; - } - - if (bad_opcode) - status = -ENOSYS; - - if ((stack_ptr < 0) || (stack_ptr >= ALTERA_STACK_SIZE)) - status = -EOVERFLOW; - - if (status != 0) { - done = 1; - *error_address = (s32)(opcode_address - code_sect); - } - } - - altera_free_buffers(astate); - - /* Free all dynamically allocated arrays */ - if ((attrs != NULL) && (vars != NULL)) - for (i = 0; i < sym_count; ++i) - if (attrs[i] & 0x80) - kfree((void *)vars[i]); - - kfree(vars); - kfree(var_size); - kfree(attrs); - kfree(proc_attributes); - - return status; -} - -static int altera_get_note(u8 *p, s32 program_size, - s32 *offset, char *key, char *value, int length) -/* - * Gets key and value of NOTE fields in the JBC file. - * Can be called in two modes: if offset pointer is NULL, - * then the function searches for note fields which match - * the key string provided. If offset is not NULL, then - * the function finds the next note field of any key, - * starting at the offset specified by the offset pointer. - * Returns 0 for success, else appropriate error code - */ -{ - int status = -ENODATA; - u32 note_strings = 0L; - u32 note_table = 0L; - u32 note_count = 0L; - u32 first_word = 0L; - int version = 0; - int delta = 0; - char *key_ptr; - char *value_ptr; - int i; - - /* Read header information */ - if (program_size > 52L) { - first_word = get_unaligned_be32(&p[0]); - version = (first_word & 1L); - delta = version * 8; - - note_strings = get_unaligned_be32(&p[8 + delta]); - note_table = get_unaligned_be32(&p[12 + delta]); - note_count = get_unaligned_be32(&p[44 + (2 * delta)]); - } - - if ((first_word != 0x4A414D00L) && (first_word != 0x4A414D01L)) - return -EIO; - - if (note_count <= 0L) - return status; - - if (offset == NULL) { - /* - * We will search for the first note with a specific key, - * and return only the value - */ - for (i = 0; (i < note_count) && - (status != 0); ++i) { - key_ptr = &p[note_strings + - get_unaligned_be32( - &p[note_table + (8 * i)])]; - if ((strnicmp(key, key_ptr, strlen(key_ptr)) == 0) && - (key != NULL)) { - status = 0; - - value_ptr = &p[note_strings + - get_unaligned_be32( - &p[note_table + (8 * i) + 4])]; - - if (value != NULL) - strlcpy(value, value_ptr, length); - - } - } - } else { - /* - * We will search for the next note, regardless of the key, - * and return both the value and the key - */ - - i = *offset; - - if ((i >= 0) && (i < note_count)) { - status = 0; - - if (key != NULL) - strlcpy(key, &p[note_strings + - get_unaligned_be32( - &p[note_table + (8 * i)])], - length); - - if (value != NULL) - strlcpy(value, &p[note_strings + - get_unaligned_be32( - &p[note_table + (8 * i) + 4])], - length); - - *offset = i + 1; - } - } - - return status; -} - -static int altera_check_crc(u8 *p, s32 program_size) -{ - int status = 0; - u16 local_expected = 0, - local_actual = 0, - shift_reg = 0xffff; - int bit, feedback; - u8 databyte; - u32 i; - u32 crc_section = 0L; - u32 first_word = 0L; - int version = 0; - int delta = 0; - - if (program_size > 52L) { - first_word = get_unaligned_be32(&p[0]); - version = (first_word & 1L); - delta = version * 8; - - crc_section = get_unaligned_be32(&p[32 + delta]); - } - - if ((first_word != 0x4A414D00L) && (first_word != 0x4A414D01L)) - status = -EIO; - - if (crc_section >= program_size) - status = -EIO; - - if (status == 0) { - local_expected = (u16)get_unaligned_be16(&p[crc_section]); - - for (i = 0; i < crc_section; ++i) { - databyte = p[i]; - for (bit = 0; bit < 8; bit++) { - feedback = (databyte ^ shift_reg) & 0x01; - shift_reg >>= 1; - if (feedback) - shift_reg ^= 0x8408; - - databyte >>= 1; - } - } - - local_actual = (u16)~shift_reg; - - if (local_expected != local_actual) - status = -EILSEQ; - - } - - if (debug || status) { - switch (status) { - case 0: - printk(KERN_INFO "%s: CRC matched: %04x\n", __func__, - local_actual); - break; - case -EILSEQ: - printk(KERN_ERR "%s: CRC mismatch: expected %04x, " - "actual %04x\n", __func__, local_expected, - local_actual); - break; - case -ENODATA: - printk(KERN_ERR "%s: expected CRC not found, " - "actual CRC = %04x\n", __func__, - local_actual); - break; - case -EIO: - printk(KERN_ERR "%s: error: format isn't " - "recognized.\n", __func__); - break; - default: - printk(KERN_ERR "%s: CRC function returned error " - "code %d\n", __func__, status); - break; - } - } - - return status; -} - -static int altera_get_file_info(u8 *p, - s32 program_size, - int *format_version, - int *action_count, - int *procedure_count) -{ - int status = -EIO; - u32 first_word = 0; - int version = 0; - - if (program_size <= 52L) - return status; - - first_word = get_unaligned_be32(&p[0]); - - if ((first_word == 0x4A414D00L) || (first_word == 0x4A414D01L)) { - status = 0; - - version = (first_word & 1L); - *format_version = version + 1; - - if (version > 0) { - *action_count = get_unaligned_be32(&p[48]); - *procedure_count = get_unaligned_be32(&p[52]); - } - } - - return status; -} - -static int altera_get_act_info(u8 *p, - s32 program_size, - int index, - char **name, - char **description, - struct altera_procinfo **proc_list) -{ - int status = -EIO; - struct altera_procinfo *procptr = NULL; - struct altera_procinfo *tmpptr = NULL; - u32 first_word = 0L; - u32 action_table = 0L; - u32 proc_table = 0L; - u32 str_table = 0L; - u32 note_strings = 0L; - u32 action_count = 0L; - u32 proc_count = 0L; - u32 act_name_id = 0L; - u32 act_desc_id = 0L; - u32 act_proc_id = 0L; - u32 act_proc_name = 0L; - u8 act_proc_attribute = 0; - - if (program_size <= 52L) - return status; - /* Read header information */ - first_word = get_unaligned_be32(&p[0]); - - if (first_word != 0x4A414D01L) - return status; - - action_table = get_unaligned_be32(&p[4]); - proc_table = get_unaligned_be32(&p[8]); - str_table = get_unaligned_be32(&p[12]); - note_strings = get_unaligned_be32(&p[16]); - action_count = get_unaligned_be32(&p[48]); - proc_count = get_unaligned_be32(&p[52]); - - if (index >= action_count) - return status; - - act_name_id = get_unaligned_be32(&p[action_table + (12 * index)]); - act_desc_id = get_unaligned_be32(&p[action_table + (12 * index) + 4]); - act_proc_id = get_unaligned_be32(&p[action_table + (12 * index) + 8]); - - *name = &p[str_table + act_name_id]; - - if (act_desc_id < (note_strings - str_table)) - *description = &p[str_table + act_desc_id]; - - do { - act_proc_name = get_unaligned_be32( - &p[proc_table + (13 * act_proc_id)]); - act_proc_attribute = - (p[proc_table + (13 * act_proc_id) + 8] & 0x03); - - procptr = (struct altera_procinfo *) - kzalloc(sizeof(struct altera_procinfo), - GFP_KERNEL); - - if (procptr == NULL) - status = -ENOMEM; - else { - procptr->name = &p[str_table + act_proc_name]; - procptr->attrs = act_proc_attribute; - procptr->next = NULL; - - /* add record to end of linked list */ - if (*proc_list == NULL) - *proc_list = procptr; - else { - tmpptr = *proc_list; - while (tmpptr->next != NULL) - tmpptr = tmpptr->next; - tmpptr->next = procptr; - } - } - - act_proc_id = get_unaligned_be32( - &p[proc_table + (13 * act_proc_id) + 4]); - } while ((act_proc_id != 0) && (act_proc_id < proc_count)); - - return status; -} - -int altera_init(struct altera_config *config, const struct firmware *fw) -{ - struct altera_state *astate = NULL; - struct altera_procinfo *proc_list = NULL; - struct altera_procinfo *procptr = NULL; - char *key = NULL; - char *value = NULL; - char *action_name = NULL; - char *description = NULL; - int exec_result = 0; - int exit_code = 0; - int format_version = 0; - int action_count = 0; - int procedure_count = 0; - int index = 0; - s32 offset = 0L; - s32 error_address = 0L; - int retval = 0; - - key = kzalloc(33, GFP_KERNEL); - if (!key) { - retval = -ENOMEM; - goto out; - } - value = kzalloc(257, GFP_KERNEL); - if (!value) { - retval = -ENOMEM; - goto free_key; - } - astate = kzalloc(sizeof(struct altera_state), GFP_KERNEL); - if (!astate) { - retval = -ENOMEM; - goto free_value; - } - - astate->config = config; - if (!astate->config->jtag_io) { - dprintk(KERN_INFO "%s: using byteblaster!\n", __func__); - astate->config->jtag_io = netup_jtag_io_lpt; - } - - altera_check_crc((u8 *)fw->data, fw->size); - - if (debug) { - altera_get_file_info((u8 *)fw->data, fw->size, &format_version, - &action_count, &procedure_count); - printk(KERN_INFO "%s: File format is %s ByteCode format\n", - __func__, (format_version == 2) ? "Jam STAPL" : - "pre-standardized Jam 1.1"); - while (altera_get_note((u8 *)fw->data, fw->size, - &offset, key, value, 256) == 0) - printk(KERN_INFO "%s: NOTE \"%s\" = \"%s\"\n", - __func__, key, value); - } - - if (debug && (format_version == 2) && (action_count > 0)) { - printk(KERN_INFO "%s: Actions available:\n", __func__); - for (index = 0; index < action_count; ++index) { - altera_get_act_info((u8 *)fw->data, fw->size, - index, &action_name, - &description, - &proc_list); - - if (description == NULL) - printk(KERN_INFO "%s: %s\n", - __func__, - action_name); - else - printk(KERN_INFO "%s: %s \"%s\"\n", - __func__, - action_name, - description); - - procptr = proc_list; - while (procptr != NULL) { - if (procptr->attrs != 0) - printk(KERN_INFO "%s: %s (%s)\n", - __func__, - procptr->name, - (procptr->attrs == 1) ? - "optional" : "recommended"); - - proc_list = procptr->next; - kfree(procptr); - procptr = proc_list; - } - } - - printk(KERN_INFO "\n"); - } - - exec_result = altera_execute(astate, (u8 *)fw->data, fw->size, - &error_address, &exit_code, &format_version); - - if (exit_code) - exec_result = -EREMOTEIO; - - if ((format_version == 2) && (exec_result == -EINVAL)) { - if (astate->config->action == NULL) - printk(KERN_ERR "%s: error: no action specified for " - "Jam STAPL file.\nprogram terminated.\n", - __func__); - else - printk(KERN_ERR "%s: error: action \"%s\"" - " is not supported " - "for this Jam STAPL file.\n" - "Program terminated.\n", __func__, - astate->config->action); - - } else if (exec_result) - printk(KERN_ERR "%s: error %d\n", __func__, exec_result); - - kfree(astate); -free_value: - kfree(value); -free_key: - kfree(key); -out: - return retval; -} -EXPORT_SYMBOL(altera_init); diff --git a/drivers/staging/altera-stapl/altera.h b/drivers/staging/altera-stapl/altera.h deleted file mode 100644 index 94c0c6181da..00000000000 --- a/drivers/staging/altera-stapl/altera.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * altera.h - * - * altera FPGA driver - * - * Copyright (C) Altera Corporation 1998-2001 - * Copyright (C) 2010 NetUP Inc. - * Copyright (C) 2010 Igor M. Liplianin - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#ifndef _ALTERA_H_ -#define _ALTERA_H_ - -struct altera_config { - void *dev; - u8 *action; - int (*jtag_io) (void *dev, int tms, int tdi, int tdo); -}; - -#if defined(CONFIG_ALTERA_STAPL) || \ - (defined(CONFIG_ALTERA_STAPL_MODULE) && defined(MODULE)) - -extern int altera_init(struct altera_config *config, const struct firmware *fw); -#else - -static inline int altera_init(struct altera_config *config, - const struct firmware *fw) -{ - printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); - return 0; -} -#endif /* CONFIG_ALTERA_STAPL */ - -#endif /* _ALTERA_H_ */ diff --git a/include/misc/altera.h b/include/misc/altera.h new file mode 100644 index 00000000000..94c0c6181da --- /dev/null +++ b/include/misc/altera.h @@ -0,0 +1,49 @@ +/* + * altera.h + * + * altera FPGA driver + * + * Copyright (C) Altera Corporation 1998-2001 + * Copyright (C) 2010 NetUP Inc. + * Copyright (C) 2010 Igor M. Liplianin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef _ALTERA_H_ +#define _ALTERA_H_ + +struct altera_config { + void *dev; + u8 *action; + int (*jtag_io) (void *dev, int tms, int tdi, int tdo); +}; + +#if defined(CONFIG_ALTERA_STAPL) || \ + (defined(CONFIG_ALTERA_STAPL_MODULE) && defined(MODULE)) + +extern int altera_init(struct altera_config *config, const struct firmware *fw); +#else + +static inline int altera_init(struct altera_config *config, + const struct firmware *fw) +{ + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); + return 0; +} +#endif /* CONFIG_ALTERA_STAPL */ + +#endif /* _ALTERA_H_ */ -- cgit v1.2.3