diff -c -r -P gdb-5.3.original/gdb/Makefile.in gdb-5.3-bdm-683xx/gdb/Makefile.in *** gdb-5.3.original/gdb/Makefile.in Mon Nov 25 23:05:38 2002 --- gdb-5.3-bdm-683xx/gdb/Makefile.in Fri Aug 15 14:23:26 2003 *************** *** 1189,1194 **** --- 1189,1199 ---- version.o: version.c $(version_h) + + # m683xx BDM support + bdmlib.o: bdmlib.c bdmlib.h bdm.h + bdmflash.o: bdmflash.c bdmlib.h bdmflash.h bdm.h + # LANG-exp.tab.c is generated in objdir from LANG-exp.y if it doesn't # exist in srcdir, then compiled in objdir to LANG-exp.tab.o. *************** *** 1374,1379 **** --- 1379,1385 ---- remote-array.c remote-e7000.c \ remote-es.c remote-hms.c remote-mips.c \ remote-rdp.c remote-sim.c \ + remote-bdm.c \ remote-st.c remote-utils.c dcache.c \ remote-vx.c \ rs6000-nat.c rs6000-tdep.c \ *************** *** 1999,2004 **** --- 2005,2013 ---- $(gdb_string_h) $(command_h) $(serial_h) $(monitor_h) \ $(remote_utils_h) $(inferior_h) $(version_h) $(regcache_h) # OBSOLETE remote-bug.o: remote-bug.c + remote-bdm.o: remote-bdm.c bdmlib.h bdmflash.h bdm.h gdb_wait.h \ + $(command_h) $(defs_h) $(gdbcore_h) target.h + remote-e7000.o: remote-e7000.c $(defs_h) $(gdbcore_h) $(gdbarch_h) \ $(inferior_h) $(target_h) $(value_h) $(command_h) $(gdb_string_h) \ $(gdbcmd_h) $(serial_h) $(remote_utils_h) $(symfile_h) $(regcache_h) diff -c -r -P gdb-5.3.original/gdb/bdm.h gdb-5.3-bdm-683xx/gdb/bdm.h *** gdb-5.3.original/gdb/bdm.h Sat Nov 2 17:19:49 2002 --- gdb-5.3-bdm-683xx/gdb/bdm.h Wed Jun 4 03:31:32 2003 *************** *** 0 **** --- 1,115 ---- + #ifndef LINUX_BDM_H + #define LINUX_BDM_H + /* + * $Id: gdb-5.3-bdm-683xx-patch,v 1.2 2004/11/18 23:07:40 ppisa Exp $ + * + * Linux Device Driver for Public Domain BDM Interface + * based on the PD driver package by Scott Howard, Feb 93 + * ported to Linux by M.Schraut + * tested for kernel version 1.2.4 + * (C) 1995 Technische Universitaet Muenchen, Lehrstuhl fuer Prozessrechner + + 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, 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; see the file COPYING. If not, write to + the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + + */ + + #define BDM_MAJOR_NUMBER 53 + + /* error codes */ + #define BDM_FAULT_UNKNOWN -610 /*Error-definitions*/ + #define BDM_FAULT_POWER -611 + #define BDM_FAULT_CABLE -612 + #define BDM_FAULT_RESPONSE -613 /*NOT Ready */ + #define BDM_FAULT_RESET -614 + #define BDM_FAULT_PORT -615 + #define BDM_FAULT_BERR -616 + #define BDM_FAULT_NVC -617 /*no valid command */ + + /* Debug Levels */ + #define BDM_DEBUG_NONE 0 + #define BDM_DEBUG_SOME 1 + #define BDM_DEBUG_ALL 2 + + /* supported ioctls */ + #define BDM_INIT 0 /* no argument */ + #define BDM_DEINIT 1 /* no argument */ + #define BDM_RESET_CHIP 2 /* no argument */ + #define BDM_RESTART_CHIP 3 /* no argument */ + #define BDM_STOP_CHIP 4 /* no argument */ + #define BDM_STEP_CHIP 5 /* no argument */ + #define BDM_GET_STATUS 6 /* no argument */ + #define BDM_SPEED 7 /* arg = speed */ + #define BDM_RELEASE_CHIP 8 /* no argument */ + #define BDM_DEBUG_LEVEL 9 /* arg = level */ + #define BDM_GET_VERSION 10 /* arg = &int */ + #define BDM_SENSECABLE 11 /* arg =on/off */ + + #define BDM_NORETURN 0 /* no error, no ret value */ + /* functional bits of ioctl BDM_GET_STATUS */ + #define BDM_TARGETRESET (1<<0) /* Target reset */ + #define BDM_TARGETSTOPPED (1<<2) /* Target (was already) stopped */ + #define BDM_TARGETPOWER (1<<3) /* Power failed */ + #define BDM_TARGETNC (1<<4) /* Target not Connected */ + + /* command codes for bdm interface */ + #define BDM_RREG_CMD 0x2180 + #define BDM_WREG_CMD 0x2080 + #define BDM_RSREG_CMD 0x2580 + #define BDM_WSREG_CMD 0x2480 + #define BDM_READ_CMD 0x1900 + #define BDM_WRITE_CMD 0x1800 + #define BDM_DUMP_CMD 0x1d00 + #define BDM_FILL_CMD 0x1c00 + #define BDM_GO_CMD 0x0c00 + #define BDM_CALL_CMD 0x0800 + #define BDM_RST_CMD 0x0400 + #define BDM_NOP_CMD 0x0000 + + /* system register for RSREG/WSREG */ + #define BDM_REG_RPC 0x0 + #define BDM_REG_PCC 0x1 + #define BDM_REG_SR 0xb + #define BDM_REG_USP 0xc + #define BDM_REG_SSP 0xd + #define BDM_REG_SFC 0xe + #define BDM_REG_DFC 0xf + #define BDM_REG_ATEMP 0x8 + #define BDM_REG_FAR 0x9 + #define BDM_REG_VBR 0xa + + /* system register for RREG/WREG */ + #define BDM_REG_D0 0x0 + #define BDM_REG_D1 0x1 + #define BDM_REG_D2 0x2 + #define BDM_REG_D3 0x3 + #define BDM_REG_D4 0x4 + #define BDM_REG_D5 0x5 + #define BDM_REG_D6 0x6 + #define BDM_REG_D7 0x7 + #define BDM_REG_A0 0x8 + #define BDM_REG_A1 0x9 + #define BDM_REG_A2 0xa + #define BDM_REG_A3 0xb + #define BDM_REG_A4 0xc + #define BDM_REG_A5 0xd + #define BDM_REG_A6 0xe + #define BDM_REG_A7 0xf + + /* op size for READ/WRITE */ + #define BDM_SIZE_BYTE 0x0000 + #define BDM_SIZE_WORD 0x0040 + #define BDM_SIZE_LONG 0x0080 + + #endif diff -c -r -P gdb-5.3.original/gdb/bdmflash.c gdb-5.3-bdm-683xx/gdb/bdmflash.c *** gdb-5.3.original/gdb/bdmflash.c Sat Nov 2 17:19:49 2002 --- gdb-5.3-bdm-683xx/gdb/bdmflash.c Fri Aug 15 11:07:40 2003 *************** *** 0 **** --- 1,945 ---- + /******************************************************************* + Flash programming algorithms for use with BDM flash utility + + bdmflash.c - test driver implementation + + (C) Copyright 2000 by Pavel Pisa + + This souce is distributed under the Gnu General Public Licence. + See file COPYING for details. + + Source could be used under any other license for embeded systems, + but in such case enhancements must be sent to original author. + If some of contributors does not agree with above two lines, + he can delete them and only GPL will apply. + *******************************************************************/ + /* + Revision history + + 2001-01-16 Added experimental support of single 8 bit flash memory + based on Avi Cohen Stuart changes + + 2001-07-10 Added support for amd_29f010 with x8x2 configuration + based on John S. Gwynne changes + Trying to solve x8x2 race condition with shortest + possible code - needs more tests + + 2001-08-30 Added alg-info for at_49f040 with x8x2 configuration + x8x2 configuration needs more testing, may be broken + + 2003-05-19 Added initial support for x32 memory configurations. + The x16x2 and x8x4 should work as well. Changes were + motivated by Andrei Smirnov + code, but his small update results in deeper code redesign. + This could enable to support page writes for modern versions + of FLASH memories in future. + */ + + #include + #include "bdm.h" + #include "bdmlib.h" + #include "bdmflash.h" + + /* predefined flash algorithms metods */ + + int bdmflash_check_id_x32(const flash_alg_info_t *alg, void *addr, flash_d_t retid[2]); + int bdmflash_prog_x32(const flash_alg_info_t *alg, void *addr, const void *data, long count); + int bdmflash_erase_x32(const flash_alg_info_t *alg, void *addr, long size); + + int bdmflash_check_id_x16(const flash_alg_info_t *alg, void *addr, flash_d_t retid[2]); + int bdmflash_prog_x16(const flash_alg_info_t *alg, void *addr, const void *data, long count); + int bdmflash_erase_x16(const flash_alg_info_t *alg, void *addr, long size); + + int bdmflash_check_id_x8(const flash_alg_info_t *alg, void *addr, flash_d_t retid[2]); + int bdmflash_prog_x8(const flash_alg_info_t *alg, void *addr, const void *data, long count); + int bdmflash_erase_x8(const flash_alg_info_t *alg, void *addr, long size); + + /* predefined flash types */ + + flash_alg_info_t amd_29f800_x16={ + check_id: bdmflash_check_id_x16, + prog: bdmflash_prog_x16, + erase: bdmflash_erase_x16, + addr_mask: 0xfffff, /* 1MB */ + reg1_addr: 0x555*2, + reg2_addr: 0x2aa*2, + sec_size: 0x10000, + width: FLASH_ALG_BITS_x16, + cmd_unlock1:0xaa, /* reg1 */ + cmd_unlock2:0x55, /* reg2 */ + cmd_rdid: 0x90, /* reg1 */ + cmd_prog: 0xa0, /* reg1 */ + cmd_erase: 0x80, /* reg1 */ + cmd_reset: 0xf0, /* any */ + erase_all: 0x10, /* reg1 */ + erase_sec: 0x30, /* sector */ + fault_bit: 0x20, + manid: 1, + devid: 0x2258, + alg_name: "amd29f800" + }; + + flash_alg_info_t amd_29f400_x16={ + check_id: bdmflash_check_id_x16, + prog: bdmflash_prog_x16, + erase: bdmflash_erase_x16, + addr_mask: 0x7ffff, /* 0.5MB */ + reg1_addr: 0x555*2, + reg2_addr: 0x2aa*2, + sec_size: 0x10000, + width: FLASH_ALG_BITS_x16, + cmd_unlock1:0xaa, /* reg1 */ + cmd_unlock2:0x55, /* reg2 */ + cmd_rdid: 0x90, /* reg1 */ + cmd_prog: 0xa0, /* reg1 */ + cmd_erase: 0x80, /* reg1 */ + cmd_reset: 0xf0, /* any */ + erase_all: 0x10, /* reg1 */ + erase_sec: 0x30, /* sector */ + fault_bit: 0x20, + manid: 1, + devid: 0x22ab, + alg_name: "amd29f400" + }; + + flash_alg_info_t amd_29f040_x8={ + check_id: bdmflash_check_id_x8, + prog: bdmflash_prog_x8, + erase: bdmflash_erase_x8, + addr_mask: 0x7ffff, /* 0.5MB */ + reg1_addr: 0x555, + reg2_addr: 0x2aa, + sec_size: 0x10000, + width: FLASH_ALG_BITS_x8, + cmd_unlock1:0xaa, /* reg1 */ + cmd_unlock2:0x55, /* reg2 */ + cmd_rdid: 0x90, /* reg1 */ + cmd_prog: 0xa0, /* reg1 */ + cmd_erase: 0x80, /* reg1 */ + cmd_reset: 0xf0, /* any */ + erase_all: 0x10, /* reg1 */ + erase_sec: 0x30, /* sector */ + fault_bit: 0x20, + manid: 1, + devid: 0xa4, + alg_name: "amd29f040" + }; + + flash_alg_info_t amd_29f010_x8x2={ + check_id: bdmflash_check_id_x16, + prog: bdmflash_prog_x16, + erase: bdmflash_erase_x16, + addr_mask: 0x3ffff, /* 2x128kB = 256kB */ + reg1_addr: 0x5555*2, + reg2_addr: 0x2aaa*2, + sec_size: 0x10000, + width: FLASH_ALG_BITS_x8x2, + cmd_unlock1:0xaaaa, /* reg1 */ + cmd_unlock2:0x5555, /* reg2 */ + cmd_rdid: 0x9090, /* reg1 */ + cmd_prog: 0xa0a0, /* reg1 */ + cmd_erase: 0x8080, /* reg1 */ + cmd_reset: 0xf0f0, /* any */ + erase_all: 0x1010, /* reg1 */ + erase_sec: 0x3030, /* sector */ + fault_bit: 0x2020, + manid: 0x0101, + devid: 0x2020, + alg_name: "amd29f010x2" + }; + + flash_alg_info_t at_49f040_x8x2={ + check_id: bdmflash_check_id_x16, + prog: bdmflash_prog_x16, + erase: bdmflash_erase_x16, + addr_mask: 0xfffff, /* 2x0.5MB = 1MB */ + reg1_addr: 0x5555*2, + reg2_addr: 0x2aaa*2, + sec_size: 0x10000, + width: FLASH_ALG_BITS_x8x2, + cmd_unlock1:0xaaaa, /* reg1 */ + cmd_unlock2:0x5555, /* reg2 */ + cmd_rdid: 0x9090, /* reg1 */ + cmd_prog: 0xa0a0, /* reg1 */ + cmd_erase: 0x8080, /* reg1 */ + cmd_reset: 0xf0f0, /* any */ + erase_all: 0x1010, /* reg1 */ + erase_sec: 0x3030, /* sector */ + fault_bit: 0x2020, + manid: 0x1F1F, + devid: 0x1313, + alg_name: "at49f040x2" + }; + + #ifdef WITH_TARGET_BUS32 + + flash_alg_info_t amd_29f080_x8x4={ + check_id: bdmflash_check_id_x32, + prog: bdmflash_prog_x32, + erase: bdmflash_erase_x32, + addr_mask: 0x3fffff, /* 4x1MB */ + reg1_addr: 0x555*4, + reg2_addr: 0x2aa*4, + sec_size: 0x10000, + width: FLASH_ALG_BITS_x8x4, + cmd_unlock1:0xaaaaaaaa, /* reg1 */ + cmd_unlock2:0x55555555, /* reg2 */ + cmd_rdid: 0x90909090, /* reg1 */ + cmd_prog: 0xa0a0a0a0, /* reg1 */ + cmd_erase: 0x80808080, /* reg1 */ + cmd_reset: 0xf0f0f0f0, /* any */ + erase_all: 0x10101010, /* reg1 */ + erase_sec: 0x30303030, /* sector */ + fault_bit: 0x20202020, + manid: 0x01010101, + devid: 0xd5d5d5d5, + alg_name: "amd29f080x4" + }; + + #endif /* WITH_TARGET_BUS32 */ + + /* please keep sorted by flash sizes, smallest first */ + flash_alg_info_t *flash_alg_infos_def[]={ + &amd_29f010_x8x2, /* 256 kB */ + &amd_29f040_x8, /* 512 kB */ + &amd_29f400_x16, /* 512 kB */ + &amd_29f800_x16, /* 1 MB */ + &at_49f040_x8x2, /* 1 MB */ + #ifdef WITH_TARGET_BUS32 + &amd_29f080_x8x4, /* 4 MB */ + #endif /* WITH_TARGET_BUS32 */ + NULL + }; + + flash_alg_info_t **flash_alg_infos=flash_alg_infos_def; + + #if 0 + #define FLASH_WR32(adr,val) (*(volatile u_int32_t*)(adr)=(val)) + #define FLASH_RD32(adr) (*(volatile u_int32_t*)(adr)) + #define FLASH_WR16(adr,val) (*(volatile u_int16_t*)(adr)=(val)) + #define FLASH_RD16(adr) (*(volatile u_int16_t*)(adr)) + #define FLASH_WR8(adr,val) (*(volatile u_int8_t*)(adr)=(val)) + #define FLASH_RD8(adr) (*(volatile u_int8_t*)(adr)) + #else + #define FLASH_WR32(adr,val) \ + ({ \ + if(bdmlib_write_var(adr,BDM_SIZE_LONG,val)<0) \ + goto mem_op_error; \ + val; \ + }) + #define FLASH_RD32(adr) \ + ({ u_int32_t temp_val; \ + if(bdmlib_read_var(adr,BDM_SIZE_LONG,&temp_val)<0) \ + goto mem_op_error; \ + temp_val; \ + }) + #define FLASH_WR16(adr,val) \ + ({ \ + if(bdmlib_write_var(adr,BDM_SIZE_WORD,val)<0) \ + goto mem_op_error; \ + val; \ + }) + #define FLASH_RD16(adr) \ + ({ u_int16_t temp_val; \ + if(bdmlib_read_var(adr,BDM_SIZE_WORD,&temp_val)<0) \ + goto mem_op_error; \ + temp_val; \ + }) + #define FLASH_WR8(adr,val) \ + ({ \ + if(bdmlib_write_var(adr,BDM_SIZE_BYTE,val)<0) \ + goto mem_op_error; \ + val; \ + }) + #define FLASH_RD8(adr) \ + ({ u_int8_t temp_val; \ + if(bdmlib_read_var(adr,BDM_SIZE_BYTE,&temp_val)<0) \ + goto mem_op_error; \ + temp_val; \ + }) + #endif + + + + static + int bdmflash_prepval_x16(u_int16_t *pval, void *addr, const void *data, long count) + { + if(!((long)addr&1) && (count>=2)){ + *pval=(((u_char*)data)[0]<<8)|(((u_char*)data)[1]); + return 2; + } + if(!count) return count; + if(!((long)addr&1)){ + *pval=(((u_char*)data)[0]<<8) | FLASH_RD8((u_char*)addr+1); + }else{ + *pval=(FLASH_RD8((u_char*)addr-1)<<8) | (((u_char*)data)[0]); + } + return 1; + + mem_op_error: + return -4; + } + + #ifdef WITH_TARGET_BUS32 + static + int bdmflash_prepval_x32(u_int32_t *pval, void *addr, const void *data, long count) + { + int offs=(long)addr&3; + int rest=4-offs; + u_int32_t val=0; + if(!offs && (count>=4)){ + *pval=((u_int32_t)((u_char*)data)[0]<<24)|((u_int32_t)((u_char*)data)[1]<<16)| + (((u_char*)data)[2]<<8)|(((u_char*)data)[3]); + return 4; + } + if(!count) return count; + if(count>rest) count=rest; + while(offs){ + val<<=8; + val|=FLASH_RD8((u_char*)addr-offs); + offs--; + } + while(offsaddr_mask); + /* reset */ + FLASH_WR16(a,alg->cmd_reset); + /* security sequence */ + FLASH_WR16(a+alg->reg1_addr,alg->cmd_unlock1); + if(alg->cmd_unlock2) + FLASH_WR16(a+alg->reg2_addr,alg->cmd_unlock2); + /* read manufacturer ID */ + FLASH_WR16(a+alg->reg1_addr,alg->cmd_rdid); + manid=FLASH_RD16(a+0); + if(manid!=alg->manid) ret=-1; + /* reset */ + FLASH_WR16(a,alg->cmd_reset); + /* security sequence */ + FLASH_WR16(a+alg->reg1_addr,alg->cmd_unlock1); + if(alg->cmd_unlock2) + FLASH_WR16(a+alg->reg2_addr,alg->cmd_unlock2); + /* read device ID */ + FLASH_WR16(a+alg->reg1_addr,alg->cmd_rdid); + devid=FLASH_RD16(a+2); + if(devid!=alg->devid) ret=-1; + /* reset */ + FLASH_WR16(a,alg->cmd_reset); + if(retid) + {retid[0]=manid;retid[1]=devid;}; + return ret; + + mem_op_error: + return -5; + } + + int bdmflash_prog_x16(const flash_alg_info_t *alg, void *addr, const void *data, long count) + { + int ret; + u_int16_t old,new,fault,val; + caddr_t a=(caddr_t)((u_int32_t)addr&~alg->addr_mask); + ret=bdmflash_prepval_x16(&val,addr,data,count); + if(ret<=0) + return ret; + addr=(void*)((long)addr&~1l); + /* check if FLASH needs programming */ + if(1){ + old=FLASH_RD16(addr); + if(old==val) return ret; + } + /* security sequence */ + FLASH_WR16(a+alg->reg1_addr,alg->cmd_unlock1); + if(alg->cmd_unlock2) + FLASH_WR16(a+alg->reg2_addr,alg->cmd_unlock2); + /* program command */ + FLASH_WR16(a+alg->reg1_addr,alg->cmd_prog); + FLASH_WR16(addr,val); + /* wait for result */ + old=FLASH_RD16(addr); + while((new=FLASH_RD16(addr))!=old){ + if((fault=old&new&alg->fault_bit)){ + old=new; + /* check for some false fault at finish or race of x8x2 */ + if(!(old^=(new=FLASH_RD16(addr)))) break; /* finished now */ + else{ + /* one chip of x8x2 configuration can finish earlier */ + if(!(old&0x00ff)||(fault&0x00ff)) + if(!(old&0xff00)||(fault&0xff00)) + {ret=-2;break;} + } + } + old=new; + } + /* reset */ + FLASH_WR16(a,alg->cmd_reset); + if((FLASH_RD16(addr)!=val) && (ret>=0)) ret=-3; + + return ret; + + mem_op_error: + return -5; + } + + int bdmflash_erase_x16(const flash_alg_info_t *alg, void *addr, long size) + { + u_int16_t old,new,fault; + int ret=0; + caddr_t a=(caddr_t)((u_int32_t)addr&~alg->addr_mask); + /* reset */ + FLASH_WR16(a,alg->cmd_reset); + /* security sequence */ + FLASH_WR16(a+alg->reg1_addr,alg->cmd_unlock1); + if(alg->cmd_unlock2) + FLASH_WR16(a+alg->reg2_addr,alg->cmd_unlock2); + /* erase command */ + FLASH_WR16(a+alg->reg1_addr,alg->cmd_erase); + /* security sequence */ + FLASH_WR16(a+alg->reg1_addr,alg->cmd_unlock1); + if(alg->cmd_unlock2) + FLASH_WR16(a+alg->reg2_addr,alg->cmd_unlock2); + /* select erase range */ + a=addr; + if(size==0) + FLASH_WR16(a+alg->reg1_addr,alg->erase_all); + else{ + FLASH_WR16(addr,alg->erase_sec); + } + /* wait for result */ + old=FLASH_RD16(addr); + while((new=FLASH_RD16(addr))!=old){ + if((fault=old&new&alg->fault_bit)){ + old=new; + /* check for some false fault at finish or race of x8x2 */ + if(!(old^=(new=FLASH_RD16(addr)))) break; /* finished now */ + else{ + /* one chip of x8x2 configuration can finish earlier */ + if(!(old&0x00ff)||(fault&0x00ff)) + if(!(old&0xff00)||(fault&0xff00)) + {ret=-2;break;} + } + } + old=new; + } + /* reset */ + FLASH_WR16(a,alg->cmd_reset); + if(FLASH_RD16(addr)!=0xffff) ret--; + return ret; + + mem_op_error: + return -5; + } + + /*******************************************************************/ + /* routines for single 8 bit wide Intel or AMD flash */ + + int bdmflash_check_id_x8(const flash_alg_info_t *alg, void *addr, + flash_d_t retid[2]) + { + int ret=0; + u_int16_t devid, manid; + caddr_t a=(caddr_t)((u_int32_t)addr&~alg->addr_mask); + /* reset */ + FLASH_WR8(a,alg->cmd_reset); + /* security sequence */ + FLASH_WR8(a+alg->reg1_addr,alg->cmd_unlock1); + if(alg->cmd_unlock2) + FLASH_WR8(a+alg->reg2_addr,alg->cmd_unlock2); + /* read manufacturer ID */ + FLASH_WR8(a+alg->reg1_addr,alg->cmd_rdid); + manid=FLASH_RD8(a+0); + if(manid!=alg->manid) ret=-1; + /* reset */ + FLASH_WR8(a,alg->cmd_reset); + /* security sequence */ + FLASH_WR8(a+alg->reg1_addr,alg->cmd_unlock1); + if(alg->cmd_unlock2) + FLASH_WR8(a+alg->reg2_addr,alg->cmd_unlock2); + /* read device ID */ + FLASH_WR8(a+alg->reg1_addr,alg->cmd_rdid); + devid=FLASH_RD8(a+1); + if(devid!=alg->devid) ret=-1; + /* reset */ + FLASH_WR8(a,alg->cmd_reset); + if(retid) + {retid[0]=manid;retid[1]=devid;}; + return ret; + + mem_op_error: + return -5; + } + + int bdmflash_prog_x8(const flash_alg_info_t *alg, void *addr, const void *data, long count) + { + int ret=1; + u_int8_t old,new,val; + caddr_t a=(caddr_t)((u_int32_t)addr&~alg->addr_mask); + val=*(u_int8_t*)data; + /* check if FLASH needs programming */ + if(1){ + old=FLASH_RD8(addr); + if(old==val) return ret; + } + /* security sequence */ + FLASH_WR8(a+alg->reg1_addr,alg->cmd_unlock1); + if(alg->cmd_unlock2) + FLASH_WR8(a+alg->reg2_addr,alg->cmd_unlock2); + /* program command */ + FLASH_WR8(a+alg->reg1_addr,alg->cmd_prog); + FLASH_WR8(addr,val); + /* wait for result */ + old=FLASH_RD8(addr); + while((new=FLASH_RD8(addr))!=old){ + if((old&alg->fault_bit)&&(new&alg->fault_bit)){ + if((FLASH_RD8(addr))!=new) ret=-2; + break; + } + old=new; + } + /* reset */ + FLASH_WR8(a,alg->cmd_reset); + if((FLASH_RD8(addr)!=val) && (ret>=0)) ret=-3; + return ret; + + mem_op_error: + return -5; + } + + int bdmflash_erase_x8(const flash_alg_info_t *alg, void *addr, long size) + { + u_int8_t old,new; + int ret=0; + caddr_t a=(caddr_t)((u_int32_t)addr&~alg->addr_mask); + /* reset */ + FLASH_WR8(a,alg->cmd_reset); + /* security sequence */ + FLASH_WR8(a+alg->reg1_addr,alg->cmd_unlock1); + if(alg->cmd_unlock2) + FLASH_WR8(a+alg->reg2_addr,alg->cmd_unlock2); + /* erase command */ + FLASH_WR8(a+alg->reg1_addr,alg->cmd_erase); + /* security sequence */ + FLASH_WR8(a+alg->reg1_addr,alg->cmd_unlock1); + if(alg->cmd_unlock2) + FLASH_WR8(a+alg->reg2_addr,alg->cmd_unlock2); + /* select erase range */ + a=addr; + if(size==0) + FLASH_WR8(a+alg->reg1_addr,alg->erase_all); + else{ + FLASH_WR8(addr,alg->erase_sec); + } + old=FLASH_RD8(addr); + while((new=FLASH_RD8(addr))!=old){ + if((old&alg->fault_bit)&&(new&alg->fault_bit)){ + if((FLASH_RD8(addr))!=new) ret=-2; + break; + } + old=new; + } + /* reset */ + FLASH_WR8(a,alg->cmd_reset); + if(FLASH_RD16(addr)!=0xffff) ret--; + return ret; + + mem_op_error: + return -5; + } + + + /*******************************************************************/ + /* routines for two/four interleaved 16/8 bit wide Intel or AMD flashes */ + + #ifdef WITH_TARGET_BUS32 + + int bdmflash_check_id_x32(const flash_alg_info_t *alg, void *addr, flash_d_t retid[2]) + { + int ret=0; + u_int32_t devid, manid; + caddr_t a=(caddr_t)((u_int32_t)addr&~alg->addr_mask); + /* reset */ + FLASH_WR32(a,alg->cmd_reset); + /* security sequence */ + FLASH_WR32(a+alg->reg1_addr,alg->cmd_unlock1); + if(alg->cmd_unlock2) + FLASH_WR32(a+alg->reg2_addr,alg->cmd_unlock2); + /* read manufacturer ID */ + FLASH_WR32(a+alg->reg1_addr,alg->cmd_rdid); + /* bank slecets swapped as i suspect (360DK only) !!!!!! */ + /*manid=FLASH_RD32(a+0xc); */ + manid=FLASH_RD32(a+0); + if(manid!=alg->manid) ret=-1; + /* reset */ + FLASH_WR32(a,alg->cmd_reset); + /* security sequence */ + FLASH_WR32(a+alg->reg1_addr,alg->cmd_unlock1); + if(alg->cmd_unlock2) + FLASH_WR32(a+alg->reg2_addr,alg->cmd_unlock2); + /* read device ID */ + FLASH_WR32(a+alg->reg1_addr,alg->cmd_rdid); + devid=FLASH_RD32(a+4); + if(devid!=alg->devid) ret=-1; + /* reset */ + FLASH_WR32(a,alg->cmd_reset); + if(retid) + {retid[0]=manid;retid[1]=devid;}; + return ret; + + mem_op_error: + return -5; + } + + int bdmflash_prog_x32(const flash_alg_info_t *alg, void *addr, const void *data, long count) + { + int ret=4; + u_int32_t old,new,fault,val; + caddr_t a=(caddr_t)((u_int32_t)addr&~alg->addr_mask); + ret=bdmflash_prepval_x32(&val,addr,data,count); + if(ret<=0) + return ret; + addr=(void*)((long)addr&~3l); + /* check if FLASH needs programming */ + if(1){ + old=FLASH_RD32(addr); + if(old==val) return ret; + } + /* security sequence */ + FLASH_WR32(a+alg->reg1_addr,alg->cmd_unlock1); + if(alg->cmd_unlock2) + FLASH_WR32(a+alg->reg2_addr,alg->cmd_unlock2); + /* program command */ + FLASH_WR32(a+alg->reg1_addr,alg->cmd_prog); + FLASH_WR32(addr,val); + /* wait for result */ + old=FLASH_RD32(addr); + while((new=FLASH_RD32(addr))!=old){ + if((fault=old&new&alg->fault_bit)){ + old=new; + /* check for some false fault at finish or race of x8x2 */ + if(!(old^=(new=FLASH_RD32(addr)))) break; /* finished now */ + else{ + /* one chip of x16x2 or x8x4 configuration can finish earlier */ + if(!(old&0x000000ff)||(fault&0x000000ff)) + if(!(old&0x0000ff00)||(fault&0x0000ff00)) + if(!(old&0x00ff0000)||(fault&0x00ff0000)) + if(!(old&0xff000000)||(fault&0xff000000)) + {ret=-2;break;} + } + } + old=new; + } + /* reset */ + FLASH_WR32(a,alg->cmd_reset); + if((FLASH_RD32(addr)!=val) && (ret>=0)) ret=-3; + + return ret; + + mem_op_error: + return -5; + } + + + int bdmflash_erase_x32(const flash_alg_info_t *alg, void *addr, long size) + { + u_int32_t old,new,fault; + int ret=0; + caddr_t a=(caddr_t)((u_int32_t)addr&~alg->addr_mask); + /* reset */ + FLASH_WR32(a,alg->cmd_reset); + /* security sequence */ + FLASH_WR32(a+alg->reg1_addr,alg->cmd_unlock1); + if(alg->cmd_unlock2) + FLASH_WR32(a+alg->reg2_addr,alg->cmd_unlock2); + /* erase command */ + FLASH_WR32(a+alg->reg1_addr,alg->cmd_erase); + /* security sequence */ + FLASH_WR32(a+alg->reg1_addr,alg->cmd_unlock1); + if(alg->cmd_unlock2) + FLASH_WR32(a+alg->reg2_addr,alg->cmd_unlock2); + /* select erase range */ + a=addr; + if(size==0) + FLASH_WR32(a+alg->reg1_addr,alg->erase_all); + else{ + FLASH_WR32(addr,alg->erase_sec); + } + /* wait for result */ + old=FLASH_RD32(addr); + while((new=FLASH_RD32(addr))!=old){ + if((fault=old&new&alg->fault_bit)){ + old=new; + /* check for some false fault at finish or race of x16x2 or x8x4 */ + if(!(old^=(new=FLASH_RD32(addr)))) break; /* finished now */ + else{ + /* one chip of x16x2 or x8x4 configuration can finish earlier */ + if(!(old&0x000000ff)||(fault&0x000000ff)) + if(!(old&0x0000ff00)||(fault&0x0000ff00)) + if(!(old&0x00ff0000)||(fault&0x00ff0000)) + if(!(old&0xff000000)||(fault&0xff000000)) + {ret=-2;break;} + } + } + old=new; + } + /* reset */ + FLASH_WR32(a,alg->cmd_reset); + if(FLASH_RD32(addr)!=0xffffffff) ret--; + return ret; + + mem_op_error: + return -5; + } + + + #endif /* WITH_TARGET_BUS32 */ + + /*******************************************************************/ + + /* flash type independent check_id */ + int bdmflash_check_id(const flash_alg_info_t *alg, void *addr, flash_d_t retid[2]) + { + if(alg->check_id) + return alg->check_id(alg, addr, retid); + else + return -10; /* we really need to define error constants in future */ + } + + /* flash type independent program one location */ + int bdmflash_prog(const flash_alg_info_t *alg, void *addr, const void *data, long count) + { + if(alg->prog) + return alg->prog(alg,addr,data,count); + else + return -10; + } + + /* flash type independent erase region */ + int bdmflash_erase(const flash_alg_info_t *alg, void *addr, long size) + { + if(alg->erase) + return alg->erase(alg,addr,size); + else + return -10; + } + + const flash_alg_info_t * + bdmflash_alg_from_id(flash_d_t id[2]) + { + int i; + const flash_alg_info_t *alg; + for(i=0;(alg=flash_alg_infos_def[i])!=NULL;i++) + if((alg->manid==id[0])&&(alg->devid==id[0])) + return alg; + return NULL; + } + + const flash_alg_info_t * + bdmflash_alg_probe(caddr_t flash_adr) + { + int i; + const flash_alg_info_t *alg,*alg1; + flash_d_t testid[2]; + for(i=0;(alg=flash_alg_infos_def[i])!=NULL;i++){ + if(bdmflash_check_id(alg,flash_adr,testid)>=0) + return alg; + alg1=bdmflash_alg_from_id(testid); + if(alg1!=NULL) + if(bdmflash_check_id(alg1,flash_adr,testid)>=0) + return alg1; + } + return NULL; + } + + int + bdmflash_wrb_filt(bdmlib_bfilt_t * filt, caddr_t in_adr, + u_int size, u_char * bl_ptr) + { + int offs=0,res; + flash_d_t val; + const flash_alg_info_t *alg=(flash_alg_info_t*)filt->info; + + #if 0 + if(alg->width!=FLASH_ALG_BITS_x8) { + /* 16 bit wide flash write path */ + if((u_long)in_adr&1) { + in_adr-=1; + val=(FLASH_RD16(in_adr)&0xff00)|bl_ptr[offs]; + if((res=bdmflash_prog(alg, in_adr, val))<0) { + fprintf(stderr, "flash byte write error %d at 0x%lx\n", + res,(u_long)in_adr); + return offs; + } + in_adr+=2; + size-=1; + offs+=1; + } + while(size>=2) { + val=(bl_ptr[offs]<<8)|bl_ptr[offs+1]; + if((res=bdmflash_prog(alg, in_adr, val))<0) { + fprintf(stderr, "flash write error %d at 0x%lx\n", + res,(u_long)in_adr); + return offs; + } + in_adr+=2; + size-=2; + offs+=2; + } + if(size) { + val=(FLASH_RD16(in_adr)&0x00ff)|(bl_ptr[offs]<<8); + if((res=bdmflash_prog(alg, in_adr, val))<0) { + fprintf(stderr, "flash byte write error %d at 0x%lx\n", + res,(u_long)in_adr); + return offs; + } + size-=1; + offs+=1; + } + } + #endif + + while(size>=1) { + val=bl_ptr[offs]; + if((res=bdmflash_prog(alg, in_adr, bl_ptr+offs, size))<=0) { + fprintf(stderr, "flash write error %d at 0x%lx\n", + res,(u_long)in_adr); + return offs; + } + in_adr+=res; + size-=res; + offs+=res; + } + return offs; + + #if 0 + mem_op_error: + fprintf(stderr, "bdm memory access error\n"); + return 0; + #endif + } + + int + bdmflash_erase_filt(bdmlib_bfilt_t * filt, caddr_t in_adr, + u_int size) + { + int res=0; + const flash_alg_info_t *alg=(flash_alg_info_t*)filt->info; + if(!in_adr) in_adr=filt->begin_adr; + + res=bdmflash_erase(alg, in_adr,size); + if(res<0) + fprintf(stderr, "flash erase error %d\n",res); + return res; + } + + #if 0 + + /* slow version of blank check */ + int + bdmflash_blankck_filt(bdmlib_bfilt_t * filt, caddr_t in_adr, + u_int size) + { + int errors=0; + if(!in_adr||!size){ + in_adr=filt->begin_adr; + size=filt->end_adr-in_adr+1; + } + if(((long)in_adr&1)&&size){ + if(FLASH_RD8(in_adr)!=0xff){ + fprintf(stderr,"blank check error at 0x%06lX",(long)in_adr); + errors++; + } + in_adr++; size--; + } + while(size>=2){ + if(FLASH_RD16(in_adr)!=0xffff){ + if(errors<5){ + if(errors) fprintf(stderr,",0x%06lX",(long)in_adr); + else fprintf(stderr,"blank check error at 0x%06lX",(long)in_adr); + }else if(errors==5) fprintf(stderr, " and more"); + errors++; + } + if(!((long)in_adr&0xfff)) bdmlib_propeller(stdout); + in_adr+=2; size-=2; + } + if(size){ + if(FLASH_RD8(in_adr)!=0xff){ + if(errors) fprintf(stderr,",0x%06lX",(long)in_adr); + else fprintf(stderr,"blank check error at 0x%06lX",(long)in_adr); + errors++; + } + } + if(errors) fprintf(stderr,"\n"); + + return errors; + + mem_op_error: + fprintf(stderr, "bdm memory access error\n"); + return -5; + } + + #else + + /* hopefully faster version of blank check */ + int + bdmflash_blankck_filt(bdmlib_bfilt_t * filt, caddr_t in_adr, + u_int size) + { + int errors=0, in_buf; + u_char buf[1024], *p; + if(!in_adr||!size){ + in_adr=filt->begin_adr; + size=filt->end_adr-in_adr+1; + } + + while(size){ + if(size + + #define FLASH_ALG_BITS_x8 0 + #define FLASH_ALG_BITS_x16 2 + #define FLASH_ALG_BITS_x8x2 3 + #define FLASH_ALG_BITS_x32 4 + #define FLASH_ALG_BITS_x16x2 5 + #define FLASH_ALG_BITS_x8x4 7 + + #define WITH_TARGET_BUS32 + + #ifndef WITH_TARGET_BUS32 + typedef u_int16_t flash_d_t; /* Type able to store one flash location */ + #else /* WITH_TARGET_BUS32 */ + typedef u_int32_t flash_d_t; /* Type able to store one flash location */ + #endif /* WITH_TARGET_BUS32 */ + + /* Structure describing programming operations for flash type */ + typedef struct flash_alg_info { + /* Sets retid to manufacturer and type ID, returns <0 in case of error */ + int (*check_id)(const struct flash_alg_info *alg, void *addr, flash_d_t retid[2]); + /* Programs one location of flash and returns number of programmed bytes */ + int (*prog)(const struct flash_alg_info *alg, void *addr, const void *data, long count); + /* Erase all sectors overlaped by region from addr of size bytes, size=0 => erase all */ + /* This version is capable only of full erase (size=0) and one sector (size=1) */ + int (*erase)(const struct flash_alg_info *alg, void *addr, long size); + /* Numeric and string fields follows */ + u_int32_t addr_mask; /* Mask to take offset inside flash */ + u_int32_t reg1_addr; /* Flash control register 1 */ + u_int32_t reg2_addr; /* Flash control register 2 */ + u_int32_t sec_size; /* block size of bigger blocks */ + flash_d_t width; /* FLASH_ALG_BITS_x8 .. 8 bit data bus, + FLASH_ALG_BITS_x16 .. 16 bit data, + FLASH_ALG_BITS_x8x2 .. two interleaved 8 bit */ + flash_d_t cmd_unlock1;/* first byte of command sequence */ + flash_d_t cmd_unlock2;/* second byte of command sequence */ + flash_d_t cmd_rdid; /* read identifier */ + flash_d_t cmd_prog; /* program one loc */ + flash_d_t cmd_erase; /* erase command */ + flash_d_t cmd_reset; /* leave program mode */ + flash_d_t erase_all; /* erase all */ + flash_d_t erase_sec; /* erase sector */ + flash_d_t fault_bit; /* programing of location failed */ + flash_d_t manid; /* manufacturer ID */ + flash_d_t devid; /* device ID */ + char *alg_name; /* informative flash type name */ + } flash_alg_info_t; + + int bdmflash_check_id(const flash_alg_info_t *alg, void *addr, + flash_d_t retid[2]); + + int bdmflash_prog(const flash_alg_info_t *alg, void *addr, const void *data, long count); + + int bdmflash_erase(const flash_alg_info_t *alg, void *addr, long size); + + flash_alg_info_t **flash_alg_infos; + + const flash_alg_info_t *bdmflash_alg_from_id(flash_d_t id[2]); + + const flash_alg_info_t *bdmflash_alg_probe(caddr_t flash_adr); + + int bdmflash_wrb_filt(bdmlib_bfilt_t * filt, caddr_t in_adr, + u_int size, u_char * bl_ptr); + + int bdmflash_erase_filt(bdmlib_bfilt_t * filt, caddr_t in_adr, u_int size); + + int bdmflash_blankck_filt(bdmlib_bfilt_t * filt, caddr_t in_adr, u_int size); + + int bdmflash_check_id(const flash_alg_info_t *alg, void *addr, flash_d_t retid[2]); + + #endif /* BDMFLASH_H */ diff -c -r -P gdb-5.3.original/gdb/bdmlib.c gdb-5.3-bdm-683xx/gdb/bdmlib.c *** gdb-5.3.original/gdb/bdmlib.c Sat Nov 2 17:19:49 2002 --- gdb-5.3-bdm-683xx/gdb/bdmlib.c Thu Nov 18 23:59:30 2004 *************** *** 0 **** --- 1,1694 ---- + /* + * $Id: gdb-5.3-bdm-683xx-patch,v 1.2 2004/11/18 23:07:40 ppisa Exp $ + * + * Remote debugging interface for 683xx via Background Debug Mode + * needs a driver, which controls the BDM interface. + * written by G.Magin + * (C) 1996 Technische Universitaet Muenchen, Lehrstuhl fuer Prozessrechner + * (C) 1997 G. Magin + * + * Modified by Pavel Pisa pisa@cmp.felk.cvut.cz 1998 + + 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, 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; see the file COPYING. If not, write to + the Free Software Foundation, 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + */ + + /* + * NOTE: + * This file is assumed to be runnable only on Linux/i386 because of + * HW-restrictions: the driver is currently only available on i386-Linux + * So byte-swapping and alignment is handled directly, violating the + * GNU-coding standards. However, the "dirty spots" are restricted in this + * file. The accompanying application backend file (e.g. remote-bdm.c for + * gdb) is not affected by this restriction. + * + * If anybody wants to port to e.g. Sparc, byte-sex has to be handled in + * a more general way. + */ + + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + + /* #define SUPPORT_RAMINIT 0 */ /* force ram_init to be loaded */ + #define RAMINIT_FILENAME "ram_init" + #define RESETINIT_FILENAME "cpu32init" + #define END_MACRO 0 + #define BEGIN_MACRO 1 + #define NO_SUFFIX_MACRO 2 + #define BDMLIB_REQUIRED_DRIVER_VERSION 2 + /* + * version 1 (cannot be accessed by ioctl): release 3/95 + * version 2 (includes SENSE ioctl + ICD): release 7/96 + */ + + #ifdef BDMLIB_FORGDB + #include "defs.h" + #endif + + #ifndef PROTO + /* this is missing in current ansidecl.h - remove it later gm */ + #if defined (__STDC__) || defined (_AIX) || (defined (__mips) && defined (_SYSTYPE_SVR4)) + + #define PROTO(type, name, arglist) type name arglist + #define PARAMS(paramlist) paramlist + #define ANSI_PROTOTYPES 1 + + #else /* Not ANSI C. */ + + #define PROTO(type, name, arglist) type name () + #define PARAMS(paramlist) () + + #endif /* ANSI C. */ + #endif + + #include + #include "bdmlib.h" + #include "bdm.h" + + + static int bdm_fd; + + /* default delay for interface */ + #define BDM_DEFAULT_DELAY 75 + static int bdm_delay=-1; + + #define BDM_DODPRINTF (1<<0) + #define BDM_GOTEXCEPTION (1<<1) + #define BDM_DEBUG_NAME "bdm-dbg.log" + static int bdm_flags = 0; + static int mbar_used = 0; + static u_long mbar_default_val = 0; + extern char hashmark; + extern int bdm_autoreset; + extern int bdm_ttcu; + + + static void dbprintf(const char *format, ...); + + #if !defined BDMLIB_FORGDB + /* + * this is borrowed from gdb utils.c + */ + static void + error(const char *format, ...) + { + va_list args; + + va_start(args, format); + vfprintf(stderr, format, args); + fprintf(stderr, "\n"); + va_end(args); + } + + static void + fprintf_filtered(FILE *fp, const char *format, ...) + { + va_list args; + + va_start(args, format); + vfprintf(fp, format, args); + fprintf(fp, "\n"); + va_end(args); + } + + #define printf_filtered printf + #define xmalloc malloc + #define gdb_stderr stderr + #endif + + void + bdmlib_setdebug(int switch_on) + { + if (switch_on) + bdm_flags |= BDM_DODPRINTF; + else + bdm_flags &= ~BDM_DODPRINTF; + dbprintf("Setting Debug to %d\n", switch_on); + } + + int + bdmlib_querydebug(void) + { + return (bdm_flags & BDM_DODPRINTF); + } + + /* startofcleanup */ + int + bdmlib_isopen(void) + { + return (bdm_fd != 0); + } + + /* filter to put out bdm specific status messages */ + char * + bdmlib_getstatus_str(bdmstatus status) + { + int st; + static char put_buffer[128]; + + *put_buffer = '\0'; + st = (int) status; + if (st < 0) { + return bdmlib_geterror_str(status); + } + if (status & BDM_TARGETNC) { + strcat(put_buffer, "NotConnected "); + return put_buffer; + } + strcat(put_buffer, "Connected "); + if (status & BDM_TARGETPOWER) { + strcat(put_buffer, "PowerFail "); + return put_buffer; + } + strcat(put_buffer, "PowerOK "); + if (status & BDM_TARGETSTOPPED) + strcat(put_buffer, "Frozen "); + else + strcat(put_buffer, "Running "); + if (status & BDM_TARGETRESET) + strcat(put_buffer, "Reset "); + return put_buffer; + } + + static struct _err_messages { + int err_num; + char *err_msg; + } + + err_messages[] = { + { BDM_FAULT_UNKNOWN, "bdm driver recognized unknown fault" } , + { BDM_FAULT_POWER, "target power failed" } , + { BDM_FAULT_CABLE, "cable disconnected" } , + { BDM_FAULT_RESPONSE, "no response from target via bdm" } , + { BDM_FAULT_RESET, "target got a reset" } , + { BDM_FAULT_PORT, "wrong bdm port" } , + { BDM_FAULT_BERR, "bus error occured on access via bdm" } , + { BDM_FAULT_NVC, "bdm internal error: no valid command to bdm" } , + { BDM_NO_ERROR, "No error" } , + { BDM_ERR_NOT_OPEN, "bdm device is not open" } , + { BDM_ERR_ILL_IOCTL, "ioctl code does not match library ioctl type" } , + { BDM_ERR_WRITE_FAIL, "write to processor failed" } , + { BDM_ERR_READ_FAIL, "read from processor failed" } , + { BDM_ERR_ILL_SIZE, "illegal variable size" } , + { BDM_ERR_OPEN, "open error" } , + { BDM_ERR_LOAD, "error on loading binary file" } , + { BDM_ERR_MACROFILE, "error on loading macro" } , + { BDM_ERR_SECTION, "error on loading section" } , + { BDM_ERR_VERSION, "driver version conflict" } , + }; + + static int err_msg_len = sizeof(err_messages) / sizeof(struct _err_messages); + + /* filter to pick out bdm specific error messages */ + char * + bdmlib_geterror_str(int err) + { + int i; + static char put_buffer[128]; + + for (i = 0; i < err_msg_len; i++) { + if (err == err_messages[i].err_num) + return err_messages[i].err_msg; + } + strncpy(put_buffer, strerror(-err), 128); + return put_buffer; + } + + #define do_case(x) case x: ret = #x; break; + + static char * + bdmlib_getioctlname(int ioctl) + { + char *ret; + switch (ioctl) { + do_case(BDM_INIT); + do_case(BDM_DEINIT); + do_case(BDM_RESET_CHIP); + do_case(BDM_RESTART_CHIP); + do_case(BDM_STOP_CHIP); + do_case(BDM_STEP_CHIP); + do_case(BDM_GET_STATUS); + do_case(BDM_SPEED); + do_case(BDM_RELEASE_CHIP); + do_case(BDM_DEBUG_LEVEL); + do_case(BDM_GET_VERSION); + do_case(BDM_SENSECABLE); + default: + ret = "Unknown ioctl"; + } + return ret; + } + + int + bdmlib_setioctl(u_int code, u_int val) + { + if (bdmlib_isopen()) { + switch (code) { + case BDM_SENSECABLE: + case BDM_DEBUG_LEVEL: + break; + case BDM_SPEED: + bdm_delay = val; break; + default: + return BDM_ERR_ILL_IOCTL; + } + return ioctl(bdm_fd, code, (u_long) val); + } else { + return BDM_ERR_NOT_OPEN; + } + } + + int + bdmlib_ioctl(u_int code) + { + int ret; + if (bdmlib_isopen()) { + switch (code) { + case BDM_INIT: + case BDM_RESET_CHIP: + case BDM_STOP_CHIP: + case BDM_RESTART_CHIP: + case BDM_RELEASE_CHIP: + case BDM_STEP_CHIP: + + if ((ret = ioctl(bdm_fd, code, (u_long) NULL)) == -1) { + dbprintf("bdmlib_ioctl %s failed; error %d %s\n", + bdmlib_getioctlname(code), errno, + bdmlib_geterror_str(errno)); + return -errno; + } else { + return BDM_NO_ERROR; + } + break; + default: + return BDM_ERR_ILL_IOCTL; + } + } else { + return BDM_ERR_NOT_OPEN; + } + } + + /* + * get status of interface + */ + bdmstatus + bdmlib_getstatus(void) + { + if (bdmlib_isopen()) { + return ioctl(bdm_fd, BDM_GET_STATUS, NULL); + } else { + return BDM_ERR_NOT_OPEN; + } + } + + int + bdmlib_go(void) + { + u_short buf; + int ret; + + dbprintf("bdmlib_go\n"); + + #if MORE_DEBUGGING + bdmlib_showpc(); + #endif /* MORE_DEBUGGING */ + + if (bdmlib_isopen()) { + buf = BDM_GO_CMD; + ret = write(bdm_fd, &buf, 2); + if ((ret < 0) || (ret != 2)) { + dbprintf("bdm_go: write_error %d\n", errno); + return -errno; + } + } else { + return BDM_ERR_NOT_OPEN; + } + return BDM_NO_ERROR; + } + + int + bdmlib_set_mbar(u_long mbar_val) + { + int ret; + bdmlib_set_sys_reg(BDM_REG_DFC, 7); + bdmlib_set_sys_reg(BDM_REG_SFC, 7); + ret = bdmlib_write_var((caddr_t)0x3ff00, BDM_SIZE_LONG, mbar_val); + if(ret >= 0){ + mbar_used = 1; + mbar_default_val = mbar_val; + } + bdmlib_set_sys_reg(BDM_REG_DFC, 5); + bdmlib_set_sys_reg(BDM_REG_SFC, 5); + return ret; + } + + int + bdmlib_reset(void) + { + int ret; + + dbprintf("bdmlib_reset ttcu %d\n", bdm_ttcu); + if ((ret = bdmlib_ioctl(BDM_RESTART_CHIP))) { + return ret; + } + + #if MORE_DEBUGGING + printf("bdmlib_reset: RESTART_CHIP replies %d %s\n", + ret, bdmlib_geterror_str(ret)); + printf("status: %s\n", bdmlib_getstatus_str(bdmlib_getstatus())); + #endif /* MORE_DEBUGGING */ + + /* + * it cannot break anything to set right SFC and DFC + * adress space for memory accesses + */ + + bdmlib_set_sys_reg(BDM_REG_DFC, 5); + bdmlib_set_sys_reg(BDM_REG_SFC, 5); + + /* + * The 68360 targets requires setup of MBAR to enable access + * to integrated modules and system configuration registers + */ + + if(mbar_used) { + bdmlib_set_mbar(mbar_default_val); + } + + /* + * in case we have a monitor in place, we might want to let him do + * the basic setup, let it come to the prompt... + */ + if (bdm_ttcu) { + if ((ret = bdmlib_go())) /* let the monitor come up.... */ + return ret; + usleep(bdm_ttcu); + ret = bdmlib_ioctl(BDM_STOP_CHIP); + } + + #if SUPPORT_RAMINIT + if ((ret = bdmlib_do_load_binary(RAMINIT_FILENAME, 0, 0)) < 0) { + fprintf_filtered(gdb_stderr, "Warning: %s for file `%s'\n", + bdmlib_geterror_str(ret), + RAMINIT_FILENAME); + } + #endif /* SUPPORT_RAMINIT */ + + bdmlib_do_load_macro(RESETINIT_FILENAME, NO_SUFFIX_MACRO); + fprintf(stdout, "\r"); fflush(stdout); + return ret; + } + + #define swaps(x) \ + ((u_short)((((u_short)(x) & 0x00ff) << 8) | \ + (((u_short)(x) & 0xff00) >> 8))) + + #define swapl(x) \ + ((u_int)((((u_int)(x) & 0x000000ffU) << 24) | \ + (((u_int)(x) & 0x0000ff00U) << 8) | \ + (((u_int)(x) & 0x00ff0000U) >> 8) | \ + (((u_int)(x) & 0xff000000U) >> 24))) + + static u_short * + bdmlib_conv_short_to_buf(u_short * buf, u_short val, int endianness) + { + if (endianness) { + *buf++ = swaps(val); + } else { + *buf++ = val; + } + return buf; + } + + /* conv long in host format (little endian) to buf (target format = big e) */ + static u_short * + bdmlib_conv_long_to_buf(u_short * buf, u_long val, int endianness) + { + if (endianness) { + *buf++ = swaps(val & 0xffff); + *buf++ = swaps(val >> 16); + } else { + *buf++ = val >> 16; + *buf++ = val & 0xffff; + } + return buf; + } + + /* buf representation to a single short */ + static u_short * + bdmlib_conv_buf_to_short(u_short * buf, u_short * val, int endianness) + { + if (endianness) { + *val = *buf++; + } else { + *val = swaps(*buf); + buf++; + } + return buf; + } + + /* buf representation to a single long */ + static u_short * + bdmlib_conv_buf_to_long(u_short * buf, u_long * val, int endianness) + { + if (endianness) { + *val = (buf[0] << 16) | buf[1]; + } else { + *val = (swaps(buf[1]) << 16) | swaps(buf[0]); + } + buf += 2; + return buf; + } + + /* + * put a char stream of 4 bytes into a long; + * endianness=0: interprete char as little end + * else interprete char as big endian + */ + static u_char * + bdmlib_conv_char_to_long(u_char * buf, u_long * val, int endianness) + { + int i; + union { + u_long l; + u_char c[4]; + } u; + + if (endianness) { + for (i = 3; i >= 0; i--) + u.c[i] = *buf++; + } else { + for (i = 0; i < 4; i++) + u.c[i] = *buf++; + } + *val = u.l; + return buf; + } + + /* put a char stream of 2 bytes into a short */ + static u_char * + bdmlib_conv_char_to_short(u_char * buf, u_short * val, int endianness) + { + int i; + union { + u_short s; + u_char c[2]; + } u; + + if (endianness) { + for (i = 1; i >= 0; i--) + u.c[i] = *buf++; + } else { + for (i = 0; i < 2; i++) + u.c[i] = *buf++; + } + *val = u.s; + return buf; + } + + /* put a long to a char stream */ + static u_char * + bdmlib_conv_long_to_char(u_char * buf, u_long val, int endianness) + { + int i; + union { + u_long l; + u_char c[4]; + } u; + + u.l = val; + if (endianness) { + for (i = 3; i >= 0; i--) + *buf++ = u.c[i]; + } else { + for (i = 0; i < 4; i++) + *buf++ = u.c[i]; + } + return buf; + } + + /* put a short to a char stream */ + static u_char * + bdmlib_conv_short_to_char(u_char * buf, u_short val, int endianness) + { + int i; + union { + u_short s; + u_char c[2]; + } u; + + u.s = val; + if (endianness) { + for (i = 1; i >= 0; i--) + *buf++ = u.c[i]; + } else { + for (i = 0; i < 2; i++) + *buf++ = u.c[i]; + } + return buf; + } + + int + bdmlib_get_sys_reg(u_int reg, u_int * ret_val) + { + u_short send; + u_short recv[2]; + int ret; + + send = BDM_RSREG_CMD | (reg & 0xf); + if (!bdmlib_isopen()) + return BDM_ERR_NOT_OPEN; + ret = write(bdm_fd, &send, 2); + if (ret == 2) { + ret = read(bdm_fd, recv, 4); + } else { + dbprintf("bdmlib_get_sys_reg error on send: errno %d\n", errno); + return -errno; + } + bdmlib_conv_buf_to_long(recv, (u_long *) ret_val, 0); + return (ret == 4) ? BDM_NO_ERROR : -errno; + } + + int + bdmlib_set_sys_reg(u_int reg, u_int cont) + { + u_short send[3]; + int ret; + + if (!bdmlib_isopen()) + return BDM_ERR_NOT_OPEN; + send[0] = BDM_WSREG_CMD | (reg & 0xf); + bdmlib_conv_long_to_buf(&send[1], cont, 0); + if ((ret = write(bdm_fd, send, 6)) != 6) { + dbprintf("bdmlib_set_sys_reg error: reg %#x cont %#x error %d\n", + reg, cont, errno); + return -errno; + } + return BDM_NO_ERROR; + } + + int + bdmlib_get_reg(u_int reg, u_int * ret_val) + { + u_short send; + u_short recv[2]; + int ret; + + if (!bdmlib_isopen()) + return BDM_ERR_NOT_OPEN; + send = BDM_RREG_CMD | (reg & 0xf); + ret = write(bdm_fd, &send, 2); + if (ret == 2) { + ret = read(bdm_fd, recv, 4); + } else { + dbprintf("bdmlib_get_reg: error on send ret %d\n", errno); + return -errno; + } + /* get target format, as conversion will be done in higher levels */ + bdmlib_conv_buf_to_long(recv, (u_long *) ret_val, 0); + return (ret == 4) ? BDM_NO_ERROR : -errno; + } + + int + bdmlib_set_reg(u_int reg, u_int cont) + { + u_short send[3]; + int ret; + + if (!bdmlib_isopen()) + return BDM_ERR_NOT_OPEN; + send[0] = BDM_WREG_CMD | (reg & 0xf); + bdmlib_conv_long_to_buf(&send[1], cont, 0); + if ((ret = write(bdm_fd, send, 6)) != 6) { + dbprintf("bdmlib_set_reg error: reg %#x to cont %#x error %#d\n", + reg, cont, errno); + return -errno; + } + return BDM_NO_ERROR; + } + + int + bdmlib_write_var(caddr_t adr, u_short size, u_int val) + { + u_short buf[6], *b_ptr = buf; + int w_buf_len, r_buf_len; + int written; + + dbprintf("bdmlib_write_var: addr %#x cont %#x\n", adr, val); + if (!bdmlib_isopen()) + return BDM_ERR_NOT_OPEN; + size &= 0x00c0; + *b_ptr++ = (BDM_WRITE_CMD | size); + /* no need for byte swapping, as adr is already a valid long; so use 0 */ + b_ptr = bdmlib_conv_long_to_buf(b_ptr, (u_long) adr, 0); + switch (size) { + case BDM_SIZE_LONG: + b_ptr = bdmlib_conv_long_to_buf(b_ptr, val, 0); + w_buf_len = 5; + break; + case BDM_SIZE_WORD: + b_ptr = bdmlib_conv_short_to_buf(b_ptr, val, 0); + w_buf_len = 4; + break; + case BDM_SIZE_BYTE: + *b_ptr++ = (u_short) (val & 0xff); + w_buf_len = 4; + break; + default: + w_buf_len = 0; + dbprintf("error! bdmlib_write_var: unknown size %#x\n", size); + return BDM_ERR_ILL_SIZE; + } + if ((written = write(bdm_fd, buf, w_buf_len * 2)) != w_buf_len * 2) { + dbprintf("error! bdmlib_write_var: write returns %d errno %d\n", + written, errno); + written = errno; + } + if ((r_buf_len = read(bdm_fd, buf, 2)) != 2) { + dbprintf( + "bdmlib_write_var: verify read return val expected 2 is %d errno %d\n", + r_buf_len, errno); + return -errno; + } + if (written == (w_buf_len*2)) { + return BDM_NO_ERROR; + } else { + return -written; + } + } + + + + #if 1 + + /* slower but reliable method for writting, main solved problem is + waiting for ready after memory access achieved by read + in bdm_write_var */ + + int + bdmlib_write_block(caddr_t in_adr, u_int size, u_char * bl_ptr) + { + u_short buf[8]; + int fills, got_size = 0; + u_long ul; + u_short us; + u_char uc; + u_int first_acc; + + dbprintf("bdmlib_write_block size %#x to adr %#x ", size, in_adr); + first_acc = 4 - ((u_long) in_adr & 0x3); + if (size < first_acc) { + switch (size) { + case 0: return 0; + case 1: first_acc = 1; break; + case 2: + case 3: first_acc = first_acc&1? 1: 2; break; + } + } + switch (first_acc) { + case 4: + bl_ptr = bdmlib_conv_char_to_long(bl_ptr, &ul, 1); + if (bdmlib_write_var(in_adr, BDM_SIZE_LONG, ul) < 0) { + return got_size; + } + got_size += 4; + break; + case 3: + uc = *bl_ptr++; + if (bdmlib_write_var(in_adr, BDM_SIZE_BYTE, uc) < 0) { + return got_size; + } + in_adr += 1; + got_size += 1; + /* fall through to 'word' */ + case 2: + bl_ptr = bdmlib_conv_char_to_short(bl_ptr, &us, 1); + if (bdmlib_write_var(in_adr, BDM_SIZE_WORD, us) < 0) { + return got_size; + } + got_size += 2; + break; + case 1: + uc = *bl_ptr++; + if (bdmlib_write_var(in_adr, BDM_SIZE_BYTE, uc) < 0) { + return got_size; + } + got_size += 1; + break; + default: ; + /* cannot happen */ + } + + + buf[0] = BDM_FILL_CMD | BDM_SIZE_LONG; + fills = (size - got_size) / 4; + while (fills--) { + bl_ptr = bdmlib_conv_char_to_long(bl_ptr, &ul, 1); + bdmlib_conv_long_to_buf(&buf[1], ul, 0); + if (write(bdm_fd, &buf[0], 6) !=6) { + return got_size; + } + if (read(bdm_fd, &buf[1], 2) != 2) { + return got_size; + } + got_size += 4; + } + + if (size - got_size >= 2) { + buf[0] = (BDM_FILL_CMD | BDM_SIZE_WORD); + bl_ptr = bdmlib_conv_char_to_short(bl_ptr, &us, 1); + bdmlib_conv_short_to_buf(&buf[1], us, 0); + if(write(bdm_fd, &buf[0], 4)!=4) return got_size; + if (read(bdm_fd, &buf[0], 2) != 2) return got_size; + got_size += 2; + } + if (size - got_size) { + buf[0] = (BDM_FILL_CMD | BDM_SIZE_BYTE); + buf[1] = *bl_ptr++; + if(write(bdm_fd, &buf[0], 4)!=4) return got_size; + if (read(bdm_fd, &buf[0], 2) != 2) return got_size; + got_size += 1; + } + if (size - got_size) { /* cannot happen */ + error("internal error: bdmlib_write_block - cannot happen"); + } + + return got_size; + } + + #else + + int + bdmlib_write_block(caddr_t in_adr, u_int size, u_char * block) + { + u_short *buf, *buf_ptr; + int buf_len = 0; /* valid len of buf to writecmd in shorts */ + u_char *bl_ptr; + u_int adr; + int fills, put_size; + u_long ul; + u_short us; + u_int first_acc; + + dbprintf("bdmlib_write_block size %#x to adr %#x\n", size, in_adr); + if (!bdmlib_isopen()) + return BDM_ERR_NOT_OPEN; + first_acc = 4 - ((u_long) in_adr & 0x3); + if (size < first_acc) { + switch (size) { + case 0: return 0; + case 1: first_acc = 1; break; + case 2: + case 3: first_acc = first_acc&1? 1: 2; break; + } + } + + put_size = size; + adr = (u_int) in_adr; + bl_ptr = block; + buf_ptr = buf = xmalloc((size / 4 + 5) * 6); + + /* + * per 4 bytes 3 shorts for fill-long-cmd + * + 3 short for initial write-long-cmd + addr + * = 1 * 3 shorts + * + worst case both a write-byte and write-short on begin & end + * = 4 * 3 shorts + */ + + switch (first_acc) { + case 4: + *buf_ptr++ = (BDM_WRITE_CMD | BDM_SIZE_LONG); + *buf_ptr++ = (adr & 0xffff0000) >> 16; /* h-Address */ + *buf_ptr++ = (adr & 0x0000ffff); /* l-Address */ + bl_ptr = bdmlib_conv_char_to_long(bl_ptr, &ul, 1); + buf_ptr = bdmlib_conv_long_to_buf(buf_ptr, ul, 0); + adr += 4; + size -= 4; + buf_len = 5; + break; + case 3: + *buf_ptr++ = (BDM_WRITE_CMD | BDM_SIZE_BYTE); + *buf_ptr++ = (adr & 0xffff0000) >> 16; /* h-Address */ + *buf_ptr++ = (adr & 0x0000ffff); /* l-Address */ + *buf_ptr++ = *bl_ptr++; + adr += 1; + size -= 1; + buf_len = 4; + /* fall through to 'word' */ + case 2: + *buf_ptr++ = (BDM_WRITE_CMD | BDM_SIZE_WORD); + *buf_ptr++ = (adr & 0xffff0000) >> 16; /* h-Address */ + *buf_ptr++ = (adr & 0x0000ffff); /* l-Address */ + bl_ptr = bdmlib_conv_char_to_short(bl_ptr, &us, 1); + buf_ptr = bdmlib_conv_short_to_buf(buf_ptr, us, 0); + adr += 2; + size -= 2; + buf_len += 4; + break; + case 1: + *buf_ptr++ = (BDM_WRITE_CMD | BDM_SIZE_BYTE); + *buf_ptr++ = (adr & 0xffff0000) >> 16; /* h-Address */ + *buf_ptr++ = (adr & 0x0000ffff); /* l-Address */ + *buf_ptr++ = *bl_ptr++; + adr += 1; + size -= 1; + buf_len = 4; + break; + default: + /* cannot happen */ + } + fills = size / 4; + size -= fills * 4; + buf_len += (fills * 3); + while (fills--) { + *buf_ptr++ = (BDM_FILL_CMD | BDM_SIZE_LONG); + bl_ptr = bdmlib_conv_char_to_long(bl_ptr, &ul, 1); + buf_ptr = bdmlib_conv_long_to_buf(buf_ptr, ul, 0); + } + + if(size>=2){ + *buf_ptr++ = (BDM_FILL_CMD | BDM_SIZE_WORD); + bl_ptr = bdmlib_conv_char_to_short(bl_ptr, &us, 1); + buf_ptr = bdmlib_conv_short_to_buf(buf_ptr, us, 0); + buf_len += 2; + size -= 2; + } + if(size>=1){ + *buf_ptr++ = (BDM_FILL_CMD | BDM_SIZE_BYTE); + *buf_ptr++ = *bl_ptr; + buf_len += 2; + size--; + } + if(size){ + error("internal error: bdmlib_write_block: size=%d!=0",size); + } + + /* now we have a whole buf we can send in one chunk to 'write' */ + + buf_len *= 2; /* now buflen in bytes */ + if ((size = write(bdm_fd, buf, buf_len)) != buf_len) { + dbprintf("error! bdmlib_write_block: write %d returns %d errno %d %s\n", + buf_len, size, errno, bdmlib_geterror_str(-errno)); + put_size = 0; + } + /* + * FIXME: needs more persistence on trying to write; analyze reason + * for not writing, and if possible, try again with rest of the buf + * give up on detected bus-err + */ + + free(buf); + return put_size; + } + + + #endif + + /* return format in *val is target byte ordering */ + int + bdmlib_read_var(caddr_t adr, u_short size, void *val) + { + u_short buf[6], *b_ptr = buf; + int count; + + /* u_char *cptr; u_short *sptr; u_long *lptr; */ + + dbprintf("bdmlib_read_var size %#x from adr %#x ", size, adr); + if (!bdmlib_isopen()) + return BDM_ERR_NOT_OPEN; + size &= 0x00c0; + *b_ptr++ = (BDM_READ_CMD | size); + /* no need for byte swapping, as adr is already a valid long; so use 0 */ + b_ptr = bdmlib_conv_long_to_buf(b_ptr, (u_long) adr, 0); + if ((count = write(bdm_fd, buf, 6)) != 6) { + dbprintf("bdmlib_read_var error: write returns %d\n", count); + return BDM_ERR_WRITE_FAIL; + } + switch (size) { + case BDM_SIZE_LONG: + if ((count = read(bdm_fd, buf, 4)) == 4) { + *(u_long *) val = (buf[0] << 16) | buf[1]; + } + break; + case BDM_SIZE_WORD: + if ((count = read(bdm_fd, buf, 2)) == 2) { + *(u_short *) val = (u_short) buf[0]; + /* sptr = (u_short*) val; *sptr = (u_short) buf[0]; */ + } + break; + case BDM_SIZE_BYTE: + if ((count = read(bdm_fd, buf, 2)) == 2) { + count = 1; + *(u_char *) val = (u_char) (buf[0] & 0xff); + /* cptr = (u_char*)val; *cptr = (u_char) (buf[0] & 0xff); */ + } + break; + default: + dbprintf("\n\terror! bdmlib_read_var: unknown size %#x\n", size); + } + if (count < 0) { + dbprintf("\nerror %d (%s)\n", errno, bdmlib_geterror_str(errno)); + return -errno; + } + /* val = (u_int*) ((u_long)val & ~3); */ + dbprintf(" cont %#x\n", *(u_long *) ((long) val & ~3)); + return count; /* _must_ return count */ + } + + int + bdmlib_read_block(caddr_t in_adr, u_int size, u_char * bl_ptr) + { + u_short buf[8]; + u_short dump_cmd; + int dumps, got_size = 0; + u_long ul; + u_short us; + u_char uc; + u_int first_acc; + + dbprintf("bdmlib_read_block size %#x from adr %#x ", size, in_adr); + first_acc = 4 - ((u_long) in_adr & 0x3); + if (size < first_acc) { + switch (size) { + case 0: return 0; + case 1: first_acc = 1; break; + case 2: + case 3: first_acc = first_acc&1? 1: 2; break; + } + } + switch (first_acc) { + case 4: + if (bdmlib_read_var(in_adr, BDM_SIZE_LONG, &ul) != 4) { + return got_size; + } + bl_ptr = bdmlib_conv_long_to_char(bl_ptr, ul, 1); + got_size += 4; + break; + case 3: + if (bdmlib_read_var(in_adr, BDM_SIZE_BYTE, &uc) != 1) { + return got_size; + } + *bl_ptr++ = uc; + got_size += 1; + in_adr += 1; + /* fall through to 'word' */ + case 2: + if (bdmlib_read_var(in_adr, BDM_SIZE_WORD, &us) != 2) { + return got_size; + } + bl_ptr = bdmlib_conv_short_to_char(bl_ptr, us, 1); + got_size += 2; + break; + case 1: + if (bdmlib_read_var(in_adr, BDM_SIZE_BYTE, &uc) != 1) { + return got_size; + } + *bl_ptr++ = uc; + got_size += 1; + break; + default: ; + /* cannot happen */ + } + + + dump_cmd = BDM_DUMP_CMD | BDM_SIZE_LONG; + dumps = (size - got_size) / 4; + while (dumps--) { + write(bdm_fd, &dump_cmd, 2); + if (read(bdm_fd, &buf, 4) != 4) { + return got_size; + } + bdmlib_conv_buf_to_long(buf, &ul, 1); + bl_ptr = bdmlib_conv_long_to_char(bl_ptr, ul, 1); + got_size += 4; + } + + if (size - got_size >= 2) { + dump_cmd = BDM_DUMP_CMD | BDM_SIZE_WORD; + write(bdm_fd, &dump_cmd, 2); + if (read(bdm_fd, &buf, 2) != 2) { + return got_size; + } + bdmlib_conv_buf_to_short(buf, &us, 1); + bl_ptr = bdmlib_conv_short_to_char(bl_ptr, us, 1); + got_size += 2; + } + if (size - got_size) { + dump_cmd = BDM_DUMP_CMD | BDM_SIZE_BYTE; + write(bdm_fd, &dump_cmd, 2); + if (read(bdm_fd, &buf, 2) != 2) { + return got_size; + } + *bl_ptr++ = *buf & 0xff; + got_size += 1; + } + if (size - got_size) { /* cannot happen */ + error("internal error: bdmlib_read_block - cannot happen"); + } + + return got_size; + } + + void + bdmlib_propeller(u_long addr, FILE * fp) + { + static char *str = "\\|/-"; + static int index; + + if (!hashmark) return; + fprintf(fp, "%c 0x%08lx\b\b\b\b\b\b\b\b\b\b\b\b", str[index++], addr); + fflush(fp); + index %= 4; + } + + /* + * Open a connection the target via bdm + * name is the devicename of bdm and the filename to be used + * used for communication. + */ + int + bdmlib_open(char *name) + { + int ret; + int version; + + if (bdmlib_isopen()) { + dbprintf("bdmlib_open: tried to open twice\n"); + return BDM_ERR_OPEN; + } + if ((bdm_fd = open(name, O_RDWR)) < 0) { + dbprintf( + "bdmlib_open: Warning trouble on opening %s: reply %d errno %d\n", + name, bdm_fd, errno); + fprintf(stderr, "Warning: trouble on opening %s: %s\n", name, + bdmlib_geterror_str(-errno)); + bdm_fd = 0; /* mark unused */ + return BDM_FAULT_PORT; + } + bdmlib_ioctl(BDM_INIT); + if (bdm_delay>=0) { + /* delay has been set before */ + bdmlib_setioctl(BDM_SPEED, bdm_delay); + } else { + bdmlib_setioctl(BDM_SPEED, BDM_DEFAULT_DELAY); + } + + if (((ret = ioctl(bdm_fd, BDM_GET_VERSION, (u_long) &version)) < 0) || + (version < BDMLIB_REQUIRED_DRIVER_VERSION)) { + if (ret < 0) version = 1; + fprintf(stderr, "Error:\tBDM device driver version conflict.\n"); + fprintf(stderr, + "\tyou need at least version %d, currently installed is version %d.\n", + BDMLIB_REQUIRED_DRIVER_VERSION, version); + fprintf(stderr, "\tAborting operation\n"); + close(bdm_fd); + return BDM_ERR_VERSION; + } + return BDM_NO_ERROR; + } + + int + bdmlib_close(quitting) + int quitting; + { + dbprintf("bdmlib_close: quitting %d\n", quitting); + + if (quitting) { + bdmlib_reset(); + bdmlib_ioctl(BDM_RELEASE_CHIP); + } + close(bdm_fd); + bdm_fd = 0; + return BDM_NO_ERROR; + } + + #define swap_l(x) (x>>24) | ((x>>8)&0xff00) | ((x<<8)&0xff0000) | ((x&0xff)<<24) + + void + bdmlib_showpc(void) + { + u_int sr, usp, ssp, vbr; + u_int pcc, rpc, a7; + + bdmlib_get_sys_reg(BDM_REG_SR, &sr); + bdmlib_get_sys_reg(BDM_REG_USP, &usp); + bdmlib_get_reg(BDM_REG_A7, &a7); + bdmlib_get_sys_reg(BDM_REG_SSP, &ssp); + printf(" SR: %9x USP: %9x A7: %9x SSP: %9x\n", + swap_l(sr), swap_l(usp), swap_l(a7), swap_l(ssp)); + + bdmlib_get_sys_reg(BDM_REG_PCC, &pcc); + bdmlib_get_sys_reg(BDM_REG_RPC, &rpc); + bdmlib_get_sys_reg(BDM_REG_VBR, &vbr); + printf("PCC: %9x RPC: %9x VBR: %9x\n", + swap_l(pcc), swap_l(rpc), swap_l(vbr)); + } + + #define LINE_LEN 256 + static char * + get_line(FILE * f, int *line_nr) + { + static char line_buf[LINE_LEN]; + + while (!feof(f)) { + fgets(line_buf, LINE_LEN, f); + (*line_nr)++; + if (line_buf[0] == '#') + continue; + if (line_buf[0] == '\n') + continue; + if (line_buf[0] == '\0') + continue; + return line_buf; + } + return NULL; + } + + /* + * retval is just if we found the macro file, no errors! + */ + int + bdmlib_do_load_macro(char *file_name, int which_suffix) + { + char m_name[256]; + FILE *m_file; + char *lptr; + char cmd; + int line_nr, ret, size; + bfd_vma addr1, addr2; + short size_tag; + u_char *buf; + int errorcount = 0; + char * begin_suffix = ".bdmmb", *end_suffix = ".bdmme", *no_suffix = ""; + char * suffix; + + + dbprintf("bdmlib_do_load_macro %s suffix %d\n", file_name, which_suffix); + strcpy(m_name, file_name); + if ((lptr = rindex(m_name, '.')) != 0) { + *lptr = '\0'; + } + switch (which_suffix) { + case BEGIN_MACRO: suffix = begin_suffix; break; + case END_MACRO: suffix = end_suffix; break; + case NO_SUFFIX_MACRO: suffix = no_suffix; break; + default: suffix = no_suffix; + } + strcat(m_name, suffix); + if ((m_file = fopen(m_name, "r")) == NULL) { + dbprintf("\tno macro file found\n"); + return BDM_ERR_MACROFILE; /* no macro file available, quit silently */ + } + if (!(bdmlib_getstatus() & BDM_TARGETSTOPPED)) { + dbprintf("\twarning: chip needs stopping\n"); + bdmlib_ioctl(BDM_STOP_CHIP); + } + line_nr = 0; + while ((lptr = get_line(m_file, &line_nr))) { + cmd = *lptr++; + addr1 = strtoul (lptr, &lptr, 0); + addr2 = strtoul (lptr, &lptr, 0); + size = strtol (lptr, &lptr, 0); + bdmlib_propeller(addr1, stdout); + switch (toupper(cmd)) { + case 'W': + dbprintf("\twrite to addr %#x cont %#x size %d\n", + addr1, addr2, size); + switch (size) { + case 1: + size_tag = BDM_SIZE_BYTE; + size = 8; + break; + case 2: + size_tag = BDM_SIZE_WORD; + size = 8; + break; + case 4: + size_tag = BDM_SIZE_LONG; + size = 10; + break; + default: + error("\ + Error in processing macro %s line %d 'W' command:\n\t\ + size must be either 1,2,4 bytes, '%d' is not allowed", + m_name, line_nr, size); + continue; + } + if ((ret = bdmlib_write_var((caddr_t) addr1, size_tag, (u_int) addr2)) < 0) { + errorcount++; + dbprintf("\ + Error in processing macro %s line %d 'W' command:\n\t\ + bdm_write size mismatch: send %d returned %d errno %d", + m_name, line_nr, size, ret, errno); + } + break; + case 'C': + dbprintf("\tcopy from %#x to %#x size %d\n", + addr1, addr2, size); + buf = xmalloc(size); + if ((ret = bdmlib_read_block((caddr_t) addr1, size, buf)) != size) { + errorcount++; + error("\ + Error in processing macro %s line %d 'C' command:\n\t\ + bdm_copy size mismatch on read from %#x: wanted %d got %d", + m_name, line_nr, addr1, size, ret); + } else { + { + int i; + + for (i = 0; i < size; i++) { + if (!(i % 16)) + printf("\n0x%08X: ", (unsigned int) addr1 + i); + printf("0x%02X ", buf[i]); + } + printf("\n"); + } + if ((ret = bdmlib_write_block((caddr_t) addr2, size, buf)) != size) { + errorcount++; + error("\ + Error in processing macro %s line %d 'C' command:\n\t\ + bdm_copy size mismatch on write to %#x: wanted %d got %d", + m_name, line_nr, addr2, size, ret); + } + } + free(buf); + break; + case 'Z': + dbprintf("\tzero from %#x with %#x size %#x\n", + addr1, addr2 & 0xff, size); + buf = xmalloc(size); + memset(buf, addr2, size); + if ((ret = bdmlib_write_block((caddr_t) addr1, size, buf)) != size) { + errorcount++; + error("\ + Error in processing macro %s line %d 'Z' command:\n\t\ + bdm_set size mismatch on write to %#x: wanted %d got %d", + m_name, line_nr, addr1, size, ret); + + } + free(buf); + break; + case 'M': + dbprintf("\tMBAR setup to %#x\n", addr1); + if ((ret = bdmlib_set_mbar((u_long) addr1))) { + errorcount++; + error("\ + Error in processing macro %s line %d 'M' command:\n\t\ + MBAR set returned %d", + m_name, line_nr, ret); + + } + break; + #if DEBUGGING_MACROS + case 'T': + { + int i; + + buf = xmalloc(size); + for (i = 0; i < size; i++) + buf[i] = i; + bdmlib_write_block(addr1, size, buf); + free(buf); + } + break; + #endif /* DEBUGGING_MACROS */ + default: + dbprintf("\tcmd %c unknown\n", cmd); + } + } + if (hashmark) { + printf(" \b\b\b\b\b\b\b\b\b\b\b\b"); + fflush(stdout); + } + if(m_file) fclose(m_file); + dbprintf("\tfinished macro. errorcount %d\n", errorcount); + return 0; + /* + * dont give back errorcount, errors will show up on binary + * download also. + */ + } + + bdmlib_bfilt_t * bdmlib_bfilt=NULL; + + int + bdmlib_wrb_filt(bdmlib_bfilt_t * filt, caddr_t in_adr, + u_int size, u_char * bl_ptr) + { + int ret, part_ret; + u_int part_size; + if (!size) return 0; + + while (filt) { + if((in_adr<=filt->end_adr)&& + (in_adr+size-1>=filt->begin_adr)) { + ret = 0; + if(in_adrbegin_adr) { + part_size=filt->begin_adr-in_adr; + part_ret=bdmlib_wrb_filt(filt->next,in_adr,part_size,bl_ptr); + ret+=part_ret; + if(part_ret!=part_size) return ret; + in_adr+=part_size; + bl_ptr+=part_size; + size-=part_size; + } + part_size=filt->end_adr-in_adr+1; + if (part_size>=size) { + part_size=size; + size=0; + } else size-=part_size; + part_ret=filt->wrb_filt(filt,in_adr,part_size,bl_ptr); + ret+=part_ret; + if(part_ret!=part_size) { + dbprintf("write error on filt write, address 0x%lx size %d acknowledged %d errno %d\n", + (long)in_adr, part_size, part_ret, errno); + return ret; + } + in_adr+=part_size; + bl_ptr+=part_size; + if(!size) return ret; + ret+=bdmlib_wrb_filt(filt->next,in_adr,size,bl_ptr); + return ret; + } + filt=filt->next; + } + /* regular memory block write */ + if ((ret = bdmlib_write_block(in_adr, size, bl_ptr)) != size) { + dbprintf("write error on block write, written %d acknowledged %d errno %d\n", + size, ret, errno); + return ret; + } + return ret; + } + + int bdmlib_load_use_lma=0; + static int load_section_error; + + static void + bdmlib_load_section(bfd * abfd, sec_ptr sec, PTR ignore) + { + u_long addr; + u_long dfc; + u_long load_bytes; + file_ptr offset; + int ret, cnt; + char cbuf[512]; + + dbprintf("bdmlib_load_section:\n\tsection %s index %d\n", + sec->name, sec->index); + dbprintf("\tflags %#x raw_size 0x%08x cooked_size 0x%08x\n", + sec->flags, sec->_raw_size, sec->_cooked_size); + dbprintf("\tvma %#x lma %#x output_offset %#x\n", + sec->vma, sec->lma, sec->output_offset); + if ((load_section_error < 0) || + ((bfd_get_section_flags(abfd, sec) & SEC_LOAD) == 0)) { + return; + } + if (bfd_get_section_flags(abfd, sec) & SEC_CODE) + dfc = 0x6; /* Supervisor program space */ + else + dfc = 0x5; /* Supervisor data space */ + if ((ret = bdmlib_set_sys_reg(BDM_REG_DFC, dfc)) < 0) { + load_section_error = ret; + return; + } + if(!bdmlib_load_use_lma) + addr = bfd_section_vma(abfd, sec); + else + addr = bfd_section_lma(abfd, sec); + + if ((load_bytes = bfd_get_section_size_before_reloc(sec)) == 0) + return; + offset = 0; + while (load_bytes) { + if (load_bytes > sizeof(cbuf)) { + cnt = sizeof(cbuf); + } else { + cnt = load_bytes; + } + if (!bfd_get_section_contents(abfd, sec, cbuf, offset, cnt)) { + dbprintf("read error section %s\n", sec->name); + load_section_error = BDM_ERR_LOAD; + return; + } + if ((ret = bdmlib_wrb_filt(bdmlib_bfilt,(caddr_t) addr, cnt, cbuf)) != cnt) { + dbprintf("write error on block write, written %d acknowledged %d errno %d\n", + cnt, ret, errno); + load_section_error = BDM_ERR_LOAD; + return; + } + + load_bytes -= cnt; + addr += cnt; + offset += cnt; + bdmlib_propeller(addr, stdout); + } + } + + static int bfd_initialized; + static bfd * prepare_binary(char *file_name) + { + bfd *abfd; + + if (!bfd_initialized) { + bfd_init(); + bfd_initialized = 1; + } + abfd = bfd_openr(file_name, 0); + if (!abfd) { + dbprintf("Unable to open file %s\n", file_name); + return NULL; + } + if (bfd_check_format(abfd, bfd_object) == 0) { + dbprintf("File %s is not an object file\n", file_name); + bfd_close(abfd); + return NULL; + } + return abfd; + } + + /* + * load a binary file, returns error codes + */ + int + bdmlib_do_load_binary(char *file_name, char *entry_name, u_long *entry_pt) + { + bfd *abfd; + int ret; + u_long entry_addr = 0; + + if ((abfd = prepare_binary(file_name)) == NULL) + return BDM_ERR_OPEN; + + if (entry_name) + while (isspace(*entry_name)) + entry_name++; + + if (entry_name && isdigit(*entry_name)) { + entry_addr = strtoul (entry_name, NULL, 0); + } else if (entry_name) { + long i, symcnt; + asymbol **symtab; + if ((i=bfd_get_symtab_upper_bound(abfd))<=0 || !(symtab=malloc(i))) + return BDM_ERR_OPEN; + if ((symcnt = bfd_canonicalize_symtab (abfd, symtab))<0) + return BDM_ERR_OPEN; + + for (i=0; iname)) { + entry_addr = symtab[i]->section->vma + symtab[i]->value; + break; + } + } + } else { + entry_addr = bfd_get_start_address(abfd); + } + if(entry_pt) *entry_pt = entry_addr; + + load_section_error = BDM_NO_ERROR; + if (!(bdmlib_getstatus() & BDM_TARGETSTOPPED) && + ((ret = bdmlib_ioctl(BDM_STOP_CHIP)))) { + dbprintf("bdmlib_do_load_binary: %d %s\n", + errno, bdmlib_geterror_str(-errno)); + return -errno; + } + bfd_map_over_sections(abfd, bdmlib_load_section, NULL); + if (hashmark) { + printf(" . \b\b\b\b\b\b\b\b\b\b\b\b"); + fflush(stdout); + } + bfd_close(abfd); + return load_section_error; + } + + int + bdmlib_do_load_binary_section(char *file_name, char *section_name) + { + bfd *abfd; + asection *sec; + int ret; + + if ((abfd = prepare_binary(file_name)) == NULL) + return BDM_ERR_OPEN; + + if ((sec = bfd_get_section_by_name(abfd, section_name)) == NULL) + return BDM_ERR_SECTION; + + load_section_error = BDM_NO_ERROR; + if (!(bdmlib_getstatus() & BDM_TARGETSTOPPED) && + ((ret = bdmlib_ioctl(BDM_STOP_CHIP)))) { + dbprintf("bdmlib_do_load_binary: %d %s\n", + errno, bdmlib_geterror_str(-errno)); + return -errno; + } + + if (hashmark) { + printf(" "); fflush(stdout); + } + bdmlib_load_section(abfd, sec, NULL); + if (hashmark) { + printf("\r \r"); + fflush(stdout); + } + bfd_close(abfd); + return load_section_error; + } + + /* + * Load a file. + * This is supposed to be coff here, but bfd should handle other formats... + * + * use a macro for target specific manipulations, eg. setting + * chipselect, switching memory banks, etc. + */ + + int + bdmlib_load(char *file, char *entry_name, u_long * entry_pt) + { + int ret = 0; + u_int sfc, dfc; + int we_have_macro_files = 0; + + if (!bdmlib_isopen()) + return BDM_ERR_NOT_OPEN; + dbprintf("bdmlib_load: program name %s\n", file); + + if (bdm_autoreset) bdmlib_reset(); + if (!(bdmlib_getstatus() & BDM_TARGETSTOPPED)) + if ((ret = bdmlib_ioctl(BDM_STOP_CHIP))) { + fprintf_filtered(gdb_stderr, "%s", bdmlib_geterror_str(ret)); + error("Download failed\n"); + return ret; /* this is for non-gdb applications */ + } + + bdmlib_set_sys_reg(BDM_REG_DFC, 5); + if ((ret = bdmlib_set_sys_reg(BDM_REG_SFC, 5)) < 0) { + return ret; + } + bdmlib_get_sys_reg(BDM_REG_DFC, &dfc); + bdmlib_get_sys_reg(BDM_REG_SFC, &sfc); + dbprintf("\tDFC %x SFC %x\n", dfc, sfc); + + we_have_macro_files = !bdmlib_do_load_macro(file, BEGIN_MACRO); + + #if SUPPORT_RAMINIT + if ((ret = bdmlib_do_load_binary(RAMINIT_FILENAME, 0, 0)) < 0) { + error("ram_init load error.\n"); + } + #endif /* SUPPORT_RAMINIT */ + + if ((ret = bdmlib_do_load_binary(file, entry_name, entry_pt)) < 0) { + error("Download failed."); + return ret; + } + if (we_have_macro_files) + bdmlib_do_load_macro(file, END_MACRO); + return BDM_NO_ERROR; + + } + + static FILE *debug_fp; + + static int + open_debug(void) + { + if ((debug_fp = fopen(BDM_DEBUG_NAME, "w")) == NULL) { + perror("bdm-dbprintf"); + fprintf_filtered(gdb_stderr, "bdm: opening debug %s\n", + BDM_DEBUG_NAME); + return -1; + } + return 0; + } + + /* debug printf for Log-file */ + void + dbprintf(const char *format, ...) + { + va_list ap; + + if (bdm_flags & BDM_DODPRINTF) { + if ((!debug_fp) && open_debug()) return; + va_start(ap, format); + vfprintf(debug_fp, format, ap); fflush(debug_fp); + va_end(ap); + } else if (debug_fp) { + fclose(debug_fp); + debug_fp = NULL; + } + } + + void + bdmlib_log(const char *format, ...) + { + + va_list ap; + + /* + * this would normally call dbprintf(); however it seems not possible + * to do nested varargs calls.... + */ + + if (bdm_flags & BDM_DODPRINTF) { + if ((!debug_fp) && open_debug()) return; + va_start(ap, format); + fprintf(debug_fp, "%s: ", + #if defined BDMLIB_FORGDB + "GDB" + #elif defined BDMLIB_FORFLT + "FLT" + #else + "???" + #endif + ); + vfprintf(debug_fp, format, ap); fflush(debug_fp); + va_end(ap); + } else if (debug_fp) { + fclose(debug_fp); + debug_fp = NULL; + } + } diff -c -r -P gdb-5.3.original/gdb/bdmlib.h gdb-5.3-bdm-683xx/gdb/bdmlib.h *** gdb-5.3.original/gdb/bdmlib.h Sat Nov 2 17:19:49 2002 --- gdb-5.3-bdm-683xx/gdb/bdmlib.h Fri Aug 15 14:06:47 2003 *************** *** 0 **** --- 1,83 ---- + /* + * $Id: gdb-5.3-bdm-683xx-patch,v 1.2 2004/11/18 23:07:40 ppisa Exp $ + */ + + #ifndef BDMLIB_H + #define BDMLIB_H + + #include + #include + #include + + typedef u_short bdmstatus; + + extern int bdmlib_open(char *device); + extern int bdmlib_close(int); + extern int bdmlib_isopen(void); + extern int bdmlib_ioctl(u_int code); + extern int bdmlib_setioctl(u_int code, u_int val); + extern bdmstatus bdmlib_getstatus(void); + extern int bdmlib_write_var(caddr_t adr, u_short size, u_int val); + extern int bdmlib_read_var(caddr_t adr, u_short size, void *val); + extern int bdmlib_write_block(caddr_t adr, u_int size, u_char *block); + extern int bdmlib_read_block(caddr_t adr, u_int size, u_char *block); + extern int bdmlib_load(char *file, char *entry_name, u_long *entry_pt); + extern int bdmlib_do_load_binary(char *file_name, char *entry_name, + u_long *entry_pt); + extern int bdmlib_do_load_macro(char *file_name, int is_begin_macro); + extern int bdmlib_get_sys_reg(u_int, u_int *); + extern int bdmlib_set_sys_reg(u_int, u_int); + extern int bdmlib_get_reg(u_int, u_int *); + extern int bdmlib_set_reg(u_int, u_int); + extern int bdmlib_go(void); + extern char *bdmlib_geterror_str(int); + extern char *bdmlib_getstatus_str(bdmstatus); + extern int bdmlib_set_mbar(u_long mbar_val); + extern int bdmlib_reset(void); + extern void bdmlib_setdebug(int switch_on); + extern int bdmlib_querydebug(void); + extern void bdmlib_showpc(void); + extern void bdmlib_log(const char *format, ...); + extern void bdmlib_propeller(u_long addr, FILE * fp); + extern int bdmlib_do_load_binary_section(char *file_name, char *sect_name); + + /* some additional error codes beyond those of the driver */ + + #define BDM_ERR_NOT_OPEN -650 + #define BDM_ERR_ILL_IOCTL -651 + #define BDM_ERR_WRITE_FAIL -652 + #define BDM_ERR_READ_FAIL -653 + #define BDM_ERR_ILL_SIZE -654 + #define BDM_ERR_OPEN -655 + #define BDM_ERR_LOAD -656 + #define BDM_ERR_MACROFILE -657 + #define BDM_ERR_SECTION -658 + #define BDM_ERR_VERSION -659 + #define BDM_NO_ERROR 0 + + /* support of filtered write for flash programming */ + + typedef struct bdmlib_bfilt{ + struct bdmlib_bfilt *next; + caddr_t begin_adr; + caddr_t end_adr; + int filt_id; + u_int flags; + int (*wrb_filt)(struct bdmlib_bfilt *, caddr_t , u_int, u_char * ); + void *info; + void *state; + }bdmlib_bfilt_t; + + #define BDMLIB_FILT_ERROR 0x08 + #define BDMLIB_FILT_ERASED 0x10 + #define BDMLIB_FILT_AUTO 0x20 + #define BDMLIB_FILT_FLASH 0x40 + + int bdmlib_load_use_lma; /* use LMA instead of VMA for load */ + bdmlib_bfilt_t * bdmlib_bfilt; + + int + bdmlib_wrb_filt(bdmlib_bfilt_t * bdmlib_bfilt, caddr_t in_adr, + u_int size, u_char * bl_ptr); + + #endif /* BDMLIB_H */ diff -c -r -P gdb-5.3.original/gdb/blockframe.c gdb-5.3-bdm-683xx/gdb/blockframe.c *** gdb-5.3.original/gdb/blockframe.c Fri Aug 23 00:25:17 2002 --- gdb-5.3-bdm-683xx/gdb/blockframe.c Fri Aug 15 14:23:26 2003 *************** *** 284,290 **** struct frame_info * get_next_frame (struct frame_info *frame) { ! return frame->next; } /* Flush the entire frame cache. */ --- 284,294 ---- struct frame_info * get_next_frame (struct frame_info *frame) { ! if(frame) return frame->next; ! else{ ! warning ("Internal error: get_next_frame(NULL) called"); ! return NULL; ! } } /* Flush the entire frame cache. */ diff -c -r -P gdb-5.3.original/gdb/config/m68k/bdm.mt gdb-5.3-bdm-683xx/gdb/config/m68k/bdm.mt *** gdb-5.3.original/gdb/config/m68k/bdm.mt Sat Nov 2 17:19:49 2002 --- gdb-5.3-bdm-683xx/gdb/config/m68k/bdm.mt Fri Aug 15 14:23:26 2003 *************** *** 0 **** --- 1,7 ---- + # Target: m68k bdm interface for CPU32(+) + XM_CLIBS=-lm + TDEPFILES= m68k-tdep.o remote-bdm.o bdmlib.o bdmflash.o \ + monitor.o cpu32bug-rom.o dsrec.o + #TDEPFILES= m68k-tdep.o remote-bdm.o bdmlib.o + TM_FILE= tm-bdm.h + DEFS += -DBDMLIB_FORGDB -Wall diff -c -r -P gdb-5.3.original/gdb/config/m68k/tm-bdm.h gdb-5.3-bdm-683xx/gdb/config/m68k/tm-bdm.h *** gdb-5.3.original/gdb/config/m68k/tm-bdm.h Sat Nov 2 17:19:49 2002 --- gdb-5.3-bdm-683xx/gdb/config/m68k/tm-bdm.h Sun Aug 24 23:20:18 2003 *************** *** 0 **** --- 1,260 ---- + /* Target machine description for BDM (Moto 683xx), for GDB, the GNU debugger. + Copyright 1994 Free Software Foundation, Inc. + Contributed by Gunter.Magin@lpr.e-technik.tu-muenchen.de + + This file is part of GDB. + + 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. */ + + /* The definitions for M683xx BDM target */ + + /* GCC is probably the only compiler used on this configuration. So + get this right even if the code which detects gcc2_compiled. is + still broken. */ + + #define BELIEVE_PCC_PROMOTION 1 + + /* bdm in CPU32 does it for us if we use PCC to get the PC */ + #define DECR_PC_AFTER_BREAK 0 + + /* use BGND cmd */ + #define BREAKPOINT {0x4a, 0xfa} + + /* target breakpoint vector number */ + #define BPT_VECTOR 0x0f + + #define GDBINIT_FILENAME ".gdbinit68" + + /* the rest is generic */ + #include "m68k/tm-m68k.h" + + /* Need to do this for ELF targets, where we can't figure out the boundaries of + the entry file. This method stops the backtrace when we reach main. */ + + #define FRAME_CHAIN_VALID(fp,fi) func_frame_chain_valid (fp, fi) + + /* the rest is from Eric Norum */ + /* modified for 68332 by gm */ + /* + * Override some of the generic definitions + */ + + #if defined THIS_IS_FOR_68360 + /* + * we need 27 registers: + * 8 data registers + * 8 address registers + * 2 other registers (PC, PS) + * 9 special registers + * 0 floating point registers + */ + #undef NUM_REGS + #undef REGISTER_BYTES + #undef NUM_FREGS + #define NUM_REGS 27 + + /* + * Add the special registers in the CPU32(+) + */ + #undef REGISTER_NAMES + #define REGISTER_NAMES \ + {"d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", \ + "a0", "a1", "a2", "a3", "a4", "a5", "fp", "sp", \ + "ps", "pc", \ + "pcc", "usp", "ssp", "sfc", "dfc", "atemp", "far", "vbr", "mbar", \ + "fp0", "fp1", "fp2", "fp3", "fp4", "fp5", "fp6", "fp7", \ + "fpcontrol", "fpstatus", "fpiaddr", "fpcode", "fpflags" } + + /* + * Update register offsets to reflect the added registers + */ + #undef FP0_REGNUM + #undef FPC_REGNUM + #undef FPS_REGNUM + #undef FPI_REGNUM + #define FP0_REGNUM 27 /* Floating point register 0 */ + #define FPC_REGNUM 35 /* 68881 control register */ + #define FPS_REGNUM 36 /* 68881 status register */ + #define FPI_REGNUM 37 /* 68881 iaddr register */ + + #else + /* + * we need 26 registers: + * 8 data registers + * 8 address registers + * 2 other registers (PC, PS) + * 8 special registers + * 0 floating point registers + */ + #undef NUM_REGS + #undef REGISTER_BYTES + #undef NUM_FREGS + #define NUM_REGS 26 + /* reserve space for FP registers, just in case someone stumbles over it */ + + /* + * Add the special registers in the CPU32(+) + */ + #undef REGISTER_NAMES + #define REGISTER_NAMES \ + {"d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", \ + "a0", "a1", "a2", "a3", "a4", "a5", "fp", "sp", \ + "ps", "pc", \ + "pcc", "usp", "ssp", "sfc", "dfc", "atemp", "far", "vbr" /*, "mbar", \ + "fp0", "fp1", "fp2", "fp3", "fp4", "fp5", "fp6", "fp7", \ + "fpcontrol", "fpstatus", "fpiaddr", "fpcode", "fpflags" */ } + + /* + * Update register offsets to reflect the added registers + */ + #undef FP0_REGNUM + #undef FPC_REGNUM + #undef FPS_REGNUM + #undef FPI_REGNUM + #define FP0_REGNUM 26 /* Floating point register 0 */ + #define FPC_REGNUM 34 /* 68881 control register */ + #define FPS_REGNUM 35 /* 68881 status register */ + #define FPI_REGNUM 36 /* 68881 iaddr register */ + + #endif + + #if !GDB_MULTI_ARCH + #define A1_REGNUM 9 + #define FP_REGNUM 14 /* Contains address of executing stack frame */ + #define SP_REGNUM 15 /* Contains address of top of stack */ + #define PS_REGNUM 16 /* Contains processor status */ + #define PC_REGNUM 17 /* Contains program counter */ + #define SIG_PC_FP_OFFSET 530 + #define FUNCTION_START_OFFSET 0 + #define REGISTER_BYTES (16*4 + 2*4 + 9*4 + 8*12 + 3*4) + #define REGISTER_SIZE 4 + #define REGISTER_RAW_SIZE(N) (((unsigned)(N) - FP0_REGNUM) < 8 ? 12 : 4) + #define MAX_REGISTER_RAW_SIZE 12 + #define REGISTER_VIRTUAL_SIZE(N) (((unsigned)(N) - FP0_REGNUM) < 8 ? 12 : 4) + #define MAX_REGISTER_VIRTUAL_SIZE 12 + #define REGISTER_VIRTUAL_TYPE(N) \ + ((unsigned) (N) >= FPC_REGNUM ? lookup_pointer_type (builtin_type_void) : \ + (unsigned) (N) >= FP0_REGNUM ? builtin_type_long_double : \ + (unsigned) (N) >= A0_REGNUM ? lookup_pointer_type (builtin_type_void) : \ + builtin_type_int) + #define REGISTER_BYTE(N) \ + ((N) >= FPC_REGNUM ? (((N) - FPC_REGNUM) * 4) + 168 \ + : (N) >= FP0_REGNUM ? (((N) - FP0_REGNUM) * 12) + 72 \ + : (N) * 4) + #define DEPRECATED_STORE_RETURN_VALUE(TYPE,VALBUF) \ + write_register_bytes (0, VALBUF, TYPE_LENGTH (TYPE)) + extern CORE_ADDR m68k_saved_pc_after_call (struct frame_info *); + #define DEPRECATED_EXTRACT_RETURN_VALUE(TYPE,REGBUF,VALBUF) \ + memcpy ((VALBUF), \ + (char *)(REGBUF) + \ + (TYPE_LENGTH(TYPE) >= 4 ? 0 : 4 - TYPE_LENGTH(TYPE)), \ + TYPE_LENGTH(TYPE)) + #define SAVED_PC_AFTER_CALL(frame) \ + m68k_saved_pc_after_call(frame) + #define INNER_THAN(lhs,rhs) ((lhs) < (rhs)) + #define FRAME_ARGS_SKIP 8 + #define SKIP_PROLOGUE(ip) (m68k_skip_prologue (ip)) + #define FRAME_NUM_ARGS(fi) (-1) + #define FRAME_ARGS_ADDRESS(fi) ((fi)->frame) + #define FRAME_LOCALS_ADDRESS(fi) ((fi)->frame) + #define POP_FRAME { m68k_pop_frame (); } + extern void m68k_pop_frame (void); + #define FRAME_INIT_SAVED_REGS(fi) m68k_frame_init_saved_regs ((fi)) + void m68k_frame_init_saved_regs (struct frame_info *frame_info); + #define FRAME_SAVED_PC(FRAME) \ + (((FRAME)->signal_handler_caller \ + ? ((FRAME)->next \ + ? read_memory_integer ((FRAME)->next->frame + SIG_PC_FP_OFFSET, 4) \ + : read_memory_integer (read_register (SP_REGNUM) \ + + SIG_PC_FP_OFFSET - 8, 4) \ + ) \ + : read_memory_integer ((FRAME)->frame + 4, 4)) \ + ) + #define FRAME_CHAIN(thisframe) \ + (thisframe->signal_handler_caller \ + ? thisframe->frame \ + : (!inside_entry_file ((thisframe)->pc) \ + ? read_memory_integer ((thisframe)->frame, 4) \ + : 0)) + /* Things needed for making the inferior call functions. */ + + /* The CALL_DUMMY macro is the sequence of instructions, as disassembled + by gdb itself: + + These instructions exist only so that m68k_find_saved_regs can parse + them as a "prologue"; they are never executed. + + fmovemx fp0-fp7,sp@- 0xf227 0xe0ff + moveml d0-a5,sp@- 0x48e7 0xfffc + clrw sp@- 0x4267 + movew ccr,sp@- 0x42e7 + + The arguments are pushed at this point by GDB; no code is needed in + the dummy for this. The CALL_DUMMY_START_OFFSET gives the position + of the following jsr instruction. That is where we start + executing. + + jsr @#0x32323232 0x4eb9 0x3232 0x3232 + addal #0x69696969,sp 0xdffc 0x6969 0x6969 + trap # 0x4e4? + nop 0x4e71 + + Note this is CALL_DUMMY_LENGTH bytes (28 for the above example). + + The dummy frame always saves the floating-point registers, whether they + actually exist on this target or not. */ + + /* FIXME: Wrong to hardwire this as BPT_VECTOR when sometimes it + should be REMOTE_BPT_VECTOR. Best way to fix it would be to define + CALL_DUMMY_BREAKPOINT_OFFSET. */ + + #define CALL_DUMMY {0xf227e0ff, 0x48e7fffc, 0x426742e7, 0x4eb93232, 0x3232dffc, 0x69696969, (0x4e404e71 | (BPT_VECTOR << 16))} + #define CALL_DUMMY_LENGTH 28 /* Size of CALL_DUMMY */ + #define CALL_DUMMY_START_OFFSET 12 /* Offset to jsr instruction */ + #define CALL_DUMMY_BREAKPOINT_OFFSET (CALL_DUMMY_START_OFFSET + 12) + + /* Insert the specified number of args and function address + into a call sequence of the above form stored at DUMMYNAME. + We use the BFD routines to store a big-endian value of known size. */ + + #define FIX_CALL_DUMMY(dummyname, pc, fun, nargs, args, type, gcc_p) \ + { bfd_putb32 (fun, (unsigned char *) dummyname + CALL_DUMMY_START_OFFSET + 2); \ + bfd_putb32 (nargs*4, (unsigned char *) dummyname + CALL_DUMMY_START_OFFSET + 8); } + + /* Push an empty stack frame, to record the current PC, etc. */ + + #define PUSH_DUMMY_FRAME { m68k_push_dummy_frame (); } + + extern void m68k_push_dummy_frame (void); + + /* Offset from SP to first arg on stack at first instruction of a function */ + + #define SP_ARG0 (1 * 4) + + #define TARGET_M68K + + /* Figure out where the longjmp will land. Slurp the args out of the stack. + We expect the first arg to be a pointer to the jmp_buf structure from which + we extract the pc (JB_PC) that we will land at. The pc is copied into ADDR. + This routine returns true on success */ + + extern int m68k_get_longjmp_target (CORE_ADDR *); + #endif + + /* + * The other definitions and macros don't need to be changed: + * a) The CPU32(+) has no floating point registers + * b) The REGISTER_BYTES_OK macro isn't used + */ diff -c -r -P gdb-5.3.original/gdb/config/m68k/tm-m68k.h gdb-5.3-bdm-683xx/gdb/config/m68k/tm-m68k.h *** gdb-5.3.original/gdb/config/m68k/tm-m68k.h Tue Jul 9 21:48:40 2002 --- gdb-5.3-bdm-683xx/gdb/config/m68k/tm-m68k.h Fri Aug 15 14:23:26 2003 *************** *** 21,27 **** #include "regcache.h" ! #define GDB_MULTI_ARCH GDB_MULTI_ARCH_PARTIAL /* Generic 68000 stuff, to be included by other tm-*.h files. */ --- 21,27 ---- #include "regcache.h" ! #define GDB_MULTI_ARCH 0 /* Generic 68000 stuff, to be included by other tm-*.h files. */ diff -c -r -P gdb-5.3.original/gdb/configure.tgt gdb-5.3-bdm-683xx/gdb/configure.tgt *** gdb-5.3.original/gdb/configure.tgt Sun Oct 20 14:14:39 2002 --- gdb-5.3-bdm-683xx/gdb/configure.tgt Fri Aug 15 14:23:26 2003 *************** *** 150,155 **** --- 150,156 ---- m68*-motorola-*) gdb_target=delta68 ;; m68*-netx-*) gdb_target=vxworks68 ;; m68*-tandem-*) gdb_target=st2000 ;; + m68*-bdm-*) gdb_target=bdm ;; m68*-*-aout*) gdb_target=monitor ;; m68*-*-coff*) gdb_target=monitor ;; m68*-*-elf*) gdb_target=monitor ;; diff -c -r -P gdb-5.3.original/gdb/frame.c gdb-5.3-bdm-683xx/gdb/frame.c *** gdb-5.3.original/gdb/frame.c Wed Sep 25 22:43:21 2002 --- gdb-5.3-bdm-683xx/gdb/frame.c Fri Aug 15 14:23:26 2003 *************** *** 206,211 **** --- 206,213 ---- else frame_register_unwind (frame->next, regnum, optimizedp, lvalp, addrp, &realnumx, raw_buffer); + + if (*addrp == 0) *addrp = REGISTER_BYTE (regnum); } void diff -c -r -P gdb-5.3.original/gdb/infcmd.c gdb-5.3-bdm-683xx/gdb/infcmd.c *** gdb-5.3.original/gdb/infcmd.c Wed Sep 25 22:43:21 2002 --- gdb-5.3-bdm-683xx/gdb/infcmd.c Sat Sep 6 09:58:22 2003 *************** *** 1337,1344 **** "finish_command: function has no target type"); /* FIXME: Shouldn't we do the cleanups before returning? */ ! if (TYPE_CODE (value_type) == TYPE_CODE_VOID) return; funcaddr = BLOCK_START (SYMBOL_BLOCK_VALUE (function)); --- 1337,1346 ---- "finish_command: function has no target type"); /* FIXME: Shouldn't we do the cleanups before returning? */ ! if (TYPE_CODE (value_type) == TYPE_CODE_VOID) { ! do_cleanups (old_chain); return; + } funcaddr = BLOCK_START (SYMBOL_BLOCK_VALUE (function)); diff -c -r -P gdb-5.3.original/gdb/m68k-tdep.c gdb-5.3-bdm-683xx/gdb/m68k-tdep.c *** gdb-5.3.original/gdb/m68k-tdep.c Sat Aug 24 02:21:34 2002 --- gdb-5.3-bdm-683xx/gdb/m68k-tdep.c Fri Aug 15 14:23:26 2003 *************** *** 60,73 **** E_SP_REGNUM = 15, /* Contains address of top of stack */ E_PS_REGNUM = 16, /* Contains processor status */ E_PC_REGNUM = 17, /* Contains program counter */ ! E_FP0_REGNUM = 18, /* Floating point register 0 */ E_FPC_REGNUM = 26, /* 68881 control register */ E_FPS_REGNUM = 27, /* 68881 status register */ E_FPI_REGNUM = 28 }; ! #define REGISTER_BYTES_FP (16*4 + 8 + 8*12 + 3*4) ! #define REGISTER_BYTES_NOFP (16*4 + 8) #define NUM_FREGS (NUM_REGS-24) --- 60,73 ---- E_SP_REGNUM = 15, /* Contains address of top of stack */ E_PS_REGNUM = 16, /* Contains processor status */ E_PC_REGNUM = 17, /* Contains program counter */ ! E_FP0_REGNUM = 26, /* Floating point register 0 */ E_FPC_REGNUM = 26, /* 68881 control register */ E_FPS_REGNUM = 27, /* 68881 status register */ E_FPI_REGNUM = 28 }; ! #define REGISTER_BYTES_FP (16*4 + 8 + 9*4 + 8*12 + 3*4) ! #define REGISTER_BYTES_NOFP (16*4 + 8 + 9*4 + 8*12 + 3*4) #define NUM_FREGS (NUM_REGS-24) *************** *** 463,469 **** this target or not. */ for (regnum = FP0_REGNUM + 7; regnum >= FP0_REGNUM; regnum--) { ! read_register_bytes (REGISTER_BYTE (regnum), raw_buffer, 12); sp = push_bytes (sp, raw_buffer, 12); } --- 463,472 ---- this target or not. */ for (regnum = FP0_REGNUM + 7; regnum >= FP0_REGNUM; regnum--) { ! if(regnum < NUM_REGS) ! read_register_bytes (REGISTER_BYTE (regnum), raw_buffer, 12); ! else ! memset(raw_buffer,0,12); sp = push_bytes (sp, raw_buffer, 12); } *************** *** 490,495 **** --- 493,499 ---- m68k_frame_init_saved_regs (frame); for (regnum = FP0_REGNUM + 7; regnum >= FP0_REGNUM; regnum--) { + if (regnum >= NUM_REGS) continue; if (frame->saved_regs[regnum]) { read_memory (frame->saved_regs[regnum], raw_buffer, 12); *************** *** 670,676 **** /* Regmask's low bit is for register fp7, the first pushed */ for (regnum = FP0_REGNUM + 8; --regnum >= FP0_REGNUM; regmask >>= 1) if (regmask & 1) ! frame_info->saved_regs[regnum] = (next_addr -= 12); pc += 4; } /* fmovemx to (fp + displacement) */ --- 674,684 ---- /* Regmask's low bit is for register fp7, the first pushed */ for (regnum = FP0_REGNUM + 8; --regnum >= FP0_REGNUM; regmask >>= 1) if (regmask & 1) ! { ! next_addr -= 12; ! if (regnum < NUM_REGS) ! frame_info->saved_regs[regnum] = next_addr; ! } pc += 4; } /* fmovemx to (fp + displacement) */ *************** *** 683,689 **** for (regnum = FP0_REGNUM + 8; --regnum >= FP0_REGNUM; regmask >>= 1) if (regmask & 1) { ! frame_info->saved_regs[regnum] = addr; addr += 12; } pc += 6; --- 691,698 ---- for (regnum = FP0_REGNUM + 8; --regnum >= FP0_REGNUM; regmask >>= 1) if (regmask & 1) { ! if (regnum < NUM_REGS) ! frame_info->saved_regs[regnum] = addr; addr += 12; } pc += 6; *************** *** 738,744 **** for (regnum = FP0_REGNUM + 8; --regnum >= FP0_REGNUM; regmask >>= 1) if (regmask & 1) { ! frame_info->saved_regs[regnum] = next_addr; next_addr += 12; } pc += 10; --- 747,754 ---- for (regnum = FP0_REGNUM + 8; --regnum >= FP0_REGNUM; regmask >>= 1) if (regmask & 1) { ! if (regnum < NUM_REGS) ! frame_info->saved_regs[regnum] = next_addr; next_addr += 12; } pc += 10; diff -c -r -P gdb-5.3.original/gdb/monitor.c gdb-5.3-bdm-683xx/gdb/monitor.c *** gdb-5.3.original/gdb/monitor.c Thu Jul 11 23:00:39 2002 --- gdb-5.3-bdm-683xx/gdb/monitor.c Fri Aug 15 14:23:26 2003 *************** *** 107,113 **** static struct monitor_ops *current_monitor; ! static int hashmark; /* flag set by "set hash" */ static int timeout = 30; --- 107,117 ---- static struct monitor_ops *current_monitor; ! extern char hashmark; ! /* ! * hack to enable multiple targets using ! * `hashmark'; flag set by "set hash" ! */ static int timeout = 30; diff -c -r -P gdb-5.3.original/gdb/remote-bdm.c gdb-5.3-bdm-683xx/gdb/remote-bdm.c *** gdb-5.3.original/gdb/remote-bdm.c Sat Nov 2 17:19:49 2002 --- gdb-5.3-bdm-683xx/gdb/remote-bdm.c Sun Sep 7 23:41:48 2003 *************** *** 0 **** --- 1,1721 ---- + /* + * $Id: gdb-5.3-bdm-683xx-patch,v 1.2 2004/11/18 23:07:40 ppisa Exp $ + * + * Remote debugging interface for 683xx via Background Debug Mode + * needs a device driver, which controls the BDM interface. + * written by G.Magin + * (C) 1995 Technische Universitaet Muenchen, Lehrstuhl fuer Prozessrechner + * (C) 1996 Technische Universitaet Muenchen, Lehrstuhl fuer Prozessrechner + + 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, 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; see the file COPYING. If not, write to + the Free Software Foundation, 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + */ + + /* + ChangeLog + + 1999-2003 Pavel Pisa + Maintaining original Gunter's patches + for GDB-4.16,4.17,4.18,5.1.1,5.2,5.2.1 + Added support for flashing from GDB + + 20030821 Josef Wolf + Ported to GDB-5.3 + Added support for symbolic bdm_entry definition + + */ + + #include "defs.h" + #include "gdbcore.h" + #include "target.h" + #include "gdb_wait.h" + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include "command.h" + #include "inferior.h" + #include "value.h" + #include "breakpoint.h" + #include "bdmlib.h" + #include "bdm.h" + + #define BDM_MAGIC_NULL_PID 4200 + + #define ENABLE_BDM_FLASH + #ifdef ENABLE_BDM_FLASH + #include "bdmflash.h" + #endif /*ENABLE_BDM_FLASH*/ + + extern int (*ui_loop_hook) (int); + + extern struct target_ops bdm_ops; /* Forward declaration */ + + struct cmd_list_element *showlist; + extern struct cmd_list_element *setlist; + + static int bdm_delay=-1; + static char *entry_name=NULL; + static u_long entry_pt = 0; + static void bdm_clear_breakpoints(void); + static void bdm_close(int); + static void bdm_fetch_register(int); + static void bdm_store_register(int); + static char *bdm_prog_loaded; + + #define BDM_DEBUG_NAME "bdm-dbg.log" + extern char hashmark; + /* + * hack to enable multiple target modules using + * `hashmark'; flag set by "set hash" + */ + static int bdm_gotexception; /* flag to signal fatal exit */ + + #define TIME_TO_COME_UP 60000 + int bdm_ttcu = TIME_TO_COME_UP; + /* time-to-come-up for a target-monitor */ + int bdm_autoreset; + /* issue an automatic reset before download */ + static int bdm_sensecable; + /* check if cable connected and power applied */ + static int bdm_xfer_use_fast=1; + /* set to 1 to enable faster transfer of variables <= 4 bytes */ + + /* default delay for interface */ + /* has beem 75, but we try to use adaptive short delay mode now */ + #define BDM_DEFAULT_DELAY 0 + + #define BDM_DODPRINTF (1<<0) + #define BDM_GOTEXCEPTION (1<<1) + + static struct _bdm_bp { + CORE_ADDR addr; + int valid; + } bdm_bp[BREAKPOINT_MAX]; + + + static void + nap (int microseconds) + { + struct timeval tv; + + tv.tv_sec = microseconds / 1000000; + tv.tv_usec = microseconds % 1000000; + select (0, NULL, NULL, NULL, &tv); + } + + /* + * this is for bdm_reset and other bdm special commands. + * generic GDB commands are checked by registering bdm_ops struct + */ + static void bdm_check_fd() + { + if (!(bdmlib_isopen())) { + error("\ + Bdm is not yet opened. Use the 'target bdm ' command to open \n\ + the bdm interface\n\ + Use 'help bdm' for more online info"); + } + + } + + static void bdm_check_status() + { + bdmstatus b = bdmlib_getstatus(); + if (b & BDM_TARGETNC) { + error("Target cable not connected."); + } else if (b & BDM_TARGETPOWER) { + error("Target has no Power"); + } + } + + /* + * control logging in the driver module + */ + static void + bdm_set_debug_driver_interactive(char *arg, int from_tty) + { + int ret; + + bdmlib_log("bdm_set_debug_driver_interactive: arg <%s> from_tty %d\n", + arg, from_tty); + bdm_check_fd(); + if (arg == NULL) { + fprintf_filtered(gdb_stderr, "no level specified\n"); + return; + } + if ((ret = bdmlib_setioctl(BDM_DEBUG_LEVEL, (u_long) atoi(arg)))) { + fprintf_filtered(gdb_stderr, "failed, error %s\n", + bdmlib_geterror_str(ret)); + } + } + + /* + * enable logging in this module and the bdmlib-module + */ + static void + bdm_set_debug_interactive(char *arg, int from_tty) + { + bdmlib_log("bdm_set_debug_interactive: arg <%s> from_tty %d\n", + arg, from_tty); + /* bdm_check_fd(); + */ + if (arg == NULL) { + if (from_tty) + printf_filtered("bdm_log is %s\n", + bdmlib_querydebug() ? "on" : "off"); + } else if (!(strcmp(arg, "on"))) { + if (from_tty) printf_filtered("on\n"); + bdmlib_setdebug(1); + } else if (!(strcmp(arg, "off"))) { + if (from_tty) printf_filtered("off\n"); + bdmlib_setdebug(0); + } else { + printf_filtered("illegal option %s\n", arg); + } + } + + static void + bdm_setdelay_interactive(char *arg, int from_tty) + { + char *dummy; + int ret; + + bdmlib_log("bdm_setdelay_interactive: arg <%s> from_tty %d\n", + arg, from_tty); + /* bdm_check_fd(); + */ + if (!arg) { + if (bdm_delay >= 0) printf_filtered("bdm_delay is %d\n", bdm_delay); + else + printf_filtered("using default delay %d\n", BDM_DEFAULT_DELAY); + } else { + bdm_delay = strtol(arg, &dummy, 0); + if (!bdmlib_isopen()) return; + if ((ret = bdmlib_setioctl(BDM_SPEED, strtol(arg, &dummy, 0)))) { + fprintf_filtered(gdb_stderr, "failed, error %s\n", + bdmlib_geterror_str(ret)); + } + } + } + + static void + bdm_sensecable_interactive(char *arg, int from_tty) + { + int ret; + + bdmlib_log("bdm_sensecable_interactive: arg <%s> from_tty %d\n", + arg, from_tty); + bdm_check_fd(); + if (arg == NULL) { + if (from_tty) + printf_filtered("sensing is %s\n", + (bdm_sensecable) ? "on" : "off"); + } else { + if (!(strcmp(arg, "on"))) { + if (from_tty) printf_filtered("on\n"); + bdm_sensecable = 1; + } else if (!(strcmp(arg, "off"))) { + if (from_tty) printf_filtered("off\n"); + bdm_sensecable = 0; + } else { + error("illegal option %s\n", arg); + } + if ((ret = bdmlib_setioctl(BDM_SENSECABLE,bdm_sensecable))) { + fprintf_filtered(gdb_stderr, "ioctl failed, error %s\n", + bdmlib_geterror_str(ret)); + } + } + } + + static void + bdm_setautoreset_interactive(char *arg, int from_tty) + { + + bdmlib_log("bdm_setautoreset_interactive: arg <%s> from_tty %d\n", + arg, from_tty); + /* bdm_check_fd(); + */ + if (arg == NULL) { + if (from_tty) + printf_filtered("automatic reset is %s\n", + (bdm_autoreset) ? "on" : "off"); + } else if (!(strcmp(arg, "on"))) { + if (from_tty) printf_filtered("on\n"); + bdm_autoreset = 1; + } else if (!(strcmp(arg, "off"))) { + if (from_tty) printf_filtered("off\n"); + bdm_autoreset = 0; + } else { + printf_filtered("illegal option %s\n", arg); + } + } + + static void + bdm_setttcu_interactive(char *arg, int from_tty) + { + char *dummy; + + bdmlib_log("bdm_setttcu_interactive: arg <%s> from_tty %d\n", + arg, from_tty); + /* bdm_check_fd(); + */ + if (!arg) { + printf_filtered("time-to-come-up is %d\n", bdm_ttcu); + } else { + bdm_ttcu = strtol(arg, &dummy, 0); + } + } + + static void + bdm_setentry_interactive(char *arg, int from_tty) + { + bdmlib_log("bdm_setentry_interactive: arg <%s> from_tty %d\n", + arg, from_tty); + /* bdm_check_fd(); + */ + if (!arg) { + if (entry_name) { + printf_filtered("current override entry point is %s\n", entry_name); + } else { + printf_filtered("no override entry point defined\n"); + } + if (entry_pt) { + printf_filtered("file read entry address 0x%08lx\n", entry_pt); + } else { + printf_filtered("no read entry address\n"); + } + } else { + if (entry_name) free (entry_name); + entry_name = NULL; + if(!(!strcmp(arg,"*"))) + entry_name = strdup (arg); + } + } + + /* + * initialize bdm interface port + */ + static void + bdm_init(int tty, char *arg) + { + int ret; + bdm_check_fd(); + if ((ret = bdmlib_ioctl(BDM_INIT))) { + fprintf_filtered(gdb_stderr, "failed, error %s\n", + bdmlib_geterror_str(ret)); + } + bdmlib_log("bdm_init: res %d\n", ret); + } + + static void + bdm_get_status_interactive(char *arg, int from_tty) + { + bdmstatus stat; + char *str; + + bdm_check_fd(); + stat = bdmlib_getstatus(); + str = bdmlib_getstatus_str(stat); + printf_filtered("%s\n", str); + bdmlib_log("bdm_get_status_int arg <%s> from_tty <%d> stat %d %s\n", + arg, from_tty, stat, str); + } + + static void + bdm_release_chip(void) + { + int ret; + + /* + * dont perform a bdm_check_fd() as we need to be able to quit gdb + * if we accidentially entered bdm mode, and no cable or target + * is connected + */ + if (!(bdmlib_isopen())) return; + if ((ret = bdmlib_ioctl(BDM_RELEASE_CHIP))) { + fprintf_filtered(gdb_stderr, "failed, error %s\n", + bdmlib_geterror_str(ret)); + } + bdmlib_log("bdm_release_chip: %d (%#x)\n", ret, ret); + } + + static void + bdm_reset(void) + { + bdm_check_fd(); bdm_check_status(); + bdmlib_log("bdm_reset\n"); + bdm_gotexception = 0; + bdmlib_reset(); + registers_changed(); + } + + /* + * step chip: execute a single instruction + */ + static void + bdm_step_chip() + { + int ret; + u_int help; + bdm_check_fd(); bdm_check_status(); + if ((ret = bdmlib_get_sys_reg(BDM_REG_RPC, &help)) < 0) { + error("%s", bdmlib_geterror_str(ret)); + } + bdmlib_log("bdm_step_chip at pc=%#x\n", extract_unsigned_integer(&help, 4)); + if ((ret = bdmlib_ioctl(BDM_STEP_CHIP)) < 0) { + error("%s", bdmlib_geterror_str(ret)); + } + bdmlib_log("bdm_step_chip\n"); + } + + #ifdef BDM_STEP_DEBUGGING + void + bdm_step(char *arg, int from_tty) + { + int i, usecs, count, ret; + long adr; + char *dummy; + bdmlib_log("bdm_step: arg <%s> from_tty %d\n", arg, from_tty); + adr = strtol(arg, &dummy, 0); + usecs = strtol(dummy, &dummy, 0); + count = strtol(dummy, &dummy, 0); + bdmlib_log("\tadr = %#x usecs %d count %d\n", adr, usecs, count); + if ((ret = bdmlib_set_sys_reg(BDM_REG_RPC, adr))) { + fprintf_filtered(gdb_stderr, + "bdm_step: setting pc failed ret %d\n", ret); + usleep(400000); + return; + } + for (i=0; i' to use the bdm target"); + } + /* + * Find the first whitespace character after device and chop it off + */ + + for (p = name; (*p != '\0') && (!isspace (*p)); p++) + ; + if ((*p == '\0') && (p == name)) + error ("\ + Please include the name of the device for the bdm port. "); + + dev_name = savestring(name, p - name); + + target_preopen(from_tty); + unpush_target(&bdm_ops); + + if ((res = bdmlib_open(dev_name)) < 0) { + p = bdmlib_geterror_str(res); + bdmlib_log("bdm_open: error on open %s res %d errno %d <%s>\n", + dev_name, res, errno, p); + perror_with_name(dev_name); /* auto return to prompt */ + return; + } + + bdm_sensecable_interactive("on", 0); + + push_target (&bdm_ops); + + bdm_clear_breakpoints(); + + delay = bdm_delay>=0 ? bdm_delay : BDM_DEFAULT_DELAY; + if ((res = bdmlib_setioctl(BDM_SPEED, bdm_delay))) { + fprintf_filtered(gdb_stderr, "set delay failed, error %s\n", + bdmlib_geterror_str(res)); + } + + if (from_tty) + printf_filtered("Remote %s connected to %s\n", + target_shortname, dev_name); + + #if 0 + /* We need some PTID to make rest of GDB happy */ + if(ptid_equal(inferior_ptid, null_ptid)) { + inferior_ptid = pid_to_ptid(BDM_MAGIC_NULL_PID); + } + #endif + } + + static void + bdm_close (quitting) + int quitting; + { + inferior_ptid = null_ptid; + if (!bdmlib_isopen()) return; /* ignore, if not open */ + bdmlib_close(quitting); + } + + /* + * kill means: terminate current application and return to system prompt. + * On a target, this might mean go to the monitor. + * However, this might be reached with bdm_reset as well. + * On a target without monitor, kill makes no sense. + * So we ignore the kill command completely. + */ + + static void + bdm_kill(void) + { + #if 1 + inferior_ptid = null_ptid; + #endif + return; + } + + static void + bdm_attach(char *args, int from_tty) + { + bdmlib_log("bdm_attach dummy: arg1 <%s> from_tty %d\n", args, from_tty); + if(ptid_equal(inferior_ptid, null_ptid)) { + inferior_ptid = pid_to_ptid(BDM_MAGIC_NULL_PID); + } + } + + /* + * _detach -- Terminate the open connection to the remote debugger. + * takes a program previously attached to and detaches it. + * We better not have left any breakpoints + * in the program or it'll die when it hits one. + * Close the open connection to the remote debugger. + * Use this when you want to detach and do something else + * with your gdb. + */ + static void + bdm_detach (char *args, int from_tty) + { + bdmlib_log("bdm_detach from_tty %d args %s\n", from_tty, args); + bdmlib_log("?? does it call bdm_close to do hard work?\n"); + pop_target(); /* calls bdm_close to do the real work */ + #if 1 + inferior_ptid = null_ptid; + #endif + } + + /* + * _resume -- Tell the remote machine to resume. + */ + static void + bdm_resume(ptid_t pid, int step, enum target_signal sig) + { + static u_int psw; + u_int newpsw; + static int int_flag; + u_int help; + + bdmlib_log("bdm_resume: pid %d step=%d, sig=%d\n", pid, step, sig); + if (step) { + /* + * This is to avoid to get jumped into an ISR if there is + * an Int pending when resuming operation. + * This is pesky, if we want to resume from a breakpoint. + * After a `continue', we stop after the first instruction, which + * is inside the ISR, after a second continue, we come back to the + * original place, where the BP has been restored. No progress so + * far. + * So we shut off interrupts, and step over the instruction, + * and then restore the clobbered int mask when continuing. + * + * As GDB implements `next' or `continue' with some single-steps + * first, the main purpose of this int mask fiddling is to make + * interrupts more transparent to the user. Still the user can set + * breakpoints to ISRs. + * + * However: This is a cludge. If we step over an operation + * manipulating the int priority mask in the status register, + * we loose! The code below is best effort on a compromise with + * speed on single stepping, however, it can be easily fooled. + * + * Please tell me other suggestions! (gm 20.07.96) + * + */ + if (!int_flag) { + bdmlib_get_sys_reg(BDM_REG_SR, &help); + psw = extract_unsigned_integer(&help, 4); + bdmlib_set_sys_reg(BDM_REG_SR, psw | 0x0700); + int_flag++; + bdmlib_log("\tgetting psw %x setting to %x\n", psw, psw | 0x0700); + } + bdm_step_chip(); + /* + * nothing must be transfered to/from target after the + * HW-BKPT based single step because analyze_exception() needs + * untouched ATEMP + */ + } else { + if (int_flag) { + bdmlib_get_sys_reg(BDM_REG_SR, &help); + newpsw = extract_unsigned_integer(&help, 4); + if ((newpsw & 0x0f00) == 0x0700) { + bdmlib_set_sys_reg(BDM_REG_SR, + (newpsw & 0xf0ff) | (psw & 0x0f00)); + bdmlib_log("\tbefore go setting psw from %x back to %x\n", + newpsw, (newpsw & 0xf0ff) | (psw & 0x0f00)); + } else { + bdmlib_log("\tAlarm: Intmask changed when stepping: %x to %x\n", + psw, newpsw & 0xf0ff); + } + int_flag = 0; + } + bdmlib_go(); + } + } + + static int ctrlc_int; + static void bdm_signal_handler(int s) + { + ctrlc_int++; + } + + static int + is_a_breakpoint(CORE_ADDR pc) + { + int i; + struct _bdm_bp *p; + for (i=0, p = bdm_bp; i < BREAKPOINT_MAX; i++, p++) { + if ((p->valid) && (p->addr == pc)) { + return 1; + } + } + return 0; + } + + /* size of exception frame in _words_ */ + static struct exec { + char size; + char used; + } except_frame_size[] = { + {4, 1}, /* format $0 */ + {4, 1}, /* format $1: throw away stack */ + {6, 1}, /* format $2 */ + {4, 0}, + {4, 0}, + {4, 0}, + {4, 0}, + {4, 0}, + {4, 0}, + {4, 0}, + {4, 0}, + {4, 0}, + {12, 1}, /* format $c */ + {4, 1}, + {4, 1}, + {4, 1} + }; + + + /* + * We have fallen into an exception supported by the runtime system. + * by executing the "bgnd" instruction in the trap handler + */ + static int analyze_exception(u_short val_h, struct target_waitstatus *status) + { + u_int pcc, rpc, sp; + u_int help; + u_int sr, vec; + + bdmlib_log("bdm_analyze_exception: val_h = %#x (should be 0x0)\n", val_h); + + /* + * get pc to check for breakpoints + */ + bdmlib_get_sys_reg(BDM_REG_PCC, &help); + pcc = extract_unsigned_integer(&help, 4); + bdmlib_get_sys_reg(BDM_REG_RPC, &help); + rpc = extract_unsigned_integer(&help, 4); + /* + * check if encountered a BGND-Breakpoint + */ + if (is_a_breakpoint(pcc)) { + bdmlib_log("\tbkpt found at (pcc) = %#x\n", pcc); + status->kind = TARGET_WAITKIND_STOPPED; + status->value.sig = TARGET_SIGNAL_TRAP; + bdmlib_set_sys_reg(BDM_REG_PCC, pcc); + bdmlib_set_sys_reg(BDM_REG_RPC, pcc); + return 0; + } + + /* + * now analyze stack for a trap + */ + bdmlib_get_sys_reg(BDM_REG_SSP, &help); + sp = extract_unsigned_integer(&help, 4); + /* get pc from stack and stuff it into pcc */ + bdmlib_read_var((caddr_t) sp, BDM_SIZE_WORD, &sr); sr &= 0xffff; + bdmlib_read_var((caddr_t) (sp+6), BDM_SIZE_WORD, &vec); vec &= 0xffff; + bdmlib_read_var((caddr_t) (sp+2), BDM_SIZE_LONG, &pcc); + pcc -= 2; /* pc has advanced before code insertion */ + bdmlib_log("\tsp = %#x\n", sp); + bdmlib_log("\tsr=%#x pc=%#x rpc=%#x vec=%#x (%x + %x)\n", + sr, pcc, rpc, vec, vec >> 12, vec & 0xfff); + + sp += (except_frame_size[vec>>12].size << 1); + bdmlib_log("\tsp fixed to %#x\n", sp); + bdmlib_set_reg(BDM_REG_A7, sp); + bdmlib_log("\tstackframe code %s\n", + except_frame_size[vec>>12].used ? "known and valid" : "unknown"); + + bdmlib_log("\t fixing pc to %#x\n", pcc); + bdmlib_set_sys_reg(BDM_REG_RPC, pcc); + bdmlib_set_sys_reg(BDM_REG_RPC, pcc); + + #if defined INSPECT_STACK_FRAME + { int i; + for (i=0; i < 36; i += 4) { + bdmlib_read_var(sp - (except_frame_size[vec>>12].size<<1) + i, + BDM_SIZE_LONG, &help); + bdmlib_log("\t\t\t\t\t*%#x = %#x\n", sp + i, help); + } + } + #endif /* INSPECT_STACK_FRAME */ + + status->kind = TARGET_WAITKIND_STOPPED; + switch ((vec & 0xfff) >> 2) { + case 2 : /* bus error */ + status->value.sig = TARGET_SIGNAL_BUS; break; + case 3 : /* address error */ + status->value.sig = TARGET_SIGNAL_BUS; break; + case 4 : /* illegal instruction */ + status->value.sig = TARGET_SIGNAL_ILL; break; + case 5 : /* zero divide */ + status->value.sig = TARGET_SIGNAL_FPE; break; + case 6 : /* chk instruction */ + status->value.sig = TARGET_SIGNAL_FPE; break; + case 7 : /* trapv instruction */ + status->value.sig = TARGET_SIGNAL_FPE; break; + case 8 : /* privilege violation */ + status->value.sig = TARGET_SIGNAL_SEGV; break; + case 9 : /* trace trap */ + status->value.sig = TARGET_SIGNAL_TRAP; break; + case 10: /* line 1010 emulator */ + status->value.sig = TARGET_SIGNAL_ILL; break; + case 11: /* line 1111 emulator */ + status->value.sig = TARGET_SIGNAL_ILL; break; + case 13: + /* + * Coprocessor protocol violation. Using a standard MMU or FPU + * this cannot be triggered by software. Call it a SIGBUS. + */ + status->value.sig = TARGET_SIGNAL_BUS; break; + case 31: /* interrupt */ + status->value.sig = TARGET_SIGNAL_INT; break; + case 46: /* trap#14 == program end */ + bdm_ops.to_has_execution = 0; + status->kind = TARGET_WAITKIND_EXITED; + bdmlib_read_var((caddr_t) (sp+8), BDM_SIZE_LONG, &help); + status->value.integer = help; + break; + case 47: /* breakpoint */ + status->value.sig = TARGET_SIGNAL_TRAP; break; + default: /* "software generated"*/ + status->value.sig = TARGET_SIGNAL_EMT; + } + bdm_gotexception = 1; + return 0; + } + + + /* + * _wait -- Wait until the remote machine stops, then return, + * storing status in status just as `wait' would. + */ + static ptid_t + bdm_wait (ptid_t pid, struct target_waitstatus *status) + { + int bdm_stat, ret; + int detach=0; + u_int val; + u_long val_conv; + u_short val_h, val_l; + struct sigaction old, new; int rv; + bdmlib_log("bdm_wait: pid %d \n", pid); + + status->kind = TARGET_WAITKIND_EXITED; + status->value.integer = 0; + + /* make gdb sensitive to ctrl-c */ + ctrlc_int = 0; + new.sa_handler = bdm_signal_handler; + sigemptyset(&new.sa_mask); + new.sa_flags = 0; + if ((rv = sigaction(SIGINT, &new, &old)) == -1) { + error("Cannot install handler for ctrl-c"); + } + /* wait here periodically polling for any actions required by target */ + while ((bdm_stat = bdmlib_getstatus()) == 0){ + if(ui_loop_hook) + detach=ui_loop_hook(0); + if(detach||ctrlc_int) { + if ((ret = bdmlib_ioctl(BDM_STOP_CHIP))) { + fprintf_filtered(gdb_stderr, + "bdm_wait: failed to stop chip %s\n", + bdmlib_geterror_str(ret)); + } + } + + nap(100000); + + } + if ((rv = sigaction(SIGINT, &old, &new)) == -1) { + error("Cannot restore handler for ctrl-c"); + } + + switch (bdm_stat) { + case BDM_TARGETNC: + status->kind = TARGET_WAITKIND_EXITED; + status->value.integer = 9999; + break; + case BDM_TARGETPOWER: + status->kind = TARGET_WAITKIND_STOPPED; + status->value.sig = TARGET_SIGNAL_PWR; + break; + case BDM_TARGETRESET: + status->kind = TARGET_WAITKIND_STOPPED; + status->value.sig = TARGET_SIGNAL_ABRT; + break; + case BDM_TARGETSTOPPED: + if (ctrlc_int) { + status->kind = TARGET_WAITKIND_STOPPED; + status->value.sig = TARGET_SIGNAL_TSTP; + } else { + bdmlib_get_sys_reg(BDM_REG_ATEMP, &val); + val_conv = extract_unsigned_integer(&val, 4); + val_h = (val_conv >> 16); val_l = (val_conv & 0xffff); + bdmlib_log("bdm_target_stopped ATEMP val %#x = (hi %#x lo %#x)\n", + val_conv, val_h, val_l); + switch (val_l) { + case 0xffff: /* double bus fault */ + status->kind = TARGET_WAITKIND_STOPPED; + status->value.sig = TARGET_SIGNAL_BUS; + break; + case 0x0: /* HW bkpt */ + if (val_h == 0) { + bdmlib_log("HW Breakpoint entered\n"); + status->kind = TARGET_WAITKIND_STOPPED; + status->value.sig = TARGET_SIGNAL_TRAP; + } else { + bdmlib_log("Error: HW Bpt, but highbyte != 0; %#x\n", + val_h); + } + break; + case 0x1: /* background mode */ + bdmlib_log("we have re-entered bdm-mode\n"); + analyze_exception(val_h, status); + break; + default: + bdmlib_log("exception default case: val_l %#x\n", val_l); + printf_filtered("\ + error: bdm-exception default case: val_l %#x\n", val_l); + status->kind = TARGET_WAITKIND_STOPPED; + status->value.sig = TARGET_SIGNAL_GRANT; + + } + } + break; + default: + bdmlib_log("bdm_wait: illegal bdm_stat %#x\n", bdm_stat); + fprintf_filtered(gdb_stderr, "\ + error in bdm_wait: bdm_wait default case: bdm_stat %#x\n", bdm_stat); + } + return inferior_ptid; + } + + static void + bdm_stop(void) + { + #if 1 + int ret; + if ((ret = bdmlib_ioctl(BDM_STOP_CHIP))) { + fprintf_filtered(gdb_stderr, + "bdm_stop: failed to stop chip %s\n", + bdmlib_geterror_str(ret)); + } + #else + ctrlc_int++; + #endif + } + + /* This is called not only when we first attach, but also when the + user types "run" after having attached. */ + void + bdm_create_inferior (char *execfile, char *args, char **env) + { + char *prg_file = NULL; + char *helper; + char *query_old = NULL; + char *query_str = NULL; + int ret; + u_long start_addr; + + bdmlib_log("bdm_create_inferior: execfile %s args=%s, env=%s\n", + execfile, args, *env); + + bdm_check_fd(); bdm_check_status(); + bdm_kill(); + bdm_clear_breakpoints(); + clear_proceed_status(); + init_wait_for_inferior(); + if (*args) { + prg_file = args; + } else if (execfile) { + prg_file = execfile; + } else { + prg_file = bdm_prog_loaded; + } + if (!(prg_file) && !(bdm_prog_loaded)) + error("No program specified to run"); + + if (bdm_prog_loaded) { + xasprintf(&query_old, + "Note - following file already loaded : '%s'\n", + bdm_prog_loaded); + } + xasprintf(&query_str, "%sDo you want to download '%s'\n", + query_old?query_old:"",prg_file); + xfree(query_old); + if (query(query_str)) { + xfree(query_str); + query_str=NULL; + /* The "entry_name" can be translated to address by "bdmlib" + but we prefer GDB's more powerful parse_and_eval_address */ + if (( ret = bdmlib_load(prg_file, NULL, &entry_pt))) { + fprintf_filtered(gdb_stderr, "Error %s\n", + bdmlib_geterror_str(ret)); + error("Download failed"); + } + helper = savestring(prg_file, strlen(prg_file)); + if (bdm_prog_loaded) free(bdm_prog_loaded); + bdm_prog_loaded = helper; + } + xfree(query_str); + query_str=NULL; + + if (!entry_pt && !entry_name) + error("No entry point defined, cannot start program."); + + start_addr = entry_pt; + if(entry_name) + start_addr = parse_and_eval_address (entry_name); + + bdmlib_log("bdm_create_inferior:\n"); + bdmlib_log("\tset pc to %#x and start prg\n", entry_pt); + bdm_ops.to_has_execution++; + + if(ptid_equal(inferior_ptid, null_ptid)) { + inferior_ptid = pid_to_ptid(BDM_MAGIC_NULL_PID); + } + proceed(start_addr, TARGET_SIGNAL_DEFAULT, 0); + } + + static void + bdm_mourn_inferior () + { + bdmlib_log("bdm_mourn_inferior\n"); + bdm_clear_breakpoints(); + generic_mourn_inferior (); + } + + /* Get ready to modify the registers array. On machines which store + individual registers, this doesn't need to do anything. On machines + which store all the registers in one fell swoop, this makes sure + that registers contains all the registers from the program being + debugged. */ + + void + bdm_prepare_to_store(void) + { + /* Do nothing, since we can store individual regs */ + } + + + /* Read the remote registers. */ + static void + bdm_fetch_registers (void) + { + int regno; + + bdmlib_log("bdm_fetch_registers\n"); + for (regno = 0; regno <= PC_REGNUM; regno++) + bdm_fetch_register(regno); + } + + /* + * Fetch register REGNO, or all registers if REGNO is -1. + */ + static void + bdm_fetch_register(int regno) + { + u_int val; + int ret; + int special_regno; + bdm_check_fd(); bdm_check_status(); + if (regno < 0) + bdm_fetch_registers(); + else { + bdmlib_log("bdm_fetch_register %d\n", regno); + if (regno < 16) { + ret = bdmlib_get_reg(regno, &val); + } else { + switch (regno) { + case 16: special_regno = BDM_REG_SR; break; + case 17: special_regno = BDM_REG_RPC; break; + case 18: special_regno = BDM_REG_PCC; break; + case 19: special_regno = BDM_REG_USP; break; + case 20: special_regno = BDM_REG_SSP; break; + case 21: special_regno = BDM_REG_SFC; break; + case 22: special_regno = BDM_REG_DFC; break; + case 23: special_regno = BDM_REG_ATEMP; break; + case 24: special_regno = BDM_REG_FAR; break; + case 25: special_regno = BDM_REG_VBR; break; + default: + error("illegal regno in bdm_fetch_register() %d", regno); + } + ret = bdmlib_get_sys_reg(special_regno, &val); + } + if (ret < 0) { + fprintf_filtered(gdb_stderr, + "get register failed: %s\n", bdmlib_geterror_str(ret)); + } else { + supply_register (regno, (char *) &val); + } + } + } + + /* Store the remote registers from the contents of the block REGS. */ + static void + bdm_store_registers(void) + { + int regno; + bdmlib_log("bdm_store_registers\n"); + for (regno = 0; regno <= PC_REGNUM; regno++) + bdm_store_register(regno); + } + + /* Store register REGNO, or all if REGNO == -1. Return errno value. */ + void + bdm_store_register(int regno) + { + u_int val, special_regno; + int ret; + + bdm_check_fd(); bdm_check_status(); + if (regno == -1) { + bdm_store_registers(); + } else { + val = read_register(regno); + bdmlib_log("bdm_store_register %d with value %#x\n", + regno, val); + if (regno < 16) { + ret = bdmlib_set_reg(regno, val); + } else { + switch (regno) { + case 16: special_regno = BDM_REG_SR; break; + case 17: special_regno = BDM_REG_RPC; break; + case 18: special_regno = BDM_REG_PCC; break; + case 19: special_regno = BDM_REG_USP; break; + case 20: special_regno = BDM_REG_SSP; break; + case 21: special_regno = BDM_REG_SFC; break; + case 22: special_regno = BDM_REG_DFC; break; + case 23: special_regno = BDM_REG_ATEMP; break; + case 24: special_regno = BDM_REG_FAR; break; + case 25: special_regno = BDM_REG_VBR; break; + default: + error("illegal regno in bdm_store_register() %d", regno); + } + ret = bdmlib_set_sys_reg(special_regno, val); + } + if (ret < 0) { + fprintf_filtered(gdb_stderr, + "set register failed: %s\n", bdmlib_geterror_str(ret)); + } + } + } + + static int + bdm_xfer_inferior_memory(CORE_ADDR memaddr, char *myaddr, int len, + int write, + struct mem_attrib *attrib ATTRIBUTE_UNUSED, + struct target_ops *t ATTRIBUTE_UNUSED) + { + caddr_t cptr; + int count; + bdm_check_fd(); bdm_check_status(); + bdmlib_log("bdm_xfer_inferior_memory memaddr %#x len %d write %d\n", + memaddr, len, write); + + count = 0; cptr = (caddr_t) memaddr; + if (write) { + if (len <= (bdm_xfer_use_fast? 1 : 4) ) { + while (len--) { + if (bdmlib_write_var(cptr, + BDM_SIZE_BYTE, *myaddr++) < 0) + break; + count++; + cptr++; + } + } else { + count = bdmlib_write_block((caddr_t)memaddr, len, myaddr); + } + } else { + if (len <= (bdm_xfer_use_fast? 1 : 4) ) { + while (len--) { + if (bdmlib_read_var(cptr, + BDM_SIZE_BYTE, (u_int *) (myaddr++)) < 0) + break; + cptr++; + count++; + } + } else { + count = bdmlib_read_block((caddr_t) memaddr, len, myaddr); + } + } + return count; + } + + static void + bdm_files_info(struct target_ops *t) + { + printf_filtered("target %s is attached to %s\n", + t->to_shortname, dev_name); + if (bdm_prog_loaded) { + printf_filtered("and running program %s\n", bdm_prog_loaded); + } else { + printf_filtered("no program loaded\n"); + } + } + + static int + bdm_insert_breakpoints(CORE_ADDR addr, char *save) + { + int i; + struct _bdm_bp *p; + + bdm_check_fd(); bdm_check_status(); + for (i=0, p = bdm_bp; i < BREAKPOINT_MAX; i++, p++) { + if (p->valid == 0) { + p->valid++; + p->addr = addr; + break; + } + } + if (i == BREAKPOINT_MAX) error("Insert of breakpoints failed"); + bdmlib_log("bdm_insert_breakpoints at %#x \n", addr); + return memory_insert_breakpoint(addr, save); + } + + static int + bdm_remove_breakpoints(CORE_ADDR addr, char *save) + { + int i; + struct _bdm_bp *p; + + bdm_check_fd(); bdm_check_status(); + bdmlib_log("bdm_remove_breakpoint at %#x \n", addr); + for (i=0, p = bdm_bp; i < BREAKPOINT_MAX; i++, p++) { + if (p->addr == addr) { + p->valid = 0; + break; + } + } + if (i == BREAKPOINT_MAX) error("Remove of breakpoints failed"); + return memory_remove_breakpoint(addr, save); + } + + /* Clear bdm's notion of what the break points are */ + static void + bdm_clear_breakpoints(void) + { + int i; + struct _bdm_bp *p; + bdmlib_log("bdm_clear_breakpoints\n"); + for (i=0, p = bdm_bp; i < BREAKPOINT_MAX; i++, p++) { + p->valid = 0; + } + } + + static void + bdm_load (char *args, int from_tty) + { + char *p; + int ret; + + #if 1 + inferior_ptid = null_ptid ; /* No process now */ + + /* This is necessary because many things were based on the PC at the time that + we attached to the monitor, which is no longer valid now that we have loaded + new code (and just changed the PC). Another way to do this might be to call + normal_stop, except that the stack may not be valid, and things would get + horribly confused... */ + #endif + + bdmlib_log("bdm_load: arg <%s> from_tty %d autoreset %d\n", + args, from_tty, bdm_autoreset); + + if (!strncmp(args, "section", 7)) { + while (*args && !isspace(*args)) args++; + while (*args && isspace(*args)) args++; + bdmlib_log("bdm_load section %s requested\n", args); + if (!bdm_prog_loaded) { + error("\ + 'load section' is only possible, if there has been already \n\ + loaded an executable. Use 'run []' for this."); + } + if ((ret = + bdmlib_do_load_binary_section(bdm_prog_loaded, args))) { + fprintf_filtered(gdb_stderr, + "load section %s for %s failed\n%s\n", + args, bdm_prog_loaded, + bdmlib_geterror_str(ret)); + } + } else { + if (bdm_prog_loaded) { + free(bdm_prog_loaded); + bdm_prog_loaded = NULL; + } + if (!args) { + error("\n" + "'load' must be called together with the filename to load.\n\n" + "You may want to use 'run', which uses the parameter supplied when gdb\n" + "was invoked via commandline, e.g. 'gdb68 x.coff'."); + } + + /* strip off additional (unwanted) arguments after file name */ + for (p = args; (*p != '\0') && (!isspace (*p)); p++) + ; + *p = '\0'; + + if ((ret = bdmlib_load(args, NULL, &entry_pt))) { + fprintf_filtered(gdb_stderr, "load failed, error %s\n", + bdmlib_geterror_str(ret)); + return; + } + + bdm_prog_loaded = savestring(args, strlen(args)); + } + } + + + #ifdef ENABLE_BDM_FLASH + + #define AUTO_ADR_CSBOOT ((caddr_t)-100) + #define AUTO_ADR_CSX ((caddr_t)-100+1) + + static int bdm_next_filt_id=0; + + static void + bdm_filt_print(bdmlib_bfilt_t *filt, int flags) + { + flash_alg_info_t const *alg; + printf_filtered("region %2d",filt->filt_id); + if((filt->begin_adr!=filt->end_adr)|| + (filt->begin_adrbegin_adr>=AUTO_ADR_CSBOOT+12)){ + printf_filtered(" addr 0x%06lx-0x%06lx", + (unsigned long)filt->begin_adr,(unsigned long)filt->end_adr); + }else{ + if(filt->begin_adr==AUTO_ADR_CSBOOT) + printf_filtered(" addr from csboot"); + else + printf_filtered(" addr from cs%d",filt->begin_adr-AUTO_ADR_CSX); + } + if(filt->flags&BDMLIB_FILT_FLASH){ + printf_filtered(" flash"); + if(filt->flags&BDMLIB_FILT_AUTO) printf_filtered(" auto"); + alg = (flash_alg_info_t *) filt->info; + if(alg!=NULL){ + printf_filtered(" %s",alg->alg_name); + } + } + if(!(flags&1))printf_filtered("\n"); + + } + + void bdm_filt_free(bdmlib_bfilt_t *filt) + { + if(filt->state) free(filt->state); + filt->state=NULL; + free(filt); + } + + static void + bdm_flash_setup_interactive(char *buf, int from_tty) + { + char *p,*r; + int i; + caddr_t begin_adr=(caddr_t)(0); + caddr_t end_adr=(caddr_t)(0); + char alg_name[32]; + flash_alg_info_t const *alg=NULL; + bdmlib_bfilt_t *filt; + + bdmlib_log("bdm_flash_setup_interactive: arg <%s> from_tty %d\n", + buf, from_tty); + bdm_check_fd(); + + if(!buf){ + printf_filtered("Defined memory ranges :\n"); + for(filt=bdmlib_bfilt;filt!=NULL;filt=filt->next){ + bdm_filt_print(filt,0); + } + return; + } + + while(*buf&&isblank(*buf)) buf++; + if((p=strchr(buf,'@'))!=NULL){/* '@' character in specification */ + i=p-buf; + if(i>=sizeof(alg_name)-1) + i=sizeof(alg_name)-1; + strncpy(alg_name,buf,i); + alg_name[i]=0; + p++; + if(!strncmp(p,"csboot",6)){ /* take address from CSBOOT */ + p+=6; + end_adr=begin_adr=AUTO_ADR_CSBOOT; + }else if(!strncmp(p,"cs",2)){ + p+=2; + end_adr=begin_adr=AUTO_ADR_CSX+strtoul(p,&r,0); + if((p==r)||(begin_adr>AUTO_ADR_CSX+11)){ + error("%s : bad chipselect format\n",buf); + return; + } + p=r; + }else{ /* take begin address after '@' */ + end_adr=begin_adr=(caddr_t)strtoul(p,&r,0); + if(p==r){ + error("%s : bad begin address format\n",buf); + return; + } + p=r; + if(*p=='+'){ /* take end address from size */ + end_adr=begin_adr+strtoul(++p,&r,0)-1; + if(p==r){ + error("%s : bad size format\n",buf); + return; + } + p=r; + } else if(*p=='-') { /* take absolute end address */ + end_adr=(caddr_t)strtoul(++p,&r,0); + if(p==r){ + error("%s : bad end address format\n",buf); + return; + } + p=r; + } + } + while(*buf&&isblank(*buf)) buf++; + if(*p){ + error("%s : extra characters in specification %s\n",buf,p); + return; + } + } + else { + end_adr=begin_adr=AUTO_ADR_CSBOOT; + strncpy(alg_name,buf,sizeof(alg_name)-1); + } + + if(strcmp(alg_name,"auto")){ + int alg_indx=0; + do{ + alg=flash_alg_infos[alg_indx++]; + if(alg==NULL){ + error("%s : unknown flash type or algorithm\n",alg_name); + return; + } + }while(strcmp(alg_name,alg->alg_name)); + } + + filt=(bdmlib_bfilt_t*)malloc(sizeof(bdmlib_bfilt_t)); + if(filt==NULL){ + error("No memory for flash_setup\n"); + return; + } + memset(filt,0,sizeof(*filt)); + + filt->flags=BDMLIB_FILT_FLASH; + if(alg==NULL){ + filt->flags|=BDMLIB_FILT_AUTO; + filt->info=flash_alg_infos[0]; + } else filt->info=(void *)alg; + filt->begin_adr=begin_adr; + filt->end_adr=end_adr; + if(begin_adr==end_adr){ + filt->flags|=BDMLIB_FILT_AUTO; + }; + filt->filt_id=bdm_next_filt_id++; + filt->wrb_filt=&bdmflash_wrb_filt; + + filt->next=bdmlib_bfilt; + bdmlib_bfilt=filt; + return; + } + + static void + bdm_flash_remove_interactive(char *arg, int from_tty) + { + bdmlib_bfilt_t *filt,**ppfilt; + int filt_id; + if(!arg){ + printf_filtered("bdm_flash_remove needs one argument - id of region or \"all\"\n"); + return; + } + if(!strcmp(arg,"all")){ + while(bdmlib_bfilt){ + filt=bdmlib_bfilt; + bdmlib_bfilt=filt->next; + bdm_filt_free(filt); + } + return; + } + filt_id=atoi(arg); + for(ppfilt=&bdmlib_bfilt;(filt=*ppfilt)!=NULL;ppfilt=&(filt->next)){ + if(filt->filt_id==filt_id){ + *ppfilt=filt->next; + bdm_filt_free(filt); + return; + } + } + error("no region with id %d found\n",filt_id); + } + + static int + bdm_flash_check_one (bdmlib_bfilt_t *filt, int autoset) + { + flash_alg_info_t const *alg; + caddr_t adr; + u_int16_t readid[2]; + int ret; + + alg = (flash_alg_info_t *) filt->info; + adr = filt->begin_adr; + + if(filt->flags&BDMLIB_FILT_AUTO) + { + autoset|=2; + if(adr==filt->end_adr) + autoset|=4; + } + + if ((autoset & 4)&&(adr>=AUTO_ADR_CSBOOT)&&(adr<=AUTO_ADR_CSBOOT+12)) + { + u_int32_t csx_opt, csx_base, csx_size; + caddr_t cpu32csopt_adr; + cpu32csopt_adr=(caddr_t)0xfffa48+(adr-AUTO_ADR_CSBOOT)*4; + if (bdmlib_read_var (cpu32csopt_adr, BDM_SIZE_LONG, &csx_opt) >= 0) + { + static u_int32_t csx_sizes[]={1<<11,1<<13,1<<14,1<<16, + 1<<17,1<<18,1<<19,1<<20}; + csx_base = (csx_opt >> 8) & 0xfff800; + filt->begin_adr = (caddr_t) csx_base; + csx_size = csx_sizes[(csx_opt >> 16) & 0x7]; + filt->end_adr = (caddr_t) (csx_base + csx_size - 1); + if(adr==AUTO_ADR_CSBOOT) + printf_filtered("Flash addresses taken from CSBOOT\n"); + else + printf_filtered("Flash addresses taken from CS%d\n", + (int)(adr-AUTO_ADR_CSX)); + printf_filtered("Start %06lX End %06lX\n", + (long) filt->begin_adr, (long) filt->end_adr); + } + } + + adr = filt->begin_adr; + + ret = bdmflash_check_id (alg, adr, readid); + if((ret >= 0)&&(autoset&4)&&(filt->begin_adr==filt->end_adr)) + filt->end_adr=filt->begin_adr+alg->addr_mask; + if (ret >= 0) + { + bdm_filt_print(filt,1); + printf_filtered(" OK\n"); + return 1; + } + if (!autoset & 2) + { + bdm_filt_print(filt,0); + error("Flash parameters are incorrect !!!\n"); + return -1; + } + alg = bdmflash_alg_probe (adr); + if (alg == NULL) + { + bdm_filt_print(filt,0); + error("Flash parameters cannot be probed\n"); + return -1; + } + ret = bdmflash_check_id (alg, adr, readid); + if (ret < 0) + { + bdm_filt_print(filt,0); + error("Probed parameters are incorrect\n"); + return -1; + } + filt->info = (void *) alg; + if(filt->begin_adr==filt->end_adr) + filt->end_adr=filt->begin_adr+alg->addr_mask; + bdm_filt_print(filt,1); + printf_filtered(" probed OK\n"); + + return 1; + } + + static void + bdm_flash_check_interactive(char *arg, int from_tty) + { + int ret; + int autoset=0; + bdmlib_bfilt_t *filt = bdmlib_bfilt; + if(arg&&!strcmp(arg,"autoset")){ + autoset=255; + } + printf_filtered("\n"); + while(filt) + { + if(filt->flags&BDMLIB_FILT_FLASH) + { + ret=bdm_flash_check_one(filt,autoset); + printf_filtered("\n"); + if(ret<0) + return; + } + filt=filt->next; + } + return; + } + + static void + bdm_flash_erase_interactive(char *arg, int from_tty) + { + int ret; + bdmlib_bfilt_t *filt = bdmlib_bfilt; + while(filt) + { + if(filt->flags&BDMLIB_FILT_FLASH) + { + ret=bdmflash_erase_filt (filt, (caddr_t) 0, 0); + if(ret<0){ + printf_filtered("Flash erase failed for\n"); + bdm_filt_print(filt,0); + return; + } + } + filt=filt->next; + } + return; + } + + static void + bdm_load_use_lma_interactive(char *arg, int from_tty) + { + if(!arg){ + printf_filtered("bdm_load_use_lma %d\n",bdmlib_load_use_lma); + }else{ + bdmlib_load_use_lma=atoi(arg); + } + } + + #endif /*ENABLE_BDM_FLASH*/ + + struct target_ops bdm_ops ; + + static void + init_bdm_ops(void) + { + bdm_ops.to_shortname = "bdm"; + bdm_ops.to_longname = "CPU32(+) Background Debug Mode Interface for download and remote debugging"; + bdm_ops.to_doc = "Debug with the Background Debug Mode\n\ + using a BDM-Interface connected to the BDM-port of a CPU32(+) \n\ + based microcontroller and to a parallel port of the PC.\n\ + Makes use of a loadable driver under Linux. \n\ + Usage: target bdm \n\ + Specify the device name the BDM interface is connected to (e.g. /dev/pdbdm0)."; + bdm_ops.to_open = bdm_open; + bdm_ops.to_close = bdm_close; + bdm_ops.to_attach = bdm_attach; + bdm_ops.to_post_attach = NULL; + bdm_ops.to_require_attach = NULL; + bdm_ops.to_detach = bdm_detach; + bdm_ops.to_require_detach = NULL; + bdm_ops.to_resume = bdm_resume; + bdm_ops.to_wait = bdm_wait; + bdm_ops.to_post_wait = NULL; + bdm_ops.to_fetch_registers = bdm_fetch_register; + bdm_ops.to_store_registers = bdm_store_register; + bdm_ops.to_prepare_to_store = bdm_prepare_to_store; + bdm_ops.to_xfer_memory = bdm_xfer_inferior_memory; + bdm_ops.to_files_info = bdm_files_info; + bdm_ops.to_insert_breakpoint = bdm_insert_breakpoints; + bdm_ops.to_remove_breakpoint = bdm_remove_breakpoints; + bdm_ops.to_terminal_init = 0; + bdm_ops.to_terminal_inferior = 0; + bdm_ops.to_terminal_ours_for_output = 0; + bdm_ops.to_terminal_ours = 0; + bdm_ops.to_terminal_info = 0; + bdm_ops.to_kill = bdm_kill; + bdm_ops.to_load = bdm_load; + bdm_ops.to_lookup_symbol = 0; + bdm_ops.to_create_inferior = bdm_create_inferior; + bdm_ops.to_post_startup_inferior = NULL; + bdm_ops.to_acknowledge_created_inferior = NULL; + bdm_ops.to_clone_and_follow_inferior = NULL; + bdm_ops.to_post_follow_inferior_by_clone = NULL; + bdm_ops.to_insert_fork_catchpoint = NULL; + bdm_ops.to_remove_fork_catchpoint = NULL; + bdm_ops.to_insert_vfork_catchpoint = NULL; + bdm_ops.to_remove_vfork_catchpoint = NULL; + bdm_ops.to_has_forked = NULL; + bdm_ops.to_has_vforked = NULL; + bdm_ops.to_can_follow_vfork_prior_to_exec = NULL; + bdm_ops.to_post_follow_vfork = NULL; + bdm_ops.to_insert_exec_catchpoint = NULL; + bdm_ops.to_remove_exec_catchpoint = NULL; + bdm_ops.to_has_execd = NULL; + bdm_ops.to_reported_exec_events_per_exec_call = NULL; + bdm_ops.to_has_syscall_event = NULL; + bdm_ops.to_has_exited = NULL; + bdm_ops.to_mourn_inferior = bdm_mourn_inferior; + bdm_ops.to_can_run = bdm_can_run; + bdm_ops.to_notice_signals = NULL; + bdm_ops.to_thread_alive = NULL; + bdm_ops.to_stop = bdm_stop; + bdm_ops.to_query = NULL; + bdm_ops.to_enable_exception_callback = NULL; + bdm_ops.to_get_current_exception_event = NULL; + bdm_ops.to_pid_to_exec_file = NULL; + /* bdm_ops.to_core_file_to_sym_file = NULL; */ + bdm_ops.to_stratum = process_stratum; + bdm_ops.DONT_USE = 0; /* formely to_next = 0 */ + bdm_ops.to_has_all_memory = 1; + bdm_ops.to_has_memory = 1; + bdm_ops.to_has_stack = 1; + bdm_ops.to_has_registers = 1; + bdm_ops.to_has_execution = 1; /* all mem, mem, stack, regs, exec */ + bdm_ops.to_has_thread_control = 0; + bdm_ops.to_sections = NULL; + bdm_ops.to_sections_end = NULL ; + bdm_ops.to_magic = OPS_MAGIC; /* Always the last thing */ + }; + + void + _initialize_remote_bdm () + { + init_bdm_ops(); + add_show_from_set ( + add_set_cmd ("hash", no_class, var_boolean, &hashmark, + "Set display of activity while downloading a file.\n\ + When enabled, a period '.' is displayed.", + &setlist), + &showlist); + add_com ("bdm_reset", class_obscure, + (void (*)(char *, int)) bdm_reset, + "Reset target and stay in BDM-mode."); + add_com ("bdm_release", class_obscure, + (void (*)(char *, int)) bdm_release_chip, + "Reset target without BDM-mode and jump to monitor."); + add_com ("bdm_status", class_obscure, + (void (*)(char *, int)) bdm_get_status_interactive, + "show status of bdm interface; usage: bdm_status\n"); + add_com ("bdm_debug_driver", class_obscure, + bdm_set_debug_driver_interactive, + "switch driver logging between level 0 (no dbg) to 2 (dbg everything)\n\ + usage: bdm_debug_driver "); + add_com ("bdm_log", class_obscure, + bdm_set_debug_interactive, + "switch log on or off; usage: bdm_log on|off\n"); + add_com ("bdm_setdelay", class_obscure, + bdm_setdelay_interactive, + "set delay for download: 10 for 486DX33"); + add_com ("bdm_autoreset", class_obscure, + bdm_setautoreset_interactive, + "issue an automatic reset before download"); + add_com ("bdm_checkcable", class_obscure, + bdm_sensecable_interactive, + "check cable connected and power applied"); + add_com ("bdm_timetocomeup", class_obscure, + bdm_setttcu_interactive, + "set time to wait (in usecs) for a target monitor to come up"); + add_com ("bdm_entry", class_obscure, + bdm_setentry_interactive, + "set entry point of target code for next step, run, etc"); + #ifdef ENABLE_BDM_FLASH + add_com ("bdm_flash_setup", class_obscure, + bdm_flash_setup_interactive, + "set flash parameters; usage: bdm_flash_setup @\n" + "type : {auto|amd29f040|amd29f400|amd29f800|...}\n" + "range: {|+|-}"); + add_com ("bdm_flash_remove", class_obscure, + bdm_flash_remove_interactive, + "remove flash region; usage: bdm_flash_remove {|all}"); + add_com ("bdm_flash_check", class_obscure, + bdm_flash_check_interactive, + "check defined flash ranges; usage: bdm_flash_check [autoset]"); + add_com ("bdm_flash_erase", class_obscure, + bdm_flash_erase_interactive, + "erases defined flash ranges; usage: bdm_flash_erase"); + add_com ("bdm_load_use_lma", class_obscure, + bdm_load_use_lma_interactive, + "use LMA instead of VMA; usage: bdm_load_use_lma {0|1}"); + #endif /*ENABLE_BDM_FLASH*/ + add_com ("bdm_init", class_obscure, + (void (*)(char *, int)) bdm_init, + "Initialize bdm interface"); + add_target (&bdm_ops); + } diff -c -r -P gdb-5.3.original/gdb/target.c gdb-5.3-bdm-683xx/gdb/target.c *** gdb-5.3.original/gdb/target.c Mon Aug 26 21:18:33 2002 --- gdb-5.3-bdm-683xx/gdb/target.c Fri Aug 15 14:23:26 2003 *************** *** 269,274 **** --- 269,276 ---- return 0; /* No bytes handled */ } + char hashmark; + static void tcomplain (void) {