Consolidate target selection code into single get_target() that handles both names...
[fw/openocd] / src / flash / ocl.c
index befa4e102ca79186a0bcfecd814eb36451d01a6b..e2099a1191a41d8fe780a0da960b13cedb7fb95c 100644 (file)
-/***************************************************************************\r
- *   Copyright (C) 2007 by Pavel Chromy                                    *\r
- *   chromy@asix.cz                                                        *\r
- *                                                                         *\r
- *   This program is free software; you can redistribute it and/or modify  *\r
- *   it under the terms of the GNU General Public License as published by  *\r
- *   the Free Software Foundation; either version 2 of the License, or     *\r
- *   (at your option) any later version.                                   *\r
- *                                                                         *\r
- *   This program is distributed in the hope that it will be useful,       *\r
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *\r
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *\r
- *   GNU General Public License for more details.                          *\r
- *                                                                         *\r
- *   You should have received a copy of the GNU General Public License     *\r
- *   along with this program; if not, write to the                         *\r
- *   Free Software Foundation, Inc.,                                       *\r
- *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *\r
- ***************************************************************************/\r
-#ifdef HAVE_CONFIG_H\r
-#include "config.h"\r
-#endif\r
-\r
-#include "replacements.h"\r
-\r
-#include "ocl.h"\r
-\r
-#include "flash.h"\r
-#include "target.h"\r
-#include "log.h"\r
-#include "binarybuffer.h"\r
-#include "types.h"\r
-#include "embeddedice.h"\r
-#include "arm7_9_common.h"\r
-\r
-#include <stdlib.h>\r
-#include <string.h>\r
-#include <unistd.h>\r
-\r
-int ocl_register_commands(struct command_context_s *cmd_ctx);\r
-int ocl_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct flash_bank_s *bank);\r
-int ocl_erase(struct flash_bank_s *bank, int first, int last);\r
-int ocl_protect(struct flash_bank_s *bank, int set, int first, int last);\r
-int ocl_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count);\r
-int ocl_probe(struct flash_bank_s *bank);\r
-int ocl_erase_check(struct flash_bank_s *bank);\r
-int ocl_protect_check(struct flash_bank_s *bank);\r
-int ocl_info(struct flash_bank_s *bank, char *buf, int buf_size);\r
-int ocl_auto_probe(struct flash_bank_s *bank);\r
-\r
-flash_driver_t ocl_flash =\r
-{\r
-       .name = "ocl",\r
-       .register_commands = ocl_register_commands,\r
-       .flash_bank_command = ocl_flash_bank_command,\r
-       .erase = ocl_erase,\r
-       .protect = ocl_protect,\r
-       .write = ocl_write,\r
-       .probe = ocl_probe,\r
-       .erase_check = ocl_erase_check,\r
-       .protect_check = ocl_protect_check,\r
-       .info = ocl_info,\r
-       .auto_probe = ocl_auto_probe\r
-};\r
-\r
-\r
-typedef struct ocl_priv_s\r
-{\r
-       arm_jtag_t *jtag_info;\r
-       int buflen;\r
-       int bufalign;\r
-} ocl_priv_t;\r
-\r
-\r
-int ocl_register_commands(struct command_context_s *cmd_ctx)\r
-{\r
-       return ERROR_OK;\r
-}\r
-\r
-\r
-int ocl_erase_check(struct flash_bank_s *bank)\r
-{\r
-       return ERROR_OK;\r
-}\r
-\r
-\r
-int ocl_protect_check(struct flash_bank_s *bank)\r
-{\r
-       return ERROR_OK;\r
-}\r
-\r
-\r
-/* flash_bank ocl 0 0 0 0 <target#> */\r
-int ocl_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct flash_bank_s *bank)\r
-{\r
-       int retval;\r
-       armv4_5_common_t *armv4_5;\r
-       arm7_9_common_t *arm7_9;\r
-       ocl_priv_t *ocl;\r
-\r
-       if (argc < 6)\r
-       {\r
-               LOG_WARNING("incomplete flash_bank ocl configuration");\r
-               return ERROR_FLASH_BANK_INVALID;\r
-       }\r
-\r
-       if ((retval = arm7_9_get_arch_pointers(bank->target, &armv4_5, &arm7_9)) != ERROR_OK)\r
-               return retval;\r
-\r
-       ocl = bank->driver_priv = malloc(sizeof(ocl_priv_t));\r
-       ocl->jtag_info = &arm7_9->jtag_info;\r
-       ocl->buflen = 0;\r
-       ocl->bufalign = 1;\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-\r
-int ocl_erase(struct flash_bank_s *bank, int first, int last)\r
-{\r
-       ocl_priv_t *ocl = bank->driver_priv;\r
-       int retval;\r
-       u32 dcc_buffer[3];\r
-\r
-       /* check preconditions */\r
-       if (bank->num_sectors == 0)\r
-               return ERROR_FLASH_BANK_NOT_PROBED;\r
-               \r
-       if (bank->target->state != TARGET_RUNNING)\r
-       {\r
-               LOG_ERROR("target has to be running to communicate with the loader");\r
-               return ERROR_TARGET_NOT_RUNNING;\r
-       }\r
-               \r
-       if ((first == 0) && (last == bank->num_sectors - 1))\r
-       {\r
-               dcc_buffer[0] = OCL_ERASE_ALL;\r
-               if ((retval = embeddedice_send(ocl->jtag_info, dcc_buffer, 1) != ERROR_OK))\r
-                       return retval;\r
-       }\r
-       else\r
-       {\r
-               dcc_buffer[0] = OCL_ERASE_BLOCK;\r
-               dcc_buffer[1] = first;\r
-               dcc_buffer[2] = last;\r
-               if ((retval = embeddedice_send(ocl->jtag_info, dcc_buffer, 3) != ERROR_OK))\r
-                       return retval;\r
-       }\r
-\r
-       /* wait for response, fixed timeout of 1 s */\r
-       if ((retval = embeddedice_handshake(ocl->jtag_info, EICE_COMM_CTRL_WBIT, 1000) != ERROR_OK))\r
-       {\r
-               if (retval == ERROR_TARGET_TIMEOUT)\r
-                       LOG_ERROR("loader not responding");\r
-               return retval;\r
-       }\r
-\r
-       /* receive response */\r
-       if ((retval = embeddedice_receive(ocl->jtag_info, dcc_buffer+1, 1) != ERROR_OK))\r
-               return retval;\r
-\r
-       if (dcc_buffer[1] != OCL_CMD_DONE)\r
-       {\r
-               if (dcc_buffer[0] == OCL_ERASE_ALL)\r
-                       LOG_ERROR("loader response to OCL_ERASE_ALL 0x%08lX", dcc_buffer[1]);\r
-               else\r
-                       LOG_ERROR("loader response to OCL_ERASE_BLOCK 0x%08lX", dcc_buffer[1]);\r
-               return ERROR_FLASH_OPERATION_FAILED;\r
-       }\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-\r
-int ocl_protect(struct flash_bank_s *bank, int set, int first, int last)\r
-{\r
-       return ERROR_OK;\r
-}\r
-\r
-\r
-int ocl_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count)\r
-{\r
-       ocl_priv_t *ocl = bank->driver_priv;\r
-       int retval;\r
-       u32 *dcc_buffer;\r
-       u32 *dcc_bufptr;\r
-       int byteofs;\r
-       int runlen;\r
-       u32 chksum;\r
-       \r
-       int i;\r
-\r
-       /* check preconditions */\r
-       if (ocl->buflen == 0 || ocl->bufalign==0)\r
-               return ERROR_FLASH_BANK_NOT_PROBED;\r
-\r
-       if (bank->target->state != TARGET_RUNNING)\r
-       {\r
-               LOG_ERROR("target has to be running to communicate with the loader");\r
-               return ERROR_TARGET_NOT_RUNNING;\r
-       }\r
-\r
-       /* allocate buffer for max. ocl buffer + overhead */\r
-       dcc_buffer = malloc(sizeof(u32)*(ocl->buflen/4+3));\r
-\r
-       while (count)\r
-       {\r
-               if (count + (offset % ocl->bufalign) > ocl->buflen)\r
-                       runlen = ocl->buflen - (offset % ocl->bufalign);\r
-               else\r
-                       runlen = count;\r
-\r
-               dcc_buffer[0] = OCL_FLASH_BLOCK | runlen;\r
-               dcc_buffer[1] = offset;\r
-               dcc_bufptr = &dcc_buffer[2];\r
-\r
-               *dcc_bufptr = 0xffffffff;\r
-               byteofs = (offset % ocl->bufalign) % 4;\r
-               chksum = OCL_CHKS_INIT;\r
-\r
-               /* copy data to DCC buffer in proper byte order and properly aligned */\r
-               for (i=0; i<runlen; i++)\r
-               {\r
-                       switch (byteofs++)\r
-                       {\r
-                               case 0:\r
-                                       *dcc_bufptr &= *(buffer++) | 0xffffff00;\r
-                                       break;\r
-                               case 1:\r
-                                       *dcc_bufptr &= ((*(buffer++))<<8) | 0xffff00ff;\r
-                                       break;\r
-                               case 2:\r
-                                       *dcc_bufptr &= ((*(buffer++))<<16) | 0xff00ffff;\r
-                                       break;\r
-                               case 3:\r
-                                       *dcc_bufptr &= ((*(buffer++))<<24) | 0x00ffffff;\r
-                                       chksum ^= *(dcc_bufptr++);\r
-                                       *dcc_bufptr = 0xffffffff;\r
-                                       byteofs = 0;\r
-                                       break;\r
-                       }\r
-               }\r
-\r
-               /* add the remaining word to checksum */\r
-               if (byteofs)\r
-                       chksum ^= *(dcc_bufptr++);\r
-\r
-               *(dcc_bufptr++) = chksum;\r
-               \r
-               /* send the data */\r
-               if ((retval = embeddedice_send(ocl->jtag_info, dcc_buffer, dcc_bufptr-dcc_buffer)) != ERROR_OK)\r
-               {\r
-                       free(dcc_buffer);\r
-                 return retval;\r
-               }\r
-\r
-               /* wait for response, fixed timeout of 1 s */\r
-               if ((retval = embeddedice_handshake(ocl->jtag_info, EICE_COMM_CTRL_WBIT, 1000) != ERROR_OK))\r
-               {\r
-                       if (retval == ERROR_TARGET_TIMEOUT)\r
-                               LOG_ERROR("loader not responding");\r
-                       free(dcc_buffer);\r
-                       return retval;\r
-               }\r
-\r
-               /* receive response */\r
-               if ((retval = embeddedice_receive(ocl->jtag_info, dcc_buffer, 1) != ERROR_OK))\r
-               {\r
-                       free(dcc_buffer);\r
-                       return retval;\r
-               }\r
-\r
-               if (dcc_buffer[0] != OCL_CMD_DONE)\r
-               {\r
-                       LOG_ERROR("loader response to OCL_FLASH_BLOCK 0x%08lX", dcc_buffer[0]);\r
-                       free(dcc_buffer);\r
-                       return ERROR_FLASH_OPERATION_FAILED;\r
-               }\r
-\r
-               count -= runlen;\r
-               offset += runlen;\r
-       }\r
-\r
-       free(dcc_buffer);\r
-       return ERROR_OK;\r
-}\r
-\r
-\r
-int ocl_probe(struct flash_bank_s *bank)\r
-{\r
-       ocl_priv_t *ocl = bank->driver_priv;\r
-       int retval;\r
-       u32 dcc_buffer[1];\r
-       int sectsize;\r
-       int i;\r
-\r
-       /* purge pending data in DCC */\r
-       embeddedice_receive(ocl->jtag_info, dcc_buffer, 1);\r
-\r
-       dcc_buffer[0] = OCL_PROBE;\r
-       if ((retval = embeddedice_send(ocl->jtag_info, dcc_buffer, 1) != ERROR_OK))\r
-               return retval;\r
-\r
-       /* wait for response, fixed timeout of 1 s */\r
-       if ((retval = embeddedice_handshake(ocl->jtag_info, EICE_COMM_CTRL_WBIT, 1000) != ERROR_OK))\r
-       {\r
-               if (retval == ERROR_TARGET_TIMEOUT)\r
-                       LOG_ERROR("loader not responding");\r
-               return retval;\r
-       }\r
-\r
-       /* receive response */\r
-       if ((retval = embeddedice_receive(ocl->jtag_info, dcc_buffer, 1) != ERROR_OK))\r
-               return retval;\r
-               \r
-       if (dcc_buffer[0] != OCL_CMD_DONE)\r
-       {\r
-               LOG_ERROR("loader response to OCL_PROBE 0x%08lX", dcc_buffer[0]);\r
-               return ERROR_FLASH_OPERATION_FAILED;\r
-       }\r
-\r
-       /* receive and fill in parameters, detection of loader is important, receive it one by one */\r
-       if ((retval = embeddedice_handshake(ocl->jtag_info, EICE_COMM_CTRL_WBIT, 0) != ERROR_OK)\r
-               || (retval = embeddedice_receive(ocl->jtag_info, dcc_buffer, 1) != ERROR_OK))\r
-               return retval;\r
-       bank->base = dcc_buffer[0];\r
-\r
-       if ((retval = embeddedice_handshake(ocl->jtag_info, EICE_COMM_CTRL_WBIT, 0) != ERROR_OK)\r
-               || (retval = embeddedice_receive(ocl->jtag_info, dcc_buffer, 1) != ERROR_OK))\r
-               return retval;\r
-       bank->size = dcc_buffer[0];\r
-\r
-       if ((retval = embeddedice_handshake(ocl->jtag_info, EICE_COMM_CTRL_WBIT, 0) != ERROR_OK)\r
-               || (retval = embeddedice_receive(ocl->jtag_info, dcc_buffer, 1) != ERROR_OK))\r
-               return retval;\r
-       bank->num_sectors = dcc_buffer[0];\r
-\r
-       if ((retval = embeddedice_handshake(ocl->jtag_info, EICE_COMM_CTRL_WBIT, 0) != ERROR_OK)\r
-               || (retval = embeddedice_receive(ocl->jtag_info, dcc_buffer, 1) != ERROR_OK))\r
-               return retval;\r
-       ocl->buflen = dcc_buffer[0] & 0xffff;\r
-       ocl->bufalign = dcc_buffer[0] >> 16;\r
-\r
-       bank->sectors = realloc(bank->sectors, sizeof(flash_sector_t)*bank->num_sectors);\r
-       if (bank->num_sectors == 0)\r
-       {\r
-               LOG_ERROR("number of sectors shall be non zero value");\r
-               return ERROR_FLASH_BANK_INVALID;\r
-       }\r
-       if (bank->size % bank->num_sectors) {\r
-               LOG_ERROR("bank size not divisible by number of sectors");\r
-               return ERROR_FLASH_BANK_INVALID;\r
-       }\r
-       sectsize = bank->size / bank->num_sectors;\r
-       for (i=0; i<bank->num_sectors; i++)\r
-       {\r
-               bank->sectors[i].offset = i * sectsize;\r
-               bank->sectors[i].size = sectsize;\r
-               bank->sectors[i].is_erased = -1;\r
-               bank->sectors[i].is_protected = -1;\r
-       }\r
-\r
-       if (ocl->bufalign == 0)\r
-               ocl->bufalign = 1;\r
-\r
-       if (ocl->buflen == 0)\r
-       {\r
-               LOG_ERROR("buflen shall be non zero value");\r
-               return ERROR_FLASH_BANK_INVALID;\r
-       }\r
-\r
-       if ((ocl->bufalign > ocl->buflen) || (ocl->buflen % ocl->bufalign))\r
-       {\r
-               LOG_ERROR("buflen is not multiple of bufalign");\r
-               return ERROR_FLASH_BANK_INVALID;\r
-       }\r
-\r
-       if (ocl->buflen % 4)\r
-       {\r
-               LOG_ERROR("buflen shall be divisible by 4");\r
-               return ERROR_FLASH_BANK_INVALID;\r
-       }\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-\r
-int ocl_info(struct flash_bank_s *bank, char *buf, int buf_size)\r
-{\r
-       return ERROR_OK;\r
-}\r
-\r
-\r
-int ocl_auto_probe(struct flash_bank_s *bank)\r
-{\r
-       ocl_priv_t *ocl = bank->driver_priv;\r
-\r
-       if (ocl->buflen == 0 || ocl->bufalign==0)\r
-               return ERROR_FLASH_BANK_NOT_PROBED;\r
-\r
-       return ERROR_OK;\r
-}\r
+/***************************************************************************
+ *   Copyright (C) 2007 by Pavel Chromy                                    *
+ *   chromy@asix.cz                                                        *
+ *                                                                         *
+ *   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.,                                       *
+ *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ ***************************************************************************/
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "ocl.h"
+#include "flash.h"
+#include "embeddedice.h"
+
+
+static int ocl_register_commands(struct command_context_s *cmd_ctx);
+static int ocl_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct flash_bank_s *bank);
+static int ocl_erase(struct flash_bank_s *bank, int first, int last);
+static int ocl_protect(struct flash_bank_s *bank, int set, int first, int last);
+static int ocl_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count);
+static int ocl_probe(struct flash_bank_s *bank);
+static int ocl_erase_check(struct flash_bank_s *bank);
+static int ocl_protect_check(struct flash_bank_s *bank);
+static int ocl_info(struct flash_bank_s *bank, char *buf, int buf_size);
+static int ocl_auto_probe(struct flash_bank_s *bank);
+
+flash_driver_t ocl_flash =
+{
+       .name = "ocl",
+       .register_commands = ocl_register_commands,
+       .flash_bank_command = ocl_flash_bank_command,
+       .erase = ocl_erase,
+       .protect = ocl_protect,
+       .write = ocl_write,
+       .probe = ocl_probe,
+       .erase_check = ocl_erase_check,
+       .protect_check = ocl_protect_check,
+       .info = ocl_info,
+       .auto_probe = ocl_auto_probe
+};
+
+typedef struct ocl_priv_s
+{
+       arm_jtag_t *jtag_info;
+       unsigned int buflen;
+       unsigned int bufalign;
+} ocl_priv_t;
+
+static int ocl_register_commands(struct command_context_s *cmd_ctx)
+{
+       return ERROR_OK;
+}
+
+static int ocl_erase_check(struct flash_bank_s *bank)
+{
+       return ERROR_OK;
+}
+
+static int ocl_protect_check(struct flash_bank_s *bank)
+{
+       return ERROR_OK;
+}
+
+/* flash_bank ocl 0 0 0 0 <target#> */
+static int ocl_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct flash_bank_s *bank)
+{
+       int retval;
+       armv4_5_common_t *armv4_5;
+       arm7_9_common_t *arm7_9;
+       ocl_priv_t *ocl;
+
+       if (argc < 6)
+       {
+               LOG_WARNING("incomplete flash_bank ocl configuration");
+               return ERROR_FLASH_BANK_INVALID;
+       }
+
+       if ((retval = arm7_9_get_arch_pointers(bank->target, &armv4_5, &arm7_9)) != ERROR_OK)
+               return retval;
+
+       ocl = bank->driver_priv = malloc(sizeof(ocl_priv_t));
+       ocl->jtag_info = &arm7_9->jtag_info;
+       ocl->buflen = 0;
+       ocl->bufalign = 1;
+
+       return ERROR_OK;
+}
+
+static int ocl_erase(struct flash_bank_s *bank, int first, int last)
+{
+       ocl_priv_t *ocl = bank->driver_priv;
+       int retval;
+       u32 dcc_buffer[3];
+
+       /* check preconditions */
+       if (bank->num_sectors == 0)
+               return ERROR_FLASH_BANK_NOT_PROBED;
+               
+       if (bank->target->state != TARGET_RUNNING)
+       {
+               LOG_ERROR("target has to be running to communicate with the loader");
+               return ERROR_TARGET_NOT_RUNNING;
+       }
+               
+       if ((first == 0) && (last == bank->num_sectors - 1))
+       {
+               dcc_buffer[0] = OCL_ERASE_ALL;
+               if ((retval = embeddedice_send(ocl->jtag_info, dcc_buffer, 1) != ERROR_OK))
+                       return retval;
+       }
+       else
+       {
+               dcc_buffer[0] = OCL_ERASE_BLOCK;
+               dcc_buffer[1] = first;
+               dcc_buffer[2] = last;
+               if ((retval = embeddedice_send(ocl->jtag_info, dcc_buffer, 3) != ERROR_OK))
+                       return retval;
+       }
+
+       /* wait for response, fixed timeout of 1 s */
+       if ((retval = embeddedice_handshake(ocl->jtag_info, EICE_COMM_CTRL_WBIT, 1000) != ERROR_OK))
+       {
+               if (retval == ERROR_TARGET_TIMEOUT)
+                       LOG_ERROR("loader not responding");
+               return retval;
+       }
+
+       /* receive response */
+       if ((retval = embeddedice_receive(ocl->jtag_info, dcc_buffer+1, 1) != ERROR_OK))
+               return retval;
+
+       if (dcc_buffer[1] != OCL_CMD_DONE)
+       {
+               if (dcc_buffer[0] == OCL_ERASE_ALL)
+                       LOG_ERROR("loader response to OCL_ERASE_ALL 0x%08X", dcc_buffer[1]);
+               else
+                       LOG_ERROR("loader response to OCL_ERASE_BLOCK 0x%08X", dcc_buffer[1]);
+               return ERROR_FLASH_OPERATION_FAILED;
+       }
+
+       return ERROR_OK;
+}
+
+static int ocl_protect(struct flash_bank_s *bank, int set, int first, int last)
+{
+       return ERROR_OK;
+}
+
+static int ocl_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count)
+{
+       ocl_priv_t *ocl = bank->driver_priv;
+       int retval;
+       u32 *dcc_buffer;
+       u32 *dcc_bufptr;
+       int byteofs;
+       int runlen;
+       u32 chksum;
+       
+       int i;
+
+       /* check preconditions */
+       if (ocl->buflen == 0 || ocl->bufalign==0)
+               return ERROR_FLASH_BANK_NOT_PROBED;
+
+       if (bank->target->state != TARGET_RUNNING)
+       {
+               LOG_ERROR("target has to be running to communicate with the loader");
+               return ERROR_TARGET_NOT_RUNNING;
+       }
+
+       /* allocate buffer for max. ocl buffer + overhead */
+       dcc_buffer = malloc(sizeof(u32)*(ocl->buflen/4+3));
+
+       while (count)
+       {
+               if (count + (offset % ocl->bufalign) > ocl->buflen)
+                       runlen = ocl->buflen - (offset % ocl->bufalign);
+               else
+                       runlen = count;
+
+               dcc_buffer[0] = OCL_FLASH_BLOCK | runlen;
+               dcc_buffer[1] = offset;
+               dcc_bufptr = &dcc_buffer[2];
+
+               *dcc_bufptr = 0xffffffff;
+               byteofs = (offset % ocl->bufalign) % 4;
+               chksum = OCL_CHKS_INIT;
+
+               /* copy data to DCC buffer in proper byte order and properly aligned */
+               for (i=0; i<runlen; i++)
+               {
+                       switch (byteofs++)
+                       {
+                               case 0:
+                                       *dcc_bufptr &= *(buffer++) | 0xffffff00;
+                                       break;
+                               case 1:
+                                       *dcc_bufptr &= ((*(buffer++))<<8) | 0xffff00ff;
+                                       break;
+                               case 2:
+                                       *dcc_bufptr &= ((*(buffer++))<<16) | 0xff00ffff;
+                                       break;
+                               case 3:
+                                       *dcc_bufptr &= ((*(buffer++))<<24) | 0x00ffffff;
+                                       chksum ^= *(dcc_bufptr++);
+                                       *dcc_bufptr = 0xffffffff;
+                                       byteofs = 0;
+                                       break;
+                       }
+               }
+
+               /* add the remaining word to checksum */
+               if (byteofs)
+                       chksum ^= *(dcc_bufptr++);
+
+               *(dcc_bufptr++) = chksum;
+               
+               /* send the data */
+               if ((retval = embeddedice_send(ocl->jtag_info, dcc_buffer, dcc_bufptr-dcc_buffer)) != ERROR_OK)
+               {
+                       free(dcc_buffer);
+                 return retval;
+               }
+
+               /* wait for response, fixed timeout of 1 s */
+               if ((retval = embeddedice_handshake(ocl->jtag_info, EICE_COMM_CTRL_WBIT, 1000) != ERROR_OK))
+               {
+                       if (retval == ERROR_TARGET_TIMEOUT)
+                               LOG_ERROR("loader not responding");
+                       free(dcc_buffer);
+                       return retval;
+               }
+
+               /* receive response */
+               if ((retval = embeddedice_receive(ocl->jtag_info, dcc_buffer, 1) != ERROR_OK))
+               {
+                       free(dcc_buffer);
+                       return retval;
+               }
+
+               if (dcc_buffer[0] != OCL_CMD_DONE)
+               {
+                       LOG_ERROR("loader response to OCL_FLASH_BLOCK 0x%08X", dcc_buffer[0]);
+                       free(dcc_buffer);
+                       return ERROR_FLASH_OPERATION_FAILED;
+               }
+
+               count -= runlen;
+               offset += runlen;
+       }
+
+       free(dcc_buffer);
+       return ERROR_OK;
+}
+
+static int ocl_probe(struct flash_bank_s *bank)
+{
+       ocl_priv_t *ocl = bank->driver_priv;
+       int retval;
+       u32 dcc_buffer[1];
+       int sectsize;
+       int i;
+
+       /* purge pending data in DCC */
+       embeddedice_receive(ocl->jtag_info, dcc_buffer, 1);
+
+       dcc_buffer[0] = OCL_PROBE;
+       if ((retval = embeddedice_send(ocl->jtag_info, dcc_buffer, 1) != ERROR_OK))
+               return retval;
+
+       /* wait for response, fixed timeout of 1 s */
+       if ((retval = embeddedice_handshake(ocl->jtag_info, EICE_COMM_CTRL_WBIT, 1000) != ERROR_OK))
+       {
+               if (retval == ERROR_TARGET_TIMEOUT)
+                       LOG_ERROR("loader not responding");
+               return retval;
+       }
+
+       /* receive response */
+       if ((retval = embeddedice_receive(ocl->jtag_info, dcc_buffer, 1) != ERROR_OK))
+               return retval;
+               
+       if (dcc_buffer[0] != OCL_CMD_DONE)
+       {
+               LOG_ERROR("loader response to OCL_PROBE 0x%08X", dcc_buffer[0]);
+               return ERROR_FLASH_OPERATION_FAILED;
+       }
+
+       /* receive and fill in parameters, detection of loader is important, receive it one by one */
+       if ((retval = embeddedice_handshake(ocl->jtag_info, EICE_COMM_CTRL_WBIT, 0) != ERROR_OK)
+               || (retval = embeddedice_receive(ocl->jtag_info, dcc_buffer, 1) != ERROR_OK))
+               return retval;
+       bank->base = dcc_buffer[0];
+
+       if ((retval = embeddedice_handshake(ocl->jtag_info, EICE_COMM_CTRL_WBIT, 0) != ERROR_OK)
+               || (retval = embeddedice_receive(ocl->jtag_info, dcc_buffer, 1) != ERROR_OK))
+               return retval;
+       bank->size = dcc_buffer[0];
+
+       if ((retval = embeddedice_handshake(ocl->jtag_info, EICE_COMM_CTRL_WBIT, 0) != ERROR_OK)
+               || (retval = embeddedice_receive(ocl->jtag_info, dcc_buffer, 1) != ERROR_OK))
+               return retval;
+       bank->num_sectors = dcc_buffer[0];
+
+       if ((retval = embeddedice_handshake(ocl->jtag_info, EICE_COMM_CTRL_WBIT, 0) != ERROR_OK)
+               || (retval = embeddedice_receive(ocl->jtag_info, dcc_buffer, 1) != ERROR_OK))
+               return retval;
+       ocl->buflen = dcc_buffer[0] & 0xffff;
+       ocl->bufalign = dcc_buffer[0] >> 16;
+
+       bank->sectors = realloc(bank->sectors, sizeof(flash_sector_t)*bank->num_sectors);
+       if (bank->num_sectors == 0)
+       {
+               LOG_ERROR("number of sectors shall be non zero value");
+               return ERROR_FLASH_BANK_INVALID;
+       }
+       if (bank->size % bank->num_sectors) {
+               LOG_ERROR("bank size not divisible by number of sectors");
+               return ERROR_FLASH_BANK_INVALID;
+       }
+       sectsize = bank->size / bank->num_sectors;
+       for (i=0; i<bank->num_sectors; i++)
+       {
+               bank->sectors[i].offset = i * sectsize;
+               bank->sectors[i].size = sectsize;
+               bank->sectors[i].is_erased = -1;
+               bank->sectors[i].is_protected = -1;
+       }
+
+       if (ocl->bufalign == 0)
+               ocl->bufalign = 1;
+
+       if (ocl->buflen == 0)
+       {
+               LOG_ERROR("buflen shall be non zero value");
+               return ERROR_FLASH_BANK_INVALID;
+       }
+
+       if ((ocl->bufalign > ocl->buflen) || (ocl->buflen % ocl->bufalign))
+       {
+               LOG_ERROR("buflen is not multiple of bufalign");
+               return ERROR_FLASH_BANK_INVALID;
+       }
+
+       if (ocl->buflen % 4)
+       {
+               LOG_ERROR("buflen shall be divisible by 4");
+               return ERROR_FLASH_BANK_INVALID;
+       }
+
+       return ERROR_OK;
+}
+
+static int ocl_info(struct flash_bank_s *bank, char *buf, int buf_size)
+{
+       return ERROR_OK;
+}
+
+static int ocl_auto_probe(struct flash_bank_s *bank)
+{
+       ocl_priv_t *ocl = bank->driver_priv;
+
+       if (ocl->buflen == 0 || ocl->bufalign==0)
+               return ERROR_FLASH_BANK_NOT_PROBED;
+
+       return ERROR_OK;
+}