From adfd70813fe4f9d01bcef1f91392c6c6e0e8ca90 Mon Sep 17 00:00:00 2001 From: Bernd Mueller Date: Wed, 17 Jun 2026 13:44:30 +0200 Subject: [PATCH] initial push --- README | 23 + doc/Makefile | 11 + doc/README | 1 + doc/gdb-bdm.texinfo | 464 ++ gdb/patches/gdb-4.18-bdm-m68k.patch | 1544 ++++ gdb/patches/gdb-5.0-bdm-m68k.patch | 1970 +++++ gdb/patches/gdb-5.2.1-bdm-m68k.patch | 2016 +++++ gdb/patches/gdb-5.3-bdm-m68k.patch | 2043 +++++ gdb/patches/gdb-6.0-bdm-m68k.patch | 2044 +++++ gdb/patches/gdb-6.1-bdm-m68k.patch | 2204 +++++ gdb/patches/gdb-6.3-bdm-m68k.patch | 2504 ++++++ gdb/patches/insight-5.0.patch | 55 + gdb/patches/insight-5.2.1.patch | 56 + gdb/patches/insight-5.3.patch | 79 + gdb/patches/insight-6.0.patch | 56 + gdb/scripts/5206.gdb | 127 + gdb/scripts/Makefile | 15 + gdb/scripts/RTEMS360.gdb | 43 + gdb/scripts/RTEMS5206.gdb | 43 + gdb/scripts/SAL68360.gdb | 78 + gdb/scripts/m68k-rtems-gdb | 3 + gdb/scripts/showCPU32Exception.gdb | 22 + m683xx/README | 28 + m683xx/README-5.3-bdm-683xx | 43 + m683xx/bdm-driver/MAKEDEV | 7 + m683xx/bdm-driver/Makefile | 121 + m683xx/bdm-driver/README | 91 + m683xx/bdm-driver/bdm.c | 1967 +++++ m683xx/bdm-driver/bdm.h | 126 + m683xx/bdm-driver/bdmlib.h | 56 + m683xx/bdm-driver/conf.modules | 9 + m683xx/bdm-driver/k_compat.h | 436 + m683xx/bdm-load/Makefile | 33 + m683xx/bdm-load/README | 188 + m683xx/bdm-load/bdm-load.c | 903 +++ m683xx/bdm-load/bdm-load.lsm | 25 + m683xx/bdm-load/bdm.h | 115 + m683xx/bdm-load/bdm_test.c | 272 + m683xx/bdm-load/bdmflash.c | 945 +++ m683xx/bdm-load/bdmflash.h | 74 + m683xx/bdm-load/bdmlib.c | 1701 ++++ m683xx/bdm-load/bdmlib.h | 83 + m683xx/bdm-load/cpu32init | 65 + m683xx/bdm-load/tpudb.c | 830 ++ m683xx/bdm-load/tpudis.c | 684 ++ m683xx/gdb-5.2.1-bdm-patches-pi1.lsm | 28 + m683xx/gdb-5.2.1-bdm.patch-1 | 4645 +++++++++++ m683xx/gdb-5.3-bdm-683xx-patch | 5240 ++++++++++++ m683xx/insight-5.3-bdm-683xx-patch | 41 + m683xx/scripts/profi360.gdb | 221 + m683xx/scripts/run332.gdb | 335 + m683xx/scripts/run376.gdb | 394 + m68k/.cvsignore | 8 + m68k/BUGS | 62 + m68k/COPYING | 339 + m68k/ChangeLog | 1174 +++ m68k/INSTALL | 234 + m68k/Makefile.am | 57 + m68k/Makefile.in | 666 ++ m68k/README | 909 +++ m68k/README.bdmgdbserver | 282 + m68k/README.cvs | 8 + m68k/README.insight | 73 + m68k/aclocal.m4 | 896 +++ m68k/autom4te.cache/output.0 | 9817 +++++++++++++++++++++++ m68k/autom4te.cache/output.1 | 9817 +++++++++++++++++++++++ m68k/autom4te.cache/requests | 131 + m68k/autom4te.cache/traces.0 | 792 ++ m68k/autom4te.cache/traces.1 | 657 ++ m68k/bdmabstraction/.cvsignore | 5 + m68k/bdmabstraction/BDMDriver.h | 70 + m68k/bdmabstraction/BDMFlash.c | 323 + m68k/bdmabstraction/BDMFlash.h | 117 + m68k/bdmabstraction/BDMTargetAddress.c | 411 + m68k/bdmabstraction/BDMTargetAddress.h | 75 + m68k/bdmabstraction/Debug.h | 64 + m68k/bdmabstraction/Flash.c | 1586 ++++ m68k/bdmabstraction/Flash.h | 258 + m68k/bdmabstraction/Makefile.am | 29 + m68k/bdmabstraction/Makefile.in | 435 + m68k/bdmabstraction/bdmcf.h | 274 + m68k/bdmabstraction/bdmops.c | 792 ++ m68k/bdmabstraction/bdmops.h | 246 + m68k/config.h.in | 115 + m68k/config/.cvsignore | 2 + m68k/config/ax_cflags_warn_all.m4 | 93 + m68k/config/bootstrap | 43 + m68k/config/compile | 142 + m68k/config/config.guess | 1500 ++++ m68k/config/config.sub | 1616 ++++ m68k/config/depcomp | 584 ++ m68k/config/install-sh | 507 ++ m68k/config/missing | 367 + m68k/config/mkinstalldirs | 161 + m68k/config/ylwrap | 223 + m68k/configure | 9817 +++++++++++++++++++++++ m68k/configure.ac | 331 + m68k/driver/ChangeLog | 224 + m68k/driver/bdm-cf-pe.c | 1108 +++ m68k/driver/bdm-cpu32.c | 946 +++ m68k/driver/bdm-tblcf.c | 1100 +++ m68k/driver/bdm.c | 1392 ++++ m68k/driver/bdm.h | 268 + m68k/driver/freebsd/.cvsignore | 8 + m68k/driver/freebsd/ChangeLog | 16 + m68k/driver/freebsd/Makefile | 28 + m68k/driver/freebsd/README | 39 + m68k/driver/freebsd/bdm | 2 + m68k/driver/freebsd/bdm.8 | 20 + m68k/driver/freebsd/freebsd-bdm.c | 500 ++ m68k/driver/freebsd/unbdm | 2 + m68k/driver/ioperm/ioperm.c | 555 ++ m68k/driver/linux-2.6/.cvsignore | 3 + m68k/driver/linux-2.6/Makefile | 14 + m68k/driver/linux-2.6/bdm.c | 374 + m68k/driver/linux/ChangeLog | 83 + m68k/driver/linux/Makefile | 102 + m68k/driver/linux/linux-bdm.c | 441 + m68k/driver/openbsd/Makefile | 9 + m68k/driver/openbsd/README | 58 + m68k/driver/openbsd/bdm-install.sh | 40 + m68k/driver/openbsd/openbsd-bdm.c | 443 + m68k/driver/sco/Makefile | 20 + m68k/driver/sco/Master | 1 + m68k/driver/sco/Node | 8 + m68k/driver/sco/README | 51 + m68k/driver/sco/Space.c | 36 + m68k/driver/sco/System | 4 + m68k/driver/sco/sco.c | 276 + m68k/driver/win/ChangeLog | 44 + m68k/driver/win/win-bdm.c | 535 ++ m68k/driver/win/win-io.h | 103 + m68k/flashlib/.cvsignore | 4 + m68k/flashlib/Makefile.am | 109 + m68k/flashlib/Makefile.in | 575 ++ m68k/flashlib/PLUGIN-MAPPING | 33 + m68k/flashlib/README | 113 + m68k/flashlib/bdmfilt.c | 58 + m68k/flashlib/bdmfilt.h | 36 + m68k/flashlib/bdmflash.c | 989 +++ m68k/flashlib/bdmflash.h | 75 + m68k/flashlib/elf-utils.c | 448 ++ m68k/flashlib/elf-utils.h | 76 + m68k/flashlib/flash29.c | 689 ++ m68k/flashlib/flash29.h | 47 + m68k/flashlib/flash_filter.c | 654 ++ m68k/flashlib/flash_filter.h | 79 + m68k/flashlib/flashcfm.c | 364 + m68k/flashlib/flashcfm.h | 44 + m68k/flashlib/flashintelc3.c | 416 + m68k/flashlib/flashintelc3.h | 32 + m68k/flashlib/m68k-bdm-compile-plugin | 21 + m68k/gdbserver/.cvsignore | 5 + m68k/gdbserver/Makefile.am | 87 + m68k/gdbserver/Makefile.in | 822 ++ m68k/gdbserver/feature_to_c.sh | 75 + m68k/gdbserver/gdb-target.dtd | 45 + m68k/gdbserver/gdb/signals.h | 234 + m68k/gdbserver/gdbserver-regs.xsl | 47 + m68k/gdbserver/inferiors.c | 320 + m68k/gdbserver/m68k-bdm-low.c | 2325 ++++++ m68k/gdbserver/m68k-bdm-low.h | 92 + m68k/gdbserver/m68k-cf5200-regs.c | 74 + m68k/gdbserver/m68k-cf5200.xml | 31 + m68k/gdbserver/m68k-cf52223-regs.c | 80 + m68k/gdbserver/m68k-cf52223.xml | 38 + m68k/gdbserver/m68k-cf5235-regs.c | 82 + m68k/gdbserver/m68k-cf5235.xml | 40 + m68k/gdbserver/m68k-cf5272-regs.c | 76 + m68k/gdbserver/m68k-cf5272.xml | 35 + m68k/gdbserver/m68k-cf5282-regs.c | 82 + m68k/gdbserver/m68k-cf5282.xml | 40 + m68k/gdbserver/m68k-cf5307-regs.c | 76 + m68k/gdbserver/m68k-cf5307.xml | 25 + m68k/gdbserver/m68k-cfv4e-regs.c | 106 + m68k/gdbserver/m68k-cfv4e.xml | 54 + m68k/gdbserver/m68k-core-regs.c | 57 + m68k/gdbserver/m68k-core.xml | 31 + m68k/gdbserver/m68k-cpu32-regs.c | 64 + m68k/gdbserver/m68k-cpu32.xml | 22 + m68k/gdbserver/m68k-cpu32plus-regs.c | 67 + m68k/gdbserver/m68k-cpu32plus.xml | 25 + m68k/gdbserver/m68k-fpu.xml | 22 + m68k/gdbserver/mem-break.c | 292 + m68k/gdbserver/mem-break.h | 77 + m68k/gdbserver/move-if-change | 22 + m68k/gdbserver/number-regs.xsl | 47 + m68k/gdbserver/regcache.c | 281 + m68k/gdbserver/regcache.h | 70 + m68k/gdbserver/regdef.h | 58 + m68k/gdbserver/remote-utils.c | 1317 +++ m68k/gdbserver/server.c | 1297 +++ m68k/gdbserver/server.h | 246 + m68k/gdbserver/signals.c | 833 ++ m68k/gdbserver/sort-regs.xsl | 11 + m68k/gdbserver/target.c | 111 + m68k/gdbserver/target.h | 237 + m68k/gdbserver/terminal.h | 51 + m68k/gdbserver/utils.c | 121 + m68k/gdbserver/version.in | 1 + m68k/gdbserver/xinclude.dtd | 13 + m68k/lib/.cvsignore | 5 + m68k/lib/BDMlib.h | 153 + m68k/lib/ChangeLog | 111 + m68k/lib/Makefile.am | 46 + m68k/lib/Makefile.in | 495 ++ m68k/lib/bdmIO.c | 1283 +++ m68k/lib/bdmRemote.c | 881 ++ m68k/lib/bdmRemote.h | 60 + m68k/libelf/COPYING.LIB | 481 ++ m68k/libelf/ChangeLog | 1392 ++++ m68k/libelf/INSTALL | 176 + m68k/libelf/MANIFEST | 95 + m68k/libelf/Makefile.in | 198 + m68k/libelf/README | 310 + m68k/libelf/VERSION | 1 + m68k/libelf/acconfig.h | 89 + m68k/libelf/aclocal.m4 | 336 + m68k/libelf/config.guess | 1459 ++++ m68k/libelf/config.h.in | 151 + m68k/libelf/config.sub | 1549 ++++ m68k/libelf/configure | 3910 +++++++++ m68k/libelf/configure.in | 379 + m68k/libelf/install-sh | 119 + m68k/libelf/lib/32.fsize.c | 155 + m68k/libelf/lib/32.getehdr.c | 56 + m68k/libelf/lib/32.getphdr.c | 56 + m68k/libelf/lib/32.getshdr.c | 58 + m68k/libelf/lib/32.newehdr.c | 80 + m68k/libelf/lib/32.newphdr.c | 118 + m68k/libelf/lib/32.xlatetof.c | 438 + m68k/libelf/lib/64.xlatetof.c | 512 ++ m68k/libelf/lib/Makefile.in | 278 + m68k/libelf/lib/Makefile.w32 | 166 + m68k/libelf/lib/assert.c | 33 + m68k/libelf/lib/begin.c | 450 ++ m68k/libelf/lib/build.bat | 36 + m68k/libelf/lib/byteswap.h | 95 + m68k/libelf/lib/checksum.c | 178 + m68k/libelf/lib/cntl.c | 71 + m68k/libelf/lib/config.h.w32 | 161 + m68k/libelf/lib/cook.c | 501 ++ m68k/libelf/lib/data.c | 36 + m68k/libelf/lib/elf_repl.h | 992 +++ m68k/libelf/lib/end.c | 118 + m68k/libelf/lib/errmsg.c | 77 + m68k/libelf/lib/errno.c | 32 + m68k/libelf/lib/errors.h | 100 + m68k/libelf/lib/ext_types.h | 334 + m68k/libelf/lib/fill.c | 29 + m68k/libelf/lib/flag.c | 92 + m68k/libelf/lib/gelf.h | 155 + m68k/libelf/lib/gelfehdr.c | 140 + m68k/libelf/lib/gelfphdr.c | 148 + m68k/libelf/lib/gelfshdr.c | 125 + m68k/libelf/lib/gelftrans.c | 407 + m68k/libelf/lib/getarhdr.c | 37 + m68k/libelf/lib/getarsym.c | 87 + m68k/libelf/lib/getbase.c | 33 + m68k/libelf/lib/getdata.c | 157 + m68k/libelf/lib/getident.c | 48 + m68k/libelf/lib/getscn.c | 48 + m68k/libelf/lib/hash.c | 38 + m68k/libelf/lib/input.c | 106 + m68k/libelf/lib/kind.c | 33 + m68k/libelf/lib/libelf.def | 82 + m68k/libelf/lib/libelf.h | 284 + m68k/libelf/lib/memset.c | 53 + m68k/libelf/lib/ndxscn.c | 33 + m68k/libelf/lib/newdata.c | 56 + m68k/libelf/lib/newscn.c | 145 + m68k/libelf/lib/next.c | 42 + m68k/libelf/lib/nextscn.c | 54 + m68k/libelf/lib/nlist.c | 253 + m68k/libelf/lib/nlist.h | 48 + m68k/libelf/lib/opt.delscn.c | 205 + m68k/libelf/lib/private.h | 425 + m68k/libelf/lib/rand.c | 43 + m68k/libelf/lib/rawdata.c | 89 + m68k/libelf/lib/rawfile.c | 52 + m68k/libelf/lib/strptr.c | 150 + m68k/libelf/lib/swap64.c | 81 + m68k/libelf/lib/sys_elf.h.in | 130 + m68k/libelf/lib/sys_elf.h.w32 | 130 + m68k/libelf/lib/update.c | 1019 +++ m68k/libelf/lib/verdef.h | 241 + m68k/libelf/lib/verdef_32_tof.c | 53 + m68k/libelf/lib/verdef_32_tom.c | 53 + m68k/libelf/lib/verdef_64_tof.c | 53 + m68k/libelf/lib/verdef_64_tom.c | 53 + m68k/libelf/lib/verneed.h | 245 + m68k/libelf/lib/version.c | 44 + m68k/libelf/lib/x.elfext.c | 175 + m68k/libelf/lib/x.movscn.c | 112 + m68k/libelf/lib/x.remscn.c | 119 + m68k/libelf/libelf.pc.in | 12 + m68k/libelf/mkinstalldirs | 35 + m68k/libelf/po/Makefile.in | 184 + m68k/libelf/po/de.gmo | Bin 0 -> 8748 bytes m68k/libelf/po/de.msg | 1 + m68k/libelf/po/de.po | 345 + m68k/libelf/po/gmo2msg.c | 121 + m68k/libelf/po/libelf.pot | 321 + m68k/libelf/po/stamp-po | 1 + m68k/libelf/stamp-h.in | 1 + m68k/local_scripts/MAKEDEV | 50 + m68k/local_scripts/README | 2 + m68k/local_scripts/build-it | 135 + m68k/local_scripts/makegdb68kbdm | 18 + m68k/local_scripts/rtsetup | 8 + m68k/packages/.cvsignore | 1 + m68k/packages/gpl.txt | 340 + m68k/packages/m68k-bdm.nsi | 69 + m68k/server/.cvsignore | 5 + m68k/server/ChangeLog | 19 + m68k/server/Makefile.am | 28 + m68k/server/Makefile.in | 444 + m68k/server/bdmServer.c | 769 ++ m68k/server/xmalloc.c | 82 + m68k/tblcf/.cvsignore | 5 + m68k/tblcf/Makefile.am | 60 + m68k/tblcf/Makefile.in | 574 ++ m68k/tblcf/commands.h | 81 + m68k/tblcf/log.c | 43 + m68k/tblcf/log.h | 3 + m68k/tblcf/log_cmdline.c | 135 + m68k/tblcf/log_cmdline.h | 35 + m68k/tblcf/srec.c | 118 + m68k/tblcf/srec.h | 4 + m68k/tblcf/tblcf-show.c | 70 + m68k/tblcf/tblcf.c | 778 ++ m68k/tblcf/tblcf.h | 210 + m68k/tblcf/tblcf_bt.c | 288 + m68k/tblcf/tblcf_bt.h | 47 + m68k/tblcf/tblcf_hwdesc.h | 18 + m68k/tblcf/tblcf_unsec.c | 131 + m68k/tblcf/tblcf_usb.c | 458 ++ m68k/tblcf/tblcf_usb.h | 56 + m68k/tblcf/version.h | 47 + m68k/test/.cvsignore | 7 + m68k/test/ChangeLog | 54 + m68k/test/Makefile.am | 41 + m68k/test/Makefile.in | 455 ++ m68k/test/README | 162 + m68k/test/README.cpu32-check | 67 + m68k/test/chk.c | 955 +++ m68k/test/coldfire-trace | 239 + m68k/test/cpu32-check.c | 1335 +++ m68k/test/cpu32-memtest.list | 51 + m68k/test/sram-test.S | 71 + m68k/utils/.cvsignore | 12 + m68k/utils/ChangeLog | 25 + m68k/utils/Makefile.am | 87 + m68k/utils/Makefile.in | 570 ++ m68k/utils/README.bdmctrl | 117 + m68k/utils/bdmctrl.c | 1647 ++++ m68k/utils/bdmflash.c | 380 + m68k/utils/bdmmon.l | 1164 +++ m68k/utils/bdmreset.c | 224 + m68k/utils/m68332.test | 78 + m68k/utils/mcf52235.test | 89 + m68k/utils/mcf5235.test | 96 + m68k/utils/mcf5329.test | 95 + schematics/coldfire/README | 1 + schematics/cpu32/eficd/eficdbdm.pld | 81 + schematics/cpu32/eficd/icd.pld | 55 + schematics/cpu32/icd32/bdm_icd1.eps | 1650 ++++ schematics/cpu32/icd32/bdm_icd2comb.pdf | Bin 0 -> 79688 bytes schematics/cpu32/icd32/icd-bdm2.jed | 76 + schematics/cpu32/icd32/icd.jed | 51 + schematics/cpu32/icd32/icd.log | 117 + schematics/cpu32/icd32/icd.opl | 37 + 372 files changed, 146450 insertions(+) create mode 100644 README create mode 100644 doc/Makefile create mode 100644 doc/README create mode 100644 doc/gdb-bdm.texinfo create mode 100644 gdb/patches/gdb-4.18-bdm-m68k.patch create mode 100644 gdb/patches/gdb-5.0-bdm-m68k.patch create mode 100644 gdb/patches/gdb-5.2.1-bdm-m68k.patch create mode 100644 gdb/patches/gdb-5.3-bdm-m68k.patch create mode 100644 gdb/patches/gdb-6.0-bdm-m68k.patch create mode 100644 gdb/patches/gdb-6.1-bdm-m68k.patch create mode 100644 gdb/patches/gdb-6.3-bdm-m68k.patch create mode 100644 gdb/patches/insight-5.0.patch create mode 100644 gdb/patches/insight-5.2.1.patch create mode 100644 gdb/patches/insight-5.3.patch create mode 100644 gdb/patches/insight-6.0.patch create mode 100644 gdb/scripts/5206.gdb create mode 100644 gdb/scripts/Makefile create mode 100644 gdb/scripts/RTEMS360.gdb create mode 100644 gdb/scripts/RTEMS5206.gdb create mode 100644 gdb/scripts/SAL68360.gdb create mode 100644 gdb/scripts/m68k-rtems-gdb create mode 100644 gdb/scripts/showCPU32Exception.gdb create mode 100644 m683xx/README create mode 100644 m683xx/README-5.3-bdm-683xx create mode 100644 m683xx/bdm-driver/MAKEDEV create mode 100644 m683xx/bdm-driver/Makefile create mode 100644 m683xx/bdm-driver/README create mode 100644 m683xx/bdm-driver/bdm.c create mode 100644 m683xx/bdm-driver/bdm.h create mode 100644 m683xx/bdm-driver/bdmlib.h create mode 100644 m683xx/bdm-driver/conf.modules create mode 100644 m683xx/bdm-driver/k_compat.h create mode 100644 m683xx/bdm-load/Makefile create mode 100644 m683xx/bdm-load/README create mode 100644 m683xx/bdm-load/bdm-load.c create mode 100644 m683xx/bdm-load/bdm-load.lsm create mode 100644 m683xx/bdm-load/bdm.h create mode 100644 m683xx/bdm-load/bdm_test.c create mode 100644 m683xx/bdm-load/bdmflash.c create mode 100644 m683xx/bdm-load/bdmflash.h create mode 100644 m683xx/bdm-load/bdmlib.c create mode 100644 m683xx/bdm-load/bdmlib.h create mode 100644 m683xx/bdm-load/cpu32init create mode 100644 m683xx/bdm-load/tpudb.c create mode 100644 m683xx/bdm-load/tpudis.c create mode 100644 m683xx/gdb-5.2.1-bdm-patches-pi1.lsm create mode 100644 m683xx/gdb-5.2.1-bdm.patch-1 create mode 100644 m683xx/gdb-5.3-bdm-683xx-patch create mode 100644 m683xx/insight-5.3-bdm-683xx-patch create mode 100644 m683xx/scripts/profi360.gdb create mode 100644 m683xx/scripts/run332.gdb create mode 100644 m683xx/scripts/run376.gdb create mode 100644 m68k/.cvsignore create mode 100644 m68k/BUGS create mode 100644 m68k/COPYING create mode 100644 m68k/ChangeLog create mode 100644 m68k/INSTALL create mode 100644 m68k/Makefile.am create mode 100644 m68k/Makefile.in create mode 100644 m68k/README create mode 100644 m68k/README.bdmgdbserver create mode 100644 m68k/README.cvs create mode 100644 m68k/README.insight create mode 100644 m68k/aclocal.m4 create mode 100644 m68k/autom4te.cache/output.0 create mode 100644 m68k/autom4te.cache/output.1 create mode 100644 m68k/autom4te.cache/requests create mode 100644 m68k/autom4te.cache/traces.0 create mode 100644 m68k/autom4te.cache/traces.1 create mode 100644 m68k/bdmabstraction/.cvsignore create mode 100644 m68k/bdmabstraction/BDMDriver.h create mode 100644 m68k/bdmabstraction/BDMFlash.c create mode 100644 m68k/bdmabstraction/BDMFlash.h create mode 100644 m68k/bdmabstraction/BDMTargetAddress.c create mode 100644 m68k/bdmabstraction/BDMTargetAddress.h create mode 100644 m68k/bdmabstraction/Debug.h create mode 100644 m68k/bdmabstraction/Flash.c create mode 100644 m68k/bdmabstraction/Flash.h create mode 100644 m68k/bdmabstraction/Makefile.am create mode 100644 m68k/bdmabstraction/Makefile.in create mode 100644 m68k/bdmabstraction/bdmcf.h create mode 100644 m68k/bdmabstraction/bdmops.c create mode 100644 m68k/bdmabstraction/bdmops.h create mode 100644 m68k/config.h.in create mode 100644 m68k/config/.cvsignore create mode 100644 m68k/config/ax_cflags_warn_all.m4 create mode 100755 m68k/config/bootstrap create mode 100755 m68k/config/compile create mode 100755 m68k/config/config.guess create mode 100755 m68k/config/config.sub create mode 100755 m68k/config/depcomp create mode 100755 m68k/config/install-sh create mode 100755 m68k/config/missing create mode 100755 m68k/config/mkinstalldirs create mode 100755 m68k/config/ylwrap create mode 100755 m68k/configure create mode 100644 m68k/configure.ac create mode 100644 m68k/driver/ChangeLog create mode 100644 m68k/driver/bdm-cf-pe.c create mode 100644 m68k/driver/bdm-cpu32.c create mode 100644 m68k/driver/bdm-tblcf.c create mode 100644 m68k/driver/bdm.c create mode 100644 m68k/driver/bdm.h create mode 100644 m68k/driver/freebsd/.cvsignore create mode 100644 m68k/driver/freebsd/ChangeLog create mode 100644 m68k/driver/freebsd/Makefile create mode 100644 m68k/driver/freebsd/README create mode 100755 m68k/driver/freebsd/bdm create mode 100644 m68k/driver/freebsd/bdm.8 create mode 100644 m68k/driver/freebsd/freebsd-bdm.c create mode 100755 m68k/driver/freebsd/unbdm create mode 100644 m68k/driver/ioperm/ioperm.c create mode 100644 m68k/driver/linux-2.6/.cvsignore create mode 100644 m68k/driver/linux-2.6/Makefile create mode 100644 m68k/driver/linux-2.6/bdm.c create mode 100644 m68k/driver/linux/ChangeLog create mode 100644 m68k/driver/linux/Makefile create mode 100644 m68k/driver/linux/linux-bdm.c create mode 100644 m68k/driver/openbsd/Makefile create mode 100644 m68k/driver/openbsd/README create mode 100755 m68k/driver/openbsd/bdm-install.sh create mode 100644 m68k/driver/openbsd/openbsd-bdm.c create mode 100644 m68k/driver/sco/Makefile create mode 100644 m68k/driver/sco/Master create mode 100644 m68k/driver/sco/Node create mode 100644 m68k/driver/sco/README create mode 100644 m68k/driver/sco/Space.c create mode 100644 m68k/driver/sco/System create mode 100644 m68k/driver/sco/sco.c create mode 100644 m68k/driver/win/ChangeLog create mode 100644 m68k/driver/win/win-bdm.c create mode 100644 m68k/driver/win/win-io.h create mode 100644 m68k/flashlib/.cvsignore create mode 100644 m68k/flashlib/Makefile.am create mode 100644 m68k/flashlib/Makefile.in create mode 100644 m68k/flashlib/PLUGIN-MAPPING create mode 100644 m68k/flashlib/README create mode 100644 m68k/flashlib/bdmfilt.c create mode 100644 m68k/flashlib/bdmfilt.h create mode 100644 m68k/flashlib/bdmflash.c create mode 100644 m68k/flashlib/bdmflash.h create mode 100755 m68k/flashlib/elf-utils.c create mode 100755 m68k/flashlib/elf-utils.h create mode 100644 m68k/flashlib/flash29.c create mode 100644 m68k/flashlib/flash29.h create mode 100644 m68k/flashlib/flash_filter.c create mode 100644 m68k/flashlib/flash_filter.h create mode 100644 m68k/flashlib/flashcfm.c create mode 100644 m68k/flashlib/flashcfm.h create mode 100644 m68k/flashlib/flashintelc3.c create mode 100644 m68k/flashlib/flashintelc3.h create mode 100755 m68k/flashlib/m68k-bdm-compile-plugin create mode 100644 m68k/gdbserver/.cvsignore create mode 100755 m68k/gdbserver/Makefile.am create mode 100644 m68k/gdbserver/Makefile.in create mode 100755 m68k/gdbserver/feature_to_c.sh create mode 100644 m68k/gdbserver/gdb-target.dtd create mode 100644 m68k/gdbserver/gdb/signals.h create mode 100644 m68k/gdbserver/gdbserver-regs.xsl create mode 100644 m68k/gdbserver/inferiors.c create mode 100644 m68k/gdbserver/m68k-bdm-low.c create mode 100644 m68k/gdbserver/m68k-bdm-low.h create mode 100644 m68k/gdbserver/m68k-cf5200-regs.c create mode 100644 m68k/gdbserver/m68k-cf5200.xml create mode 100644 m68k/gdbserver/m68k-cf52223-regs.c create mode 100644 m68k/gdbserver/m68k-cf52223.xml create mode 100644 m68k/gdbserver/m68k-cf5235-regs.c create mode 100644 m68k/gdbserver/m68k-cf5235.xml create mode 100644 m68k/gdbserver/m68k-cf5272-regs.c create mode 100644 m68k/gdbserver/m68k-cf5272.xml create mode 100644 m68k/gdbserver/m68k-cf5282-regs.c create mode 100644 m68k/gdbserver/m68k-cf5282.xml create mode 100644 m68k/gdbserver/m68k-cf5307-regs.c create mode 100644 m68k/gdbserver/m68k-cf5307.xml create mode 100644 m68k/gdbserver/m68k-cfv4e-regs.c create mode 100644 m68k/gdbserver/m68k-cfv4e.xml create mode 100644 m68k/gdbserver/m68k-core-regs.c create mode 100644 m68k/gdbserver/m68k-core.xml create mode 100644 m68k/gdbserver/m68k-cpu32-regs.c create mode 100644 m68k/gdbserver/m68k-cpu32.xml create mode 100644 m68k/gdbserver/m68k-cpu32plus-regs.c create mode 100644 m68k/gdbserver/m68k-cpu32plus.xml create mode 100644 m68k/gdbserver/m68k-fpu.xml create mode 100644 m68k/gdbserver/mem-break.c create mode 100644 m68k/gdbserver/mem-break.h create mode 100755 m68k/gdbserver/move-if-change create mode 100644 m68k/gdbserver/number-regs.xsl create mode 100644 m68k/gdbserver/regcache.c create mode 100644 m68k/gdbserver/regcache.h create mode 100644 m68k/gdbserver/regdef.h create mode 100644 m68k/gdbserver/remote-utils.c create mode 100755 m68k/gdbserver/server.c create mode 100755 m68k/gdbserver/server.h create mode 100644 m68k/gdbserver/signals.c create mode 100644 m68k/gdbserver/sort-regs.xsl create mode 100644 m68k/gdbserver/target.c create mode 100644 m68k/gdbserver/target.h create mode 100644 m68k/gdbserver/terminal.h create mode 100644 m68k/gdbserver/utils.c create mode 100644 m68k/gdbserver/version.in create mode 100644 m68k/gdbserver/xinclude.dtd create mode 100644 m68k/lib/.cvsignore create mode 100644 m68k/lib/BDMlib.h create mode 100644 m68k/lib/ChangeLog create mode 100644 m68k/lib/Makefile.am create mode 100644 m68k/lib/Makefile.in create mode 100644 m68k/lib/bdmIO.c create mode 100644 m68k/lib/bdmRemote.c create mode 100644 m68k/lib/bdmRemote.h create mode 100644 m68k/libelf/COPYING.LIB create mode 100644 m68k/libelf/ChangeLog create mode 100644 m68k/libelf/INSTALL create mode 100644 m68k/libelf/MANIFEST create mode 100644 m68k/libelf/Makefile.in create mode 100644 m68k/libelf/README create mode 100644 m68k/libelf/VERSION create mode 100644 m68k/libelf/acconfig.h create mode 100644 m68k/libelf/aclocal.m4 create mode 100755 m68k/libelf/config.guess create mode 100644 m68k/libelf/config.h.in create mode 100755 m68k/libelf/config.sub create mode 100755 m68k/libelf/configure create mode 100644 m68k/libelf/configure.in create mode 100755 m68k/libelf/install-sh create mode 100644 m68k/libelf/lib/32.fsize.c create mode 100644 m68k/libelf/lib/32.getehdr.c create mode 100644 m68k/libelf/lib/32.getphdr.c create mode 100644 m68k/libelf/lib/32.getshdr.c create mode 100644 m68k/libelf/lib/32.newehdr.c create mode 100644 m68k/libelf/lib/32.newphdr.c create mode 100644 m68k/libelf/lib/32.xlatetof.c create mode 100644 m68k/libelf/lib/64.xlatetof.c create mode 100644 m68k/libelf/lib/Makefile.in create mode 100644 m68k/libelf/lib/Makefile.w32 create mode 100644 m68k/libelf/lib/assert.c create mode 100644 m68k/libelf/lib/begin.c create mode 100644 m68k/libelf/lib/build.bat create mode 100644 m68k/libelf/lib/byteswap.h create mode 100644 m68k/libelf/lib/checksum.c create mode 100644 m68k/libelf/lib/cntl.c create mode 100644 m68k/libelf/lib/config.h.w32 create mode 100644 m68k/libelf/lib/cook.c create mode 100644 m68k/libelf/lib/data.c create mode 100644 m68k/libelf/lib/elf_repl.h create mode 100644 m68k/libelf/lib/end.c create mode 100644 m68k/libelf/lib/errmsg.c create mode 100644 m68k/libelf/lib/errno.c create mode 100644 m68k/libelf/lib/errors.h create mode 100644 m68k/libelf/lib/ext_types.h create mode 100644 m68k/libelf/lib/fill.c create mode 100644 m68k/libelf/lib/flag.c create mode 100644 m68k/libelf/lib/gelf.h create mode 100644 m68k/libelf/lib/gelfehdr.c create mode 100644 m68k/libelf/lib/gelfphdr.c create mode 100644 m68k/libelf/lib/gelfshdr.c create mode 100644 m68k/libelf/lib/gelftrans.c create mode 100644 m68k/libelf/lib/getarhdr.c create mode 100644 m68k/libelf/lib/getarsym.c create mode 100644 m68k/libelf/lib/getbase.c create mode 100644 m68k/libelf/lib/getdata.c create mode 100644 m68k/libelf/lib/getident.c create mode 100644 m68k/libelf/lib/getscn.c create mode 100644 m68k/libelf/lib/hash.c create mode 100644 m68k/libelf/lib/input.c create mode 100644 m68k/libelf/lib/kind.c create mode 100644 m68k/libelf/lib/libelf.def create mode 100644 m68k/libelf/lib/libelf.h create mode 100644 m68k/libelf/lib/memset.c create mode 100644 m68k/libelf/lib/ndxscn.c create mode 100644 m68k/libelf/lib/newdata.c create mode 100644 m68k/libelf/lib/newscn.c create mode 100644 m68k/libelf/lib/next.c create mode 100644 m68k/libelf/lib/nextscn.c create mode 100644 m68k/libelf/lib/nlist.c create mode 100644 m68k/libelf/lib/nlist.h create mode 100644 m68k/libelf/lib/opt.delscn.c create mode 100644 m68k/libelf/lib/private.h create mode 100644 m68k/libelf/lib/rand.c create mode 100644 m68k/libelf/lib/rawdata.c create mode 100644 m68k/libelf/lib/rawfile.c create mode 100644 m68k/libelf/lib/strptr.c create mode 100644 m68k/libelf/lib/swap64.c create mode 100644 m68k/libelf/lib/sys_elf.h.in create mode 100644 m68k/libelf/lib/sys_elf.h.w32 create mode 100644 m68k/libelf/lib/update.c create mode 100644 m68k/libelf/lib/verdef.h create mode 100644 m68k/libelf/lib/verdef_32_tof.c create mode 100644 m68k/libelf/lib/verdef_32_tom.c create mode 100644 m68k/libelf/lib/verdef_64_tof.c create mode 100644 m68k/libelf/lib/verdef_64_tom.c create mode 100644 m68k/libelf/lib/verneed.h create mode 100644 m68k/libelf/lib/version.c create mode 100644 m68k/libelf/lib/x.elfext.c create mode 100644 m68k/libelf/lib/x.movscn.c create mode 100644 m68k/libelf/lib/x.remscn.c create mode 100644 m68k/libelf/libelf.pc.in create mode 100755 m68k/libelf/mkinstalldirs create mode 100644 m68k/libelf/po/Makefile.in create mode 100644 m68k/libelf/po/de.gmo create mode 100644 m68k/libelf/po/de.msg create mode 100644 m68k/libelf/po/de.po create mode 100644 m68k/libelf/po/gmo2msg.c create mode 100644 m68k/libelf/po/libelf.pot create mode 100644 m68k/libelf/po/stamp-po create mode 100644 m68k/libelf/stamp-h.in create mode 100755 m68k/local_scripts/MAKEDEV create mode 100644 m68k/local_scripts/README create mode 100755 m68k/local_scripts/build-it create mode 100644 m68k/local_scripts/makegdb68kbdm create mode 100644 m68k/local_scripts/rtsetup create mode 100644 m68k/packages/.cvsignore create mode 100755 m68k/packages/gpl.txt create mode 100755 m68k/packages/m68k-bdm.nsi create mode 100644 m68k/server/.cvsignore create mode 100644 m68k/server/ChangeLog create mode 100644 m68k/server/Makefile.am create mode 100644 m68k/server/Makefile.in create mode 100644 m68k/server/bdmServer.c create mode 100644 m68k/server/xmalloc.c create mode 100644 m68k/tblcf/.cvsignore create mode 100644 m68k/tblcf/Makefile.am create mode 100644 m68k/tblcf/Makefile.in create mode 100644 m68k/tblcf/commands.h create mode 100644 m68k/tblcf/log.c create mode 100644 m68k/tblcf/log.h create mode 100644 m68k/tblcf/log_cmdline.c create mode 100644 m68k/tblcf/log_cmdline.h create mode 100644 m68k/tblcf/srec.c create mode 100644 m68k/tblcf/srec.h create mode 100644 m68k/tblcf/tblcf-show.c create mode 100644 m68k/tblcf/tblcf.c create mode 100644 m68k/tblcf/tblcf.h create mode 100644 m68k/tblcf/tblcf_bt.c create mode 100644 m68k/tblcf/tblcf_bt.h create mode 100644 m68k/tblcf/tblcf_hwdesc.h create mode 100644 m68k/tblcf/tblcf_unsec.c create mode 100644 m68k/tblcf/tblcf_usb.c create mode 100644 m68k/tblcf/tblcf_usb.h create mode 100644 m68k/tblcf/version.h create mode 100644 m68k/test/.cvsignore create mode 100644 m68k/test/ChangeLog create mode 100644 m68k/test/Makefile.am create mode 100644 m68k/test/Makefile.in create mode 100644 m68k/test/README create mode 100644 m68k/test/README.cpu32-check create mode 100644 m68k/test/chk.c create mode 100644 m68k/test/coldfire-trace create mode 100644 m68k/test/cpu32-check.c create mode 100644 m68k/test/cpu32-memtest.list create mode 100644 m68k/test/sram-test.S create mode 100644 m68k/utils/.cvsignore create mode 100644 m68k/utils/ChangeLog create mode 100644 m68k/utils/Makefile.am create mode 100644 m68k/utils/Makefile.in create mode 100644 m68k/utils/README.bdmctrl create mode 100644 m68k/utils/bdmctrl.c create mode 100644 m68k/utils/bdmflash.c create mode 100644 m68k/utils/bdmmon.l create mode 100644 m68k/utils/bdmreset.c create mode 100644 m68k/utils/m68332.test create mode 100644 m68k/utils/mcf52235.test create mode 100644 m68k/utils/mcf5235.test create mode 100644 m68k/utils/mcf5329.test create mode 100644 schematics/coldfire/README create mode 100644 schematics/cpu32/eficd/eficdbdm.pld create mode 100644 schematics/cpu32/eficd/icd.pld create mode 100644 schematics/cpu32/icd32/bdm_icd1.eps create mode 100644 schematics/cpu32/icd32/bdm_icd2comb.pdf create mode 100644 schematics/cpu32/icd32/icd-bdm2.jed create mode 100644 schematics/cpu32/icd32/icd.jed create mode 100644 schematics/cpu32/icd32/icd.log create mode 100644 schematics/cpu32/icd32/icd.opl diff --git a/README b/README new file mode 100644 index 0000000..d31786c --- /dev/null +++ b/README @@ -0,0 +1,23 @@ +The subdirectories contain: + + m68k/ + The ColdFire/CPU32 BDM driver and tools originally developed by + W. Eric Norum and later enhanced by Chris Johns. + + m683xx/ + The CPU32 BDM driver enhanced by Pavel Pisa. This version + offers better CPU32 support and some features not available + in the m68k driver. + + gdb/patches/ + Patches to add BDM support to GDB. + + gdb/scripts/ + Example GDB command scripts that show how to initialize and run + a Motorola 68360 system using standard GDB commands. + + doc/ + GDB BDM documentation. + + schematics/ + Sample schematics for building ColdFire/CPU32 BDM pods. diff --git a/doc/Makefile b/doc/Makefile new file mode 100644 index 0000000..1d99aa4 --- /dev/null +++ b/doc/Makefile @@ -0,0 +1,11 @@ +# +# $Id: Makefile,v 1.1 2003/06/02 15:13:33 codewiz Exp $ +# + +all: gdb-bdm.info gdb-bdm.html + +gdb-bdm.info: gdb-bdm.texinfo + makeinfo gdb-bdm.texinfo + +gdb-bdm.html: gdb-bdm.texinfo gdb-bdm.init + texi2html -init_file gdb-bdm.init gdb-bdm.texinfo diff --git a/doc/README b/doc/README new file mode 100644 index 0000000..e47d93a --- /dev/null +++ b/doc/README @@ -0,0 +1 @@ +This is a work in progress. diff --git a/doc/gdb-bdm.texinfo b/doc/gdb-bdm.texinfo new file mode 100644 index 0000000..20eddc3 --- /dev/null +++ b/doc/gdb-bdm.texinfo @@ -0,0 +1,464 @@ +\input texinfo +@setfilename gdb-bdm.info +@syncodeindex ky cp + +@c +@c $Id: gdb-bdm.texinfo,v 1.1 2003/06/02 15:13:33 codewiz Exp $ +@c +@c GDB BDM Manual +@c + +@c Parts taken from the Ld, the GNU Linker info page. +@c This is Copyright (C) Free Software Foundation, Inc. + +@ifinfo +@format +START-INFO-DIR-ENTRY +* @sc{gdb-bdm}: GDB m68k Background Debug Mode (BDM). +END-INFO-DIR-ENTRY +@end format +@end ifinfo + +@ifinfo +This file documents the Background Debug support for GDB, the GNU debugger. + +Copyright @copyright{} Free Software Foundation, Inc. + +Permission is granted to make and distribute verbatim copies of +this manual provided the copyright notice and this permission notice +are preserved on all copies. + +Permission is granted to copy and distribute modified versions of this +manual under the conditions for verbatim copying, provided also that +the entire resulting derived work is distributed under the terms of a +permission notice identical to this one. + +Permission is granted to copy and distribute translations of this manual +into another language, under the above conditions for modified versions. + +@ignore +Permission is granted to process this file through Tex and print the +results, provided the printed document carries copying permission +notice identical to this one except for the removal of this paragraph +(this paragraph not being relevant to the printed manual). +@end ignore +@end ifinfo + +@iftex +@finalout +@setchapternewpage odd +@settitle GDB Background Debug Mode Support +@titlepage +@title GDB BDM +@subtitle GDB Background Debug Mode +@sp 1 +@subtitle @code{MRB} version 1 +@subtitle December 1999 +@author Chris Johns (ccj@@acm.org) +@author Objective Design Systems Pty Ltd +@page + +@tex +{\parskip=0pt +\hfill Objective Design Systems Pty Ltd\par +\hfill ccj\@acm.org, cjohns\@cybertec.com.au\par +\hfill {\it Using m68k BDM with GDB, the GNU debugger}\par +\hfill Edited by Chris Johns (ccj@@acm.org)\par +} +\global\parindent=0pt % Steve likes it this way. +@end tex + +@vskip 0pt plus 1filll +Copyright @copyright{} Free Software Foundation, Inc. + +Permission is granted to make and distribute verbatim copies of +this manual provided the copyright notice and this permission notice +are preserved on all copies. + +Permission is granted to copy and distribute modified versions of this +manual under the conditions for verbatim copying, provided also that +the entire resulting derived work is distributed under the terms of a +permission notice identical to this one. + +Permission is granted to copy and distribute translations of this manual +into another language, under the above conditions for modified versions. +@end titlepage +@end iftex + +@ifinfo +@node Top, , , +@top GDB BDM + +This file documents GDB support for BDM for CPU32 and Coldfire processors. + +@menu +* Overview:: Overview +* Hardware:: POD, Pins, Power +* Driver:: The Driver +* Library:: A Library for Applications + +* Testing:: Is BDM working + +* GDB:: Building and using GDB + +* Server:: BDM Server + +@c Following blank line required for remaining bug in makeinfo conds/menus + +* Reporting Bugs:: Reporting Bugs +* Index:: Index +@end menu +@end ifinfo + +@c --------------------------------------- +@node Overview, Build System, Top, Top +@chapter Overview + +@cindex what is this? + +Welcome to Background Debug Mode (BDM) support for GDB. BDM is emulator +or debugger support in a range of Motorola processors. This package +deals with the CPU32, and Coldfire family of processors. PowerPC +processors are not supported by this package. + +CPU32 processors were the first processors to appear with BDM +support. The Coldfire family's BDM module is similar to the CPU32 family +of processors. The CPU32 has the BDM module integrated into the +processor core. The Coldfire is more modular. The debug module is +separate to the core. + +BDM is not JTAG debugging although a serial bug is used. JTAG is a +standard and operates differently to BDM. BDM uses high level commands +to control the device. You do not need to clock in and out a loop of +registers. + +BDM is accessed on the procesor via a three wire serial bus. The signals +are a clock, data in and data out. Various other support signals +exists. This are used to place the processor into BDM, break the +prcessor, or monitor the status of a running processor. + +The CPU32 standard BDM connector is not the same as the Coldfire +connector. You need separate plug on modules for each processor +family. Check the POD you use matches the processors voltage and clock +speed. This is import for Coldfire users. + +Coldfire BDM has support for realtime trace. This package does not +support realtime trace. + +Coldfire BDM can operate in a limited manner while the processor is +running. The BDM module being separate from the procesor core allows +this feature. + +History + +Gunta Magna contributes here is a bit of history of how GDB and BDM +came to light due to mutual support. + +Somewhere in 1994/1995 Gunta Magna wrote (with the help of Michael +Schraut, at that time a student at lpr.e-technik.tu-muenchen) a first +version of the m68k Linux BDM device driver. This driver heavily based +on the work of Scott Howard (scott\@objsw.com), who wrote BD32, a DOS +tool to access 683xx controllers via BDM. He made the driver available +in source form, so I could use them. Scott is currently maintainer of +the crossgcc mailing list (http://www.objsw.com/CrossGCC/). + +Additionally Gunta Magna wrote a BDM backend for gdb-4.13. (Note: Eric +credits M.Schraut falsly as the author of the GDB patches in the header +files. This went through until Chris Johns's version for Coldfire). + +The driver was only for BDM interfaces compatilble to AN1230, aka as PD +interfaces. Scott supported also the ICD compatible interface, but due to +lack of equipment at that time Gunta Magna did not include that. + +Eric Norum used those sources to port it to NextStep. He did not like +my way of interfacing driver and application, and designed a new +interface. He also introduced an abstraction layer, enabling other +applications than gdb to take advantage of the BDM driver. He also added +support for 68360, which is different in detail from the 68332 version +(MBAR support). + +In 1996, Gunta Magna upgraded his driver to ICD by a compile time +option, and fixed some errors. He also upgraded the gdb backend to +gdb-4.16, introducing Eric's idea of the abstraction layer. Sources for +that can be found at the ftp server of lpr.e-technik.tu-muechen.de + +In 1997 Eric went Linux and ported his NextStep driver to Linux. He +also wrote/ported his NextStep gdb backend, incorporating some of the +ideas (and bugs) introduced in Gunta's 4.16-version. He also published a +schematic stemming from the Motorola customer center here in Munich +(bd32new) (See below). + +In 1997 I upgraded my driver to simultaneously support ICD and PD +interfaces. The selection is made by accessing different minor numbers. +This version has been handed out to several testers (including Chris +Johns), but has never been officially released. + +Chris Johns used Eric's driver and added Coldfire support. + +@c --------------------------------------- +@node Build System, Layout, Overview, Top +@chapter POD, Pins, Power + +@cindex hardware + +Various means exist to access a BDM port on a processor. This driver +provides support for various host operating system, and adapator boards. + +The driver support the IDC hardware. A circuit abd PAL equations are +provided in the package. + +The Coldfire support is via the P&E standard interface. You can find +information about these adaptor from the P&E web site. + + + +Coldfire + +The Coldfire has a 26pin header. The expanded connector is for the +realtime trace. These signals are the PST or processor status +signals. Four of these signals provide provide the status of the +processor in realtime. + +The 5206 and 5206e processor share the PST signals with the parallel +port on Coldfire. Anr application that uses the Coldfire's parallel +port, cannot relying on the PST for the realtime status of the +processor. The P&E module provides a processor halted signal to the PC's +parallel port based on the PST signals. The P&E Windows driver and DLL +use this signal. Using this software with the P&E interface and a 5206 +variant of Coldfire requires the parallel port to left for the PST +signals. The PST signals on the 5307 processor are not shared. They are +free to be used for debugging. + +This driver does not require the use of the PST signals. The parallel +port on the 5206 processor can be used as a parallel port. + +The 5206 and 5206e differ in Vcc voltage. The 5206 is a 5.0V processor +while the 5206e is a 3.3V processor. You need to check your POD can +handle your processors voltage. The 5206e can operate at 54MHz. The 5307 +operate at 70MHz. The processor clock is carried up the BDM cable to the +POD. You need to insure the PLD on the POD is fast enough and the cable +from the target to the POD is not too long. If the cable is too long or +the PLD marginal the processor clock could be dragged out of shape +causing various problems which can be hard to find. + +Various people have reported problems when using the driver with 5307 +processors. Building the driver with the Makefile define @code{USE_PST} +causes the problem to go away. The error is + +@c --------------------------------------- +@node Build System, Layout, Overview, Top +@chapter The Driver + +@cindex driver + +Various means exist to access a BDM port on a processor. This driver +provides support for various host operating system, and adapator boards. + +The code which accesses the pod is + +The driver supports different host operating systems. + +@c --------------------------------------- +@node Layout, Configurations, Build System, Top +@chapter A Library for Applications + +@cindex Library + +The library provides an interface to the driver for user +applications. GDB currently requires this library to build. Future +release may have the library moved into the GDB patch allowing the BDM +code reside in the GDB source tree. + +The library also contains the client code for talking to the BDM server. + + +@c --------------------------------------- +@node Layout, Configurations, Build System, Top +@chapter Testing + +@cindex Testing + +The driver should be tested with the `chk' program. It provides a +reasonable test of the software, driver and hardware path to the target. + +@c --------------------------------------- +@node Layout, Configurations, Build System, Top +@chapter GDB + +@cindex GDB + +This section covers building GDB and contains some info about using GDB +with BDM. + +@c --------------------------------------- +@node Layout, Configurations, Build System, Top +@chapter Server + +@cindex Server + +This section covers building and installing the GDB server. + +Currently only a Unix version exists. It should operate on any platform +the driver can be built for. + +The BDM server operates from inetd. You need to add the following line +to @file(/etc/services} : + +@smallexample + +bdm 6543/tcp # BDM server + +@end smallexample + +The port number @code{6543} was a random selection. If for any reason it +is a bad or taken number, please let me know. + +In the file @file{/etc/inetd.con} add the following line : + +@smallexample + +bdm stream tcp nowait cjohns /usr/local/sbin//bdmd bdmd + +@end smallexample + +I am running this server as me. If the BDM devices have global +read/write enabled, then it should be ok to use the user @code{nobody}, +or something similar as the user. + +The server has not been checked for security holes. If the + + +@c --------------------------------------- +@node Reporting Bugs +@chapter Reporting Bugs +@cindex bugs in @code{MRB} +@cindex reporting bugs in @code{MRB} + +Your bug reports play an essential role in making @code{MRB} reliable. + +Reporting a bug may help you by bringing a solution to your problem, or +it may not. But in any case the principal function of a bug report is +to help the entire community by making the next version of @code{MRB} +work better. Bug reports are your contribution to the maintenance of +@code{MRB}. + +In order for a bug report to serve its purpose, you must include the +information that enables us to fix the bug. + +@menu +* Bug Criteria:: Have you found a bug? +* Bug Reporting:: How to report bugs +@end menu + +@c --------------------------------------- +@node Bug Criteria +@section Have you found a bug? +@cindex bug criteria + +If you are not sure whether you have found a bug, here are some guidelines: + +@itemize @bullet +@item +If the you select a particular configuration and @code{MRB} does not +build. It should build if the configuration parameter selection make +sense. For example building the networking code without configuring a +network driver. + +@item +The standard targets which are contained in MRB do not run. + +@item +A new release of the GNU tools can break the current code. + +@item +Your suggestions for improvement of @code{MRB} are welcome. +@end itemize + +@c --------------------------------------- +@node Bug Reporting +@section How to report bugs +@cindex bug reports +@cindex @code{MRB} bugs, reporting + +The fundamental principle of reporting bugs usefully is this: +@strong{report all the facts}. If you are not sure whether to state a +fact or leave it out, state it! + +Often people omit facts because they think they know what causes the +problem and assume that some details do not matter. Play it safe and +give a specific, complete example. That is the easiest thing for you to +do, and the most helpful. + +Keep in mind that the purpose of a bug report is to enable us to fix the +bug if it is new to us. Therefore, always write your bug reports on the +assumption that the bug has not been reported previously. + +Sometimes people give a few sketchy facts and ask, ``Does this ring a +bell?'' Those bug reports are useless, and we urge everyone to +@emph{refuse to respond to them} except to chide the sender to report +bugs properly. + +To enable us to fix the bug, you should include all these things: + +@itemize @bullet +@item +The version of @code{MRB}. + +Without this, we will not know whether there is any point in looking for +the bug in the current version of @code{MRB}. + +@item +Any patches you may have applied to the @code{MRB} source. + +@item +The type of host machine you are using, and the operating system name +and version number. + +@item +What compiler (and its version) was used to compile @code{MRB} +--e.g. ``@code{gcc-2.7}''. + +@item +The target you are building. If this is a new target you are developing, +you may need to provide some details of the changes you have made. + +@item +A description of what behavior you observe that you believe is +incorrect. + +@item +If you wish to suggest changes to the @code{MRB} source, send us context +diffs, as generated by @code{diff} with the @samp{-u}, @samp{-c}, or +@samp{-p} option. Always send diffs from the old file to the new file. +If you even discuss something in the @code{MRB} source, refer to it by +context, not by line number. + +The line numbers in our development sources will not match those in your +sources. Your line numbers would convey no useful information to us. +@end itemize + +Here are some things that are not necessary: + +@itemize @bullet +@item +A patch for the bug. + +A patch for the bug does help us if it is a good one. But do not omit +the necessary information, such as the test case, on the assumption that +a patch is all we need. We might see problems with your patch and decide +to fix the problem another way, or we might not understand it at all. + +And if we cannot understand what bug you are trying to fix, or why your +patch should be an improvement, we will not install it. A test case will +help us to understand. +@end itemize + +@c --------------------------------------- +@node Index +@unnumbered Index + +@printindex cp + +@contents +@bye + diff --git a/gdb/patches/gdb-4.18-bdm-m68k.patch b/gdb/patches/gdb-4.18-bdm-m68k.patch new file mode 100644 index 0000000..cc79b18 --- /dev/null +++ b/gdb/patches/gdb-4.18-bdm-m68k.patch @@ -0,0 +1,1544 @@ +diff -urN gdb-4.18/gdb/Makefile.in gdb-4.18-new/gdb/Makefile.in +--- gdb-4.18/gdb/Makefile.in Wed Apr 7 15:00:43 1999 ++++ gdb-4.18-new/gdb/Makefile.in Thu Aug 19 14:18:02 1999 +@@ -949,5 +949,5 @@ + vax-tdep.c \ +- vx-share/xdr_ld.c vx-share/xdr_ptrace.c vx-share/xdr_rdb.c \ ++ vx-share/xdr_ld.c vx-share/xdr_ptrace.c vx-share/xdr_rdb.c remote-m68k-bdm.c\ + win32-nat.c \ + udip2soc.o: $(srcdir)/29k-share/udi/udip2soc.c $(udiheaders) + $(CC) -c $(INTERNAL_CFLAGS) $(srcdir)/29k-share/udi/udip2soc.c +@@ -1392,6 +1392,9 @@ + + remote-mm.o: remote-mm.c $(bfd_h) $(wait_h) $(defs_h) $(inferior_h) \ + minimon.h target.h terminal.h gdb_string.h ++ ++remote-m68k-bdm.o: remote-m68k-bdm.c $(bfd_h) $(wait_h) $(defs_h) $(inferior_h) \ ++ $(gdbcore_h) target.h + + remote-nindy.o: remote-nindy.c $(floatformat_h) $(wait_h) $(command_h) \ + $(defs_h) $(gdbcore_h) $(inferior_h) \ +diff -urN gdb-4.18/gdb/config/m68k/bdm.mt gdb-4.18-new/gdb/config/m68k/bdm.mt +--- gdb-4.18/gdb/config/m68k/bdm.mt Wed Dec 31 18:00:00 1969 ++++ gdb-4.18-new/gdb/config/m68k/bdm.mt Wed Dec 8 04:25:12 1999 +@@ -0,0 +1,5 @@ ++# Target: m68k bdm interface for the CPU32 and Coldfire processors. ++# ++TM_CLIBS= -lBDM ++TDEPFILES= m68k-tdep.o remote-m68k-bdm.o ++TM_FILE= tm-bdm.h +diff -urN gdb-4.18/gdb/config/m68k/tm-bdm.h gdb-4.18-new/gdb/config/m68k/tm-bdm.h +--- gdb-4.18/gdb/config/m68k/tm-bdm.h Wed Dec 31 18:00:00 1969 ++++ gdb-4.18-new/gdb/config/m68k/tm-bdm.h Thu Aug 19 14:18:02 1999 +@@ -0,0 +1,87 @@ ++/* ++ * Target machine description for Coldfire BDM (Moto 5200) ++ * Copyright (C) 1995 W. Eric Norum ++ * Copyright (C) 1998 Chris Johns (ccj@acm.org) ++ * ++ * Based on: ++ * 1. `A Background Debug Mode Driver Package for Motorola's ++ * 16- and 32-Bit Microcontrollers', Scott Howard, Motorola ++ * Canada, 1993. ++ * 2. `Linux device driver for public domain BDM Interface', ++ * M. Schraut, Technische Universitaet Muenchen, Lehrstuhl ++ * fuer Prozessrechner, 1995. ++ * 3. BDM support for gdb by W. Eric Norum ++ * Saskatchewan Accelerator Laboratory ++ * University of Saskatchewan ++ * 107 North Road ++ * Saskatoon, Saskatchewan, CANADA ++ * S7N 5C6 ++ * ++ * 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. ++ */ ++ ++/* ++ * Coldfire does it for us if we use PCC to get the PC ++ */ ++#define DECR_PC_AFTER_BREAK 0 ++ ++/* ++ * We have to control this directly as the CPU32 and Coldfire have different ++ * breakpoint opcodes. ++ */ ++#define BREAKPOINT_FROM_PC m68k_bdm_breakpoint_from_pc ++ ++/* ++ * Include the generic stuff ++ */ ++#include "m68k/tm-m68k.h" ++ ++/* ++ * Override some of the generic definitions ++ */ ++ ++/* ++ * we need 40 registers for the CPU32 and Coldfire: ++ * 8 data registers ++ * 8 address registers ++ * 2 other registers (PC, PS) ++ * 22 special registers (actual set depends on architecture) ++ * 0 floating point registers ++ */ ++#undef NUM_REGS ++#undef REGISTER_BYTES ++#define NUM_REGS 40 ++#define REGISTER_BYTES (16*4 + 2*4 + 22*4) ++ ++#undef REGISTER_NAMES ++#define REGISTER_NAME(i) bdm_register_name(i) ++extern const char *bdm_register_name(int i); ++ ++#undef FP0_REGNUM ++#undef FPC_REGNUM ++#undef FPS_REGNUM ++#undef FPI_REGNUM ++#define FP0_REGNUM 40 /* Floating point register 0 */ ++#define FPC_REGNUM FP0_REGNUM + 8 /* 68881 control register */ ++#define FPS_REGNUM FPC_REGNUM + 1 /* 68881 status register */ ++#define FPI_REGNUM FPS_REGNUM + 1 /* 68881 iaddr register */ ++ ++/* ++ * The other definitions and macros don't need to be changed: ++ * a) The Coldfire has no floating point registers ++ * b) The REGISTER_BYTES_OK macro isn't used ++ */ +diff -urN gdb-4.18/gdb/configure.tgt gdb-4.18-new/gdb/configure.tgt +--- gdb-4.18/gdb/configure.tgt Wed Apr 7 15:00:17 1999 ++++ gdb-4.18-new/gdb/configure.tgt Thu Aug 19 14:18:02 1999 +@@ -149,6 +149,7 @@ + m68*-*bug-*) gdb_target=monitor ;; + m68*-monitor-*) gdb_target=monitor ;; + m68*-est-*) gdb_target=monitor ;; ++m68*-bdm-*) gdb_target=bdm ;; + m68*-*-aout*) gdb_target=monitor ;; + m68*-*-coff*) gdb_target=monitor ;; + m68*-*-elf*) gdb_target=monitor ;; +diff -urN gdb-4.18/gdb/doc/all-cfg.texi gdb-4.18-new/gdb/doc/all-cfg.texi +--- gdb-4.18/gdb/doc/all-cfg.texi Fri Feb 5 19:26:05 1999 ++++ gdb-4.18-new/gdb/doc/all-cfg.texi Thu Aug 19 14:18:02 1999 +@@ -39,6 +39,9 @@ + @c Intel 960 target: + @set I960 + @c ++@c Motorola BDM target: ++@set BDM ++@c + @c Tandem ST2000 (phone switch) target: + @set ST2000 + @c +diff -urN gdb-4.18/gdb/doc/gdb.texinfo gdb-4.18-new/gdb/doc/gdb.texinfo +--- gdb-4.18/gdb/doc/gdb.texinfo Thu Feb 11 20:02:45 1999 ++++ gdb-4.18-new/gdb/doc/gdb.texinfo Thu Aug 19 14:18:02 1999 +@@ -413,6 +413,10 @@ + * Simulator:: Simulated CPU target + @end ifset + ++@ifset BDM ++* Motorola BDM Target:: @value{GDBN} and Motorola 68k/Coldfire BDM targets ++@end ifset ++ + Controlling @value{GDBN} + + * Prompt:: Prompt +@@ -8527,6 +8531,12 @@ + @item target bug @var{dev} + BUG monitor, running on a MVME187 (m88k) board. + ++@ifset BDM ++@kindex target bdm ++Background Debug Mode interface to Motorola 68k/Coldfire machine. ++@xref{Motorola BDM Target, ,@value{GDBN} and Motorola 68k/Coldfire BDM}. ++@end ifset ++ + @kindex target cpu32bug + @item target cpu32bug @var{dev} + CPU32BUG monitor, running on a CPU32 (M68K) board. +@@ -8819,6 +8829,11 @@ + @ifset SIMS + * Simulator:: Simulated CPU target + @end ifset ++@ifset BDM ++* Motorola BDM Target:: @value{GDBN} and Motorola 68k/Coldfire Background Debug ++Mode ++@end ifset ++ + @end menu + + @include remote.texi +diff -urN gdb-4.18/gdb/doc/remote.texi gdb-4.18-new/gdb/doc/remote.texi +--- gdb-4.18/gdb/doc/remote.texi Fri Feb 5 19:28:34 1999 ++++ gdb-4.18-new/gdb/doc/remote.texi Thu Aug 19 14:18:02 1999 +@@ -1705,4 +1705,101 @@ + simulated clock ticks. + @end ifset + ++ ++@ifset BDM ++@node Motorola BDM Target ++@subsection @value{GDBN} and Motorola BDM ++ ++@cindex BDM ++@cindex CPU32 ++@cindex Coldfire ++Background Debug Mode (@dfn{BDM}) provides a full set of debug options ++including the ability to: ++@itemize @bullet ++@item Insert breakpoints ++@item Single-step ++@item Display register contents ++@item Display memory contents ++@item Modify register contents ++@item Modify memory contents ++@end itemize ++ ++A small interface circuit connects the BDM interface port on the ++target machine to a parallel printer port on the debugging host. ++A target system can be configured and a program downloaded and ++executed with no bootstrap memory on the target machine and no other ++connection between the debugging host and the target machine. ++ ++The @code{target} command tells @value{GDBN} ++to debug a program running on a target machine ++@xref{Target Commands, ,Commands for managing targets}. ++For example, the following command tells @value{GDBN} to use a BDM ++interface connected to the @code{LPT0} parallel port: ++@example ++target bdm /dev/bdm0 ++@end example ++ ++Do not attempt to use the parallel port for any other purpose while ++@value{GDBN} is using it to control a BDM target. ++ ++Once the BDM target has been selected a few other commands become ++available: ++ ++@table @code ++@item bdm_reset ++@kindex bdm_reset ++Reset the target machine and enable BDM operation in the target. ++ ++@item bdm_restart ++@kindex bdm_restart ++Reset the target machine and disable BDM operation in the target. ++This command is useful only if the target machine has some kind of ++bootstrap memory installed. ++ ++@item bdm_status ++@kindex bdm_status ++Print the status of the target machine and the BDM interface. ++ ++@item bdm_setdelay @var{N} ++@kindex bdm_setdelay ++Some BDM interface circuits can not handle high-speed data transfer. ++This command lets you insert a delay between each BDM clock. ++The larger the value of @var{N}, the longer the delay. ++On most machines the default delay of @var{0} should work just fine. ++ ++@item bdm_setdebug @var{N} ++@kindex bdm_setdebug ++Setting the level (@var{N}) to a non-zero value turns on ++debugging messages in the BDM support library. ++ ++@item bdm_setdriverdebug @var{N} ++@kindex bdm_setdriverdebug ++Setting the level (@var{N}) to a non-zero value turns on ++debugging messages in the BDM device driver. ++ ++@end table ++ ++The registers which can be displayed and modified are: ++@itemize @bullet ++@item The data registers: @code{$d0}-@code{$d7} ++@item The address registers: @code{$a0}-@code{$a5}, @code{$fp}, @code{$sp} ++@item The program counter: @code{$pc} ++@item The status register: @code{$ps} ++@item The program counter at the beginning of the most recently executed ++instruction: @code{$pcc} ++@item The user stack pointer: @code{$usp} ++@item The supervisor stack pointer: @code{$ssp} ++@item The source function code register: @code{$sfc} ++@item The destinaton function code register: @code{$dfc} ++@item The vector base register: @code{$vbr} ++@item The fault address register: @code{$far} ++@item The BDM temporary register: @code{$atemp} ++@item The module base address register: @code{$mbar} ++@end itemize ++ ++Target processor interrupts are disabled during single-step (step, next, ++stepi, nexti) operations. ++ ++@end ifset ++ + @c need to add much more detail about sims! +diff -urN gdb-4.18/gdb/findvar.c gdb-4.18-new/gdb/findvar.c +--- gdb-4.18/gdb/findvar.c Fri Jan 29 03:46:03 1999 ++++ gdb-4.18-new/gdb/findvar.c Tue Dec 7 13:23:36 1999 +@@ -253,6 +253,7 @@ + LONGEST val; + { + if( TARGET_BYTE_ORDER == BIG_ENDIAN ++ && HOST_BYTE_ORDER != LITTLE_ENDIAN + && len != sizeof( LONGEST )) { + /* On big-endian machines (e.g., HPPA 2.0, narrow mode) + * just letting this fall through to the call below will +diff -urN gdb-4.18/gdb/remote-m68k-bdm.c gdb-4.18-new/gdb/remote-m68k-bdm.c +--- gdb-4.18/gdb/remote-m68k-bdm.c Wed Dec 31 18:00:00 1969 ++++ gdb-4.18-new/gdb/remote-m68k-bdm.c Thu Aug 19 14:18:02 1999 +@@ -0,0 +1,1241 @@ ++/* ++ * Motorola Background Debug Mode Target ++ * Copyright (C) 1995 W. Eric Norum ++ * Copyright (C) 1998 Chris Johns (ccj@acm.org) ++ * ++ * Based on: ++ * 1. `A Background Debug Mode Driver Package for Motorola's ++ * 16- and 32-Bit Microcontrollers', Scott Howard, Motorola ++ * Canada, 1993. ++ * 2. `Linux device driver for public domain BDM Interface', ++ * M. Schraut, Technische Universitaet Muenchen, Lehrstuhl ++ * fuer Prozessrechner, 1995. ++ * 3. BDM support for gdb by W. Eric Norum ++ * Saskatchewan Accelerator Laboratory ++ * University of Saskatchewan ++ * 107 North Road ++ * Saskatoon, Saskatchewan, CANADA ++ * S7N 5C6 ++ * 4. Coldfire support added by C Johns. ++ * ++ * 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. ++ * ++ * W. Eric Norum ++ * Saskatchewan Accelerator Laboratory ++ * University of Saskatchewan ++ * 107 North Road ++ * Saskatoon, Saskatchewan, CANADA ++ * S7N 5C6 ++ * ++ * eric@skatter.usask.ca ++ * ++ * Coldfire support by: ++ * Chris Johns ++ * Objective Design Systems ++ * 35 Cairo Street ++ * Cammeray, Sydney, 2062, Australia ++ * ++ * ccj@acm.org ++ */ ++ ++/* ++ * $Revision: 1.1 $ $Date: 2004/03/28 23:13:10 $ $Author: codewiz $ ++ */ ++ ++#include "defs.h" ++#include "gdbcore.h" ++#include "target.h" ++#include "wait.h" ++#include ++#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" ++ ++extern struct target_ops bdm_ops; /* Forward declaration */ ++ ++/* ++ * The name of the BDM driver special file ++ */ ++static char *dev_name; ++static int cpu_type; ++ ++/* ++ * The different register names for the processors. ++ */ ++static const char *cpu32_reg_names[NUM_REGS] = { ++ "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", ++ NULL, NULL, NULL, NULL, ++ "mbar", ++ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ++}; ++ ++static const char *cf_reg_names[NUM_REGS] = { ++ "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", ++ "a0", "a1", "a2", "a3", "a4", "a5", "fp", "sp", ++ "ps", "pc", ++ NULL, NULL, NULL, NULL, NULL, NULL, NULL, ++ "vbr", ++ "cacr", "acr0", "acr1", "rambar", ++ "mbar", ++ "csr", "aatr", "tdr", "pbr", "pbmr", "abhr", "ablr", "dbr", "dbmr", ++}; ++ ++static const char **bdm_reg_names = cpu32_reg_names; ++ ++const char *bdm_register_name(int i) ++{ ++ if ((i < 0) || (i >= NUM_REGS)) ++ return NULL; ++ return bdm_reg_names[i]; ++} ++ ++static int reg_to_dev_num[] = ++{ BDM_REG_SR, ++ BDM_REG_RPC, ++ BDM_REG_PCC, ++ BDM_REG_USP, ++ BDM_REG_SSP, ++ BDM_REG_SFC, ++ BDM_REG_DFC, ++ BDM_REG_ATEMP, ++ BDM_REG_FAR, ++ BDM_REG_VBR, ++ BDM_REG_CACR, ++ BDM_REG_ACR0, ++ BDM_REG_ACR1, ++ BDM_REG_RAMBAR, ++ BDM_REG_MBAR, ++ BDM_REG_CSR, ++ BDM_REG_AATR, ++ BDM_REG_TDR, ++ BDM_REG_PBR, ++ BDM_REG_PBMR, ++ BDM_REG_ABHR, ++ BDM_REG_ABLR, ++ BDM_REG_DBR, ++ BDM_REG_DBMR ++ }; ++ ++/* ++ * The name of the most recently loaded program ++ */ ++static char *bdm_prog_loaded; ++ ++/* ++ * default delay for interface ++ */ ++#define BDM_DEFAULT_DELAY 0 ++static int bdm_delay = -1; ++ ++/* ++ * does gdb wait or not, only valid for a Coldfire processor ++ */ ++static int bdm_gdb_no_wait = 0; ++ ++/* ++ * Hold BDM ATEMP register (CPU32 only). ++ */ ++static unsigned long atemp; ++static int haveAtemp; ++ ++/* ++ * Forward declarations ++ */ ++static void bdm_load (char *, int); ++ ++/* ++ * give target time to come up after reset ++ * time in usec ++ */ ++#define TIME_TO_COME_UP 60000 ++ ++/* ++ * Downloader routines ++ */ ++static int downLoaderReturn; ++static int downLoaderFirst; ++static unsigned long downLoadBaseAddress, downLoadStartAddress; ++static int bdmDebugLevel; ++static const char *downloadErrorString; ++ ++static void ++downloadSection (bfd *abfd, sec_ptr sec, PTR ignore) ++{ ++ unsigned long dfc; ++ unsigned long address; ++ unsigned long nleft; ++ int count; ++ file_ptr offset; ++ char cbuf[1024]; ++ ++ /* ++ * See if the section needs loading ++ */ ++ if (bdmDebugLevel) ++ printf_filtered ("Section flags:%#x", bfd_get_section_flags (abfd, sec)); ++ if ((downLoaderReturn < 0) || ++ ((bfd_get_section_flags (abfd, sec) & SEC_HAS_CONTENTS) == 0) || ++ ((bfd_get_section_flags (abfd, sec) & SEC_LOAD) == 0)) ++ return; ++ address = bfd_section_lma (abfd, sec); ++ if (bdmDebugLevel) ++ printf_filtered ("Section address:%#x", address); ++ if (downLoaderFirst && (bfd_get_section_flags (abfd, sec) & SEC_CODE)) { ++ downLoadStartAddress = bfd_get_start_address (abfd); ++ downLoadBaseAddress = address; ++ downLoaderFirst = 0; ++ if (bdmDebugLevel) ++ printf_filtered ("Start address:%#x Base address:%#x", downLoadStartAddress, downLoadBaseAddress); ++ } ++ ++ /* ++ * Set the appropriate destination address space ++ */ ++ if (bfd_get_section_flags (abfd, sec) & SEC_CODE) ++ dfc = 0x6; /* Supervisor program space */ ++ else ++ dfc = 0x5; /* Supervisor data space */ ++ if (bdmWriteSystemRegister (BDM_REG_DFC, dfc) < 0) { ++ downLoaderReturn = -1; ++ return; ++ } ++ ++ /* ++ * Load the section in `sizeof cbuf` chunks ++ */ ++ nleft = bfd_get_section_size_before_reloc (sec); ++ if (nleft == 0) ++ return; ++ offset = 0; ++ while (nleft) { ++ if (nleft > sizeof cbuf) ++ count = sizeof cbuf; ++ else ++ count = nleft; ++ if (!bfd_get_section_contents (abfd, sec, cbuf, offset, count)) { ++ downloadErrorString = "Error reading section contents"; ++ downLoaderReturn = -1; ++ return; ++ } ++ if (bdmWriteMemory (address, cbuf, count) < 0) { ++ downLoaderReturn = -1; ++ return; ++ } ++ address += count; ++ offset += count; ++ nleft -= count; ++ } ++} ++ ++/* ++ * Load an executable image into the target ++ */ ++static int ++loadExecutable (const char *name) ++{ ++ bfd *abfd; ++ unsigned long dfc; ++ unsigned long l; ++ ++ /* ++ * Make sure target is there ++ */ ++ if (!bdmCheck ()) ++ return -1; ++ ++ /* ++ * Open and verify the file ++ */ ++ bfd_init (); ++ abfd = bfd_openr (name, "default"); ++ if (abfd == NULL) { ++ downloadErrorString = bfd_errmsg (bfd_get_error()); ++ return -1; ++ } ++ if (!bfd_check_format (abfd, bfd_object)) { ++ downloadErrorString = "Not an object file"; ++ return -1; ++ } ++ ++ /* ++ * Save the destination function code register ++ */ ++ if (bdmReadSystemRegister (BDM_REG_DFC, &dfc) < 0) ++ return -1; ++ ++ /* ++ * Load each section of the executable file ++ */ ++ downLoaderFirst = 1; ++ downLoaderReturn = 0; ++ bfd_map_over_sections (abfd, downloadSection, NULL); ++ if (downLoaderReturn < 0) ++ return -1; ++ ++ /* ++ * Set up stack pointer and program counter ++ */ ++ if ((bdmReadLongWord (downLoadBaseAddress, &l) < 0) ++ || (bdmWriteSystemRegister (BDM_REG_SSP, l) < 0) ++ || (bdmReadLongWord (downLoadBaseAddress+4, &l) < 0) ++ || (bdmWriteSystemRegister (BDM_REG_RPC, l) < 0) ++ || (bdmWriteSystemRegister (BDM_REG_VBR, downLoadBaseAddress) < 0) ++ || (bdmWriteSystemRegister (BDM_REG_DFC, dfc) < 0)) ++ return -1; ++ return 0; ++} ++ ++/* ++ * The breakpoint codes for the different processors ++ */ ++static char cpu32_breakpoint[] = {0x4a, 0xfa}; ++static char cf_breakpoint[] = {0x4a, 0xc8}; ++static char *breakpointCode; ++static int breakpointSize; ++ ++unsigned char *m68k_bdm_breakpoint_from_pc (pcptr, lenptr) ++ CORE_ADDR *pcptr; ++ int *lenptr; ++{ ++ *lenptr = breakpointSize; ++ return breakpointCode; ++} ++ ++/* ++ * Short pause ++ */ ++static void ++nap (int microseconds) ++{ ++ struct timeval tv; ++ ++ tv.tv_sec = microseconds / 1000000; ++ tv.tv_usec = microseconds % 1000000; ++ select (0, NULL, NULL, NULL, &tv); ++} ++ ++/* ++ * Display error message and jump back to main input loop ++ */ ++static void ++bdm_report_error (void) ++{ ++ error ("BDM error: %s", bdmErrorString ()); ++} ++ ++/* ++ * Initialize bdm interface port ++ */ ++static void ++bdm_init (int tty, char *arg) ++{ ++} ++ ++/* ++ * Return interface status ++ */ ++static int ++bdm_get_status (void) ++{ ++ int status; ++ ++ if ((status = bdmStatus ()) < 0) ++ bdm_report_error (); ++ return status; ++} ++ ++static void ++bdm_get_status_interactive (int pid, char *arg) ++{ ++ printf ("BDM status: 0x%x\n", bdm_get_status ()); ++} ++ ++/* ++ * release chip: reset and disable bdm mode ++ */ ++static void ++bdm_release_chip (void) ++{ ++ haveAtemp = 0; ++ registers_changed (); ++ if (bdmRelease () < 0) ++ bdm_report_error (); ++} ++ ++/* ++ * stop chip ++ */ ++static void ++bdm_stop_chip (void) ++{ ++ if (bdmStop () < 0) ++ bdm_report_error (); ++} ++ ++/* ++ * Allow chip to resume execution ++ */ ++static void ++bdm_go (void) ++{ ++ haveAtemp = 0; ++ if (bdmGo () < 0) ++ bdm_report_error (); ++} ++ ++/* ++ * Reset chip, enter BDM mode ++ */ ++static void ++bdm_reset (void) ++{ ++ registers_changed (); ++ if (bdmReset () < 0) ++ bdm_report_error (); ++ nap (TIME_TO_COME_UP); ++} ++ ++/* ++ * step cpu32 chip: execute a single instruction ++ * This is complicated by the presence of interrupts. ++ * Consider the following sequence of events: ++ * - User attempts to `continue' from a breakpoint. ++ * - Gdb calls bdm_step_chip to single-step the instruction that ++ * had been replaced by the BGND instruction. ++ * - The target processor executes the instruction and stops. ++ * - GDB replaces the instruction with a BGND instruction to ++ * force a breakpoint the next time the instruction is hit. ++ * - GDB calls bdm_go and the target resumes execution. ++ * This all seems fine, but now consider what happens when a interrupt ++ * is pending: ++ * - User attempts to `continue' from a breakpoint. ++ * - Gdb calls bdm_step_chip to single-step the instruction that ++ * had been replaced by the BGND instruction. ++ * - The target processor does not execute the replaced instruction, ++ * but rather executes the first instruction of the interrupt ++ * service routine, then stops. ++ * - GDB replaces the instruction with a BGND instruction to ++ * force a breakpoint the next time the instruction is hit. ++ * - GDB calls bdm_go and the target resumes execution. ++ * - The target finishes off the interrupt, and upon returing from ++ * the interrupt generates another breakpoint! ++ * The solution is simple -- disable interrupts when single stepping. ++ * The problem then becomes the handling of instructions which involve ++ * the program status word! ++ */ ++static void ++bdm_step_cpu32_chip (void) ++{ ++ unsigned long pc; ++ unsigned short instruction; ++ unsigned short immediate; ++ unsigned long d7; ++ unsigned long sr; ++ unsigned long nsr; ++ enum { ++ op_other, ++ op_ANDIsr, ++ op_EORIsr, ++ op_ORIsr, ++ op_TOsr, ++ op_FROMsr, ++ op_FROMsrTOd7 ++ } op; ++ ++ /* ++ * Get the existing status register ++ */ ++ if (bdmReadSystemRegister (BDM_REG_SR, &sr) < 0) ++ bdm_report_error (); ++ ++ /* ++ * Read the instuction about to be executed ++ */ ++ if ((bdmReadSystemRegister (BDM_REG_RPC, &pc) < 0) ++ || (bdmReadWord (pc, &instruction) < 0)) ++ bdm_report_error (); ++ ++ /* ++ * See what operation is to be performed ++ */ ++ if (instruction == 0x027C) ++ op = op_ANDIsr; ++ else if (instruction == 0x0A7C) ++ op = op_EORIsr; ++ else if (instruction == 0x007C) ++ op = op_ORIsr; ++ else if (instruction == 0x40C7) ++ op = op_FROMsrTOd7; ++ else if ((instruction & 0xFFC0) == 0x40C0) ++ op = op_FROMsr; ++ else if ((instruction & 0xFFC0) == 0x46C0) ++ op = op_TOsr; ++ else ++ op = op_other; ++ ++ /* ++ * Set things up for the single-step operation ++ */ ++ switch (op) { ++ case op_FROMsr: ++ /* ++ * It's storing the SR somewhere. ++ * Store the SR in D7 and change the instruction ++ * to save D7. This fails if the addressing mode ++ * is one of the esoteric modes that uses D7 as ++ * and index register, but we'll just have to hope ++ * that doesn't happen too often. ++ */ ++ if ((bdmReadRegister (7, &d7) < 0) ++ || (bdmWriteRegister (7, sr) < 0) ++ || (bdmWriteWord (pc, 0x3007 | ++ ((instruction & 0x38) << 3) | ++ ((instruction & 0x07) << 9)) < 0)) ++ bdm_report_error (); ++ break; ++ ++ case op_ANDIsr: ++ case op_EORIsr: ++ case op_ORIsr: ++ /* ++ * It's an immediate operation to the SR -- pick up the value ++ */ ++ if (bdmReadWord (pc+2, &immediate) < 0) ++ bdm_report_error (); ++ break; ++ ++ case op_TOsr: ++ case op_other: ++ break; ++ } ++ ++ /* ++ * Ensure the step is done with interrupts disabled ++ */ ++ if (bdmWriteSystemRegister (BDM_REG_SR, sr | 0x0700) < 0) ++ bdm_report_error (); ++ ++ /* ++ * Do the single-step ++ */ ++ if (bdmStep () < 0) ++ bdm_report_error (); ++ ++ /* ++ * Get the ATEMP register since the following operations may ++ * modify it. ++ */ ++ if (bdmReadSystemRegister (BDM_REG_ATEMP, &atemp) < 0) ++ bdm_report_error (); ++ haveAtemp = 1; ++ ++ /* ++ * Clean things up ++ */ ++ switch (op) { ++ case op_FROMsr: ++ if ((bdmWriteRegister (7, d7) < 0) ++ || (bdmWriteWord (pc, instruction) < 0) ++ || (bdmWriteSystemRegister (BDM_REG_SR, sr) < 0)) ++ bdm_report_error (); ++ break; ++ ++ case op_FROMsrTOd7: ++ if ((bdmReadRegister (7, &d7) < 0) ++ || (bdmWriteRegister (7, (d7 & ~0xFFFF) | (sr & 0xFFFF)) < 0) ++ || (bdmWriteSystemRegister (BDM_REG_SR, sr) < 0)) ++ bdm_report_error (); ++ break; ++ ++ case op_ANDIsr: ++ if (bdmWriteSystemRegister (BDM_REG_SR, sr & immediate) < 0) ++ bdm_report_error (); ++ break; ++ ++ case op_EORIsr: ++ if (bdmWriteSystemRegister (BDM_REG_SR, sr ^ immediate) < 0) ++ bdm_report_error (); ++ break; ++ ++ case op_ORIsr: ++ if (bdmWriteSystemRegister (BDM_REG_SR, sr | immediate) < 0) ++ bdm_report_error (); ++ break; ++ ++ case op_TOsr: ++ break; ++ ++ case op_other: ++ if ((bdmReadSystemRegister (BDM_REG_SR, &nsr) < 0) ++ || (bdmWriteSystemRegister (BDM_REG_SR, (nsr & ~0x0700) | (sr & 0x0700)) < 0)) ++ bdm_report_error (); ++ break; ++ } ++} ++ ++static void ++bdm_step_chip (void) ++{ ++ /* ++ * The cpu32 is harder to step than the Coldfire. ++ */ ++ if (cpu_type == BDM_CPU32) { ++ bdm_step_cpu32_chip(); ++ return; ++ } ++ ++ /* ++ * Do the single-step ++ */ ++ if (bdmStep () < 0) ++ bdm_report_error (); ++} ++ ++/* ++ * true if runnable ++ */ ++static int ++bdm_can_run (void) ++{ ++ return 1; ++} ++ ++static void ++bdm_setdelay(int delay) ++{ ++ if (bdmSetDelay (delay) < 0) ++ bdm_report_error (); ++} ++ ++static void ++bdm_setdelay_interactive (char *arg, int from_tty) ++{ ++ char *dummy; ++ ++ if (!arg) { ++ if (bdm_delay >= 0) ++ printf_filtered("bdm_delay is %d", bdm_delay); ++ else ++ printf_filtered("using default delay %d", BDM_DEFAULT_DELAY); ++ } ++ else { ++ bdm_delay = strtoul(arg, &dummy, 0); ++ bdm_setdelay (bdm_delay); ++ } ++} ++ ++static void ++bdm_setdebug_interactive (char *arg, int from_tty) ++{ ++ char *dummy; ++ ++ if (arg) { ++ bdmDebugLevel = strtoul(arg, &dummy, 0); ++ bdmSetDebugFlag (bdmDebugLevel); ++ } ++ else ++ error ("Argument missing"); ++} ++ ++static void ++bdm_setdriverdebug_interactive (char *arg, int from_tty) ++{ ++ char *dummy; ++ ++ if (arg) ++ bdmSetDriverDebugFlag (strtoul(arg, &dummy, 0)); ++ else ++ error ("Argument missing"); ++} ++ ++static void ++bdm_set_no_wait (char *arg, int from_tty) ++{ ++ bdm_gdb_no_wait = 1; ++} ++ ++static void ++bdm_set_wait (char *arg, int from_tty) ++{ ++ if (cpu_type == BDM_CPU32) { ++ error ("No wait mode is not supported on a CPU32"); ++ return; ++ } ++ if (bdm_get_status ()) ++ bdm_gdb_no_wait = 0; ++ else ++ error ("The target is running, please stop first"); ++} ++ ++static void ++bdm_issue_stop (char *arg, int from_tty) ++{ ++ bdm_stop_chip (); ++} ++ ++/* ++ * Open a connection the target via bdm ++ * name is the devicename of bdm and the filename to be used ++ * used for communication. ++ */ ++static void ++bdm_open (char *name, int from_tty) ++{ ++ char *p; ++ int version; ++ ++ if (bdmIsOpen ()) ++ error ("Bdm is already open, must close it first"); ++ if (name == NULL) ++ error ("Use `target bdm ' 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 the bdm port device."); ++ dev_name = savestring (name, p - name); ++ ++ target_preopen (from_tty); ++ unpush_target (&bdm_ops); ++ ++ if (bdmOpen (dev_name) < 0) ++ bdm_report_error (); ++ if (bdmStatus () & (BDM_TARGETPOWER | BDM_TARGETNC)) { ++ bdmClose (); ++ error ("Target or cable problem"); ++ } ++ ++ /* ++ * Ask the driver for it's version. ++ * We are only interested in the major number when checking the ++ * driver version number. ++ */ ++ if (bdmGetDrvVersion (&version) < 0) ++ bdm_report_error (); ++ if ((version & 0xff00) != (BDM_DRV_VERSION & 0xff00)) { ++ printf_filtered ("Incorrect driver version, looking for %i.%i and found %i.%i\n", ++ BDM_DRV_VERSION >> 8, BDM_DRV_VERSION & 0xff, ++ version >> 8, version & 0xff); ++ bdmClose (); ++ error ("Can't run with wrong BDM driver"); ++ } ++ ++ /* ++ * Get the processor type. ++ */ ++ if (bdmGetProcessor (&cpu_type) < 0) ++ bdm_report_error (); ++ switch (cpu_type) { ++ case BDM_CPU32: ++ bdm_reg_names = cpu32_reg_names; ++ breakpointCode = cpu32_breakpoint; ++ breakpointSize = sizeof cpu32_breakpoint; ++ break; ++ ++ case BDM_COLDFIRE: ++ bdm_reg_names = cf_reg_names; ++ breakpointCode = cf_breakpoint; ++ breakpointSize = sizeof cf_breakpoint; ++ break; ++ ++ default: ++ bdmClose (); ++ error ("Unknown processor type returned from the driver."); ++ } ++ ++ push_target (&bdm_ops); ++ ++ if (bdm_delay >= 0) ++ bdm_setdelay (bdm_delay); ++ else ++ bdm_setdelay (BDM_DEFAULT_DELAY); ++ if (from_tty) ++ printf_filtered ("Remote %s connected to %s\n", target_shortname, dev_name); ++} ++ ++/* ++ * Terminate current application and return to system prompt. ++ * On a target, just let the program keep on running ++ */ ++static void ++bdm_kill (void) ++{ ++ if (bdm_get_status () & BDM_TARGETSTOPPED) ++ bdm_go (); ++} ++ ++static void ++bdm_close (quitting) ++int quitting; ++{ ++ if (quitting) ++ bdm_kill (); ++ bdmClose (); ++} ++ ++/* ++ * _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) ++{ ++ pop_target (); /* calls bdm_close to do the real work */ ++} ++ ++/* ++ * _resume -- Tell the remote machine to resume. ++ */ ++static void ++bdm_resume (int pid, int step, enum target_signal sig) ++{ ++ if (step) ++ bdm_step_chip (); ++ else ++ bdm_go (); ++} ++ ++/* ++ * We have fallen into an exception supported by the runtime system. ++ * by executing a `breakpoint' instruction. ++ */ ++static void ++analyze_exception (struct target_waitstatus *status) ++{ ++ unsigned long pc, sp; ++ unsigned short vec; ++ char opcode[20]; /* `big enough' */ ++ ++ if (cpu_type == BDM_CPU32) { ++ if (bdmReadSystemRegister (BDM_REG_PCC, &pc) < 0) ++ bdm_report_error (); ++ } ++ else { ++ if (bdmReadSystemRegister (BDM_REG_RPC, &pc) < 0) ++ bdm_report_error (); ++ if (pc) ++ pc -= 2; ++ } ++ status->kind = TARGET_WAITKIND_STOPPED; ++ ++ /* ++ * See if it was a `breakpoint' instruction ++ */ ++ if (bdmReadMemory (pc, opcode, breakpointSize) < 0) ++ bdm_report_error (); ++ if (memcmp (breakpointCode, opcode, breakpointSize) == 0) { ++ if (bdmWriteSystemRegister (BDM_REG_RPC, pc) < 0) ++ bdm_report_error (); ++ status->value.sig = TARGET_SIGNAL_TRAP; ++ return; ++ } ++ /* ++ * FIXME: Why an illegal instruction signal ? ++ */ ++ status->value.sig = TARGET_SIGNAL_ILL; ++} ++ ++static int sigintFlag; ++static void ++bdm_signal_handler (int s) ++{ ++ sigintFlag++; ++} ++ ++/* ++ * Wait until the remote machine stops, then return, ++ * storing status in status just as `wait' would. ++ */ ++static int ++bdm_wait (int pid, struct target_waitstatus *status) ++{ ++ unsigned long csr; ++ int bdm_stat; ++ void (*ofunc) (); ++ ++ if (bdm_gdb_no_wait) { ++ status->kind = TARGET_WAITKIND_STOPPED; ++ status->value.sig = TARGET_SIGNAL_GRANT; ++ return 0; ++ } ++ ++ status->kind = TARGET_WAITKIND_EXITED; ++ status->value.integer = 0; ++ ++ /* ++ * Catch SIGINT signals ++ */ ++ sigintFlag = 0; ++ ofunc = signal (SIGINT, bdm_signal_handler); ++ ++ /* ++ * Wait here till the target requires service ++ */ ++ while ((bdm_stat = bdm_get_status ()) == 0) { ++ nap (500000); ++ if (sigintFlag) ++ bdm_stop_chip (); ++ } ++ ++ signal (SIGINT, ofunc); ++ ++ /* ++ * Determine why the target stopped ++ */ ++ 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: ++ case BDM_TARGETHALT: ++ case BDM_TARGETSTOPPED | BDM_TARGETHALT: ++ if (sigintFlag) { ++ status->kind = TARGET_WAITKIND_STOPPED; ++ status->value.sig = TARGET_SIGNAL_TSTP; ++ } ++ else { ++ if (cpu_type == BDM_CPU32) { ++ if (!haveAtemp ++ && (bdmReadSystemRegister (BDM_REG_ATEMP, &atemp) < 0)) ++ bdm_report_error (); ++ switch (atemp & 0xffff) { ++ case 0xffff: /* double bus fault */ ++ status->kind = TARGET_WAITKIND_STOPPED; ++ status->value.sig = TARGET_SIGNAL_BUS; ++ break; ++ case 0x0: /* HW bkpt */ ++ status->kind = TARGET_WAITKIND_STOPPED; ++ status->value.sig = TARGET_SIGNAL_TRAP; ++ break; ++ case 0x1: /* background mode */ ++ analyze_exception (status); ++ break; ++ default: ++ printf_filtered ("bdm_wait: Unknown atemp:%#lx\n", atemp); ++ status->kind = TARGET_WAITKIND_STOPPED; ++ status->value.sig = TARGET_SIGNAL_GRANT; ++ } ++ } ++ else { ++ if (bdmReadSystemRegister (BDM_REG_CSR, &csr) < 0) ++ bdm_report_error (); ++ switch (csr & 0x0f000000) { ++ case 0x08000000: /* double bus fault */ ++ status->kind = TARGET_WAITKIND_STOPPED; ++ status->value.sig = TARGET_SIGNAL_BUS; ++ break; ++ case 0x04000000: /* HW bkpt */ ++ case 0x03000000: /* we have both, treat it as a brk signal */ ++ case 0x01000000: /* bkpt signal asserted */ ++ status->kind = TARGET_WAITKIND_STOPPED; ++ status->value.sig = TARGET_SIGNAL_TRAP; ++ break; ++ case 0x02000000: /* background mode */ ++ analyze_exception (status); ++ break; ++ default: ++ printf_filtered ("bdm_wait: Unknown csr:%#lx", csr); ++ status->kind = TARGET_WAITKIND_STOPPED; ++ status->value.sig = TARGET_SIGNAL_GRANT; ++ } ++ } ++ } ++ break; ++ default: ++ printf_filtered ("bdm_wait: Unknown BDM status: %#x", bdm_stat); ++ break; ++ } ++ haveAtemp = 0; ++ return 0; ++} ++ ++/* 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; ++ unsigned long entry_pt; ++ ++ clear_proceed_status (); ++ init_wait_for_inferior (); ++ if (*args) { ++ prg_file = args; ++ } ++ else { ++ prg_file = execfile; ++ } ++ if (!(prg_file) && !(bdm_prog_loaded)) ++ error ("No program specified to run\n"); ++ if (bdm_prog_loaded) ++ printf_filtered ("Note: `%s' has already been loaded.\n", bdm_prog_loaded); ++ if (query ("Do you want to download `%s'?", prg_file)) ++ bdm_load (prg_file, 0); ++ if (bdmReadSystemRegister (BDM_REG_RPC, &entry_pt) < 0) ++ bdm_report_error (); ++ proceed (entry_pt, TARGET_SIGNAL_DEFAULT, 0); ++} ++ ++/* ++ * Fetch register REGNO, or all user registers if REGNO is -1. ++ */ ++static void ++bdm_fetch_register (int regno) ++{ ++ unsigned long l; ++ char cbuf[4]; ++ int ret; ++ ++ if (regno < 0) { ++ for (regno = 0 ; regno < NUM_REGS ; regno++) ++ bdm_fetch_register (regno); ++ } ++ else { ++ /* ++ * When the target is running the ++ * cpu registers can not be accessed. ++ */ ++ if (bdm_gdb_no_wait && (bdm_get_status () == 0)) { ++ l = 0; ++ ret = 0; ++ } ++ else { ++ if (regno < 16) { ++ ret = bdmReadRegister (regno, &l); ++ } ++ else { ++ if ((regno - 16) < (sizeof (reg_to_dev_num) / sizeof (int))) { ++ ret = bdmReadSystemRegister (reg_to_dev_num[regno - 16], &l); ++ } ++ else { ++ error ("Bad register number (%d)", regno); ++ return; ++ } ++ } ++ } ++ if (ret < 0) ++ bdm_report_error (); ++ cbuf[0] = l >> 24; ++ cbuf[1] = l >> 16; ++ cbuf[2] = l >> 8; ++ cbuf[3] = l; ++ supply_register (regno, cbuf); ++ } ++} ++ ++void ++bdm_prepare_to_store (void) ++{ ++ /* Do nothing, since we can store individual regs */ ++} ++ ++/* ++ * Store register REGNO, or all user registers if REGNO == -1. ++ */ ++void ++bdm_store_register (int regno) ++{ ++ unsigned long l; ++ int ret; ++ ++ if (bdm_gdb_no_wait && (bdm_get_status () == 0)) ++ return; ++ ++ if (regno == -1) { ++ for (regno = 0 ; regno < NUM_REGS ; regno++) ++ bdm_store_register (regno); ++ } ++ else { ++ l = read_register (regno); ++ if (regno < 16) { ++ ret = bdmWriteRegister (regno, l); ++ } ++ else { ++ if ((regno - 16) < (sizeof (reg_to_dev_num) / sizeof (int))) { ++ ret = bdmWriteSystemRegister (reg_to_dev_num[regno - 16], l); ++ } ++ else { ++ error ("Bad register number (%d)", regno); ++ return; ++ } ++ } ++ if (ret < 0) ++ bdm_report_error (); ++ } ++} ++ ++/* ++ * Transfer memory contents between target and host ++ */ ++static int ++bdm_xfer_inferior_memory (CORE_ADDR memaddr, char *myaddr, int len, int write, struct target_ops *t) ++{ ++ int ret; ++ ++ if (write) ++ ret = bdmWriteMemory (memaddr, myaddr, len); ++ else ++ ret = bdmReadMemory (memaddr, myaddr, len); ++ if (ret < 0) ++ bdm_report_error (); ++ return len; ++} ++ ++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"); ++ } ++} ++ ++/* ++ * Load a file. ++ */ ++static void ++bdm_load (char *args, int from_tty) ++{ ++ char *p; ++ ++ if (bdm_prog_loaded) { ++ free (bdm_prog_loaded); ++ bdm_prog_loaded = NULL; ++ } ++ if (!args) { ++ error ( ++ "The bdmload command must include the filename to load.\n" ++ "You may want to use 'run', which uses the file given\n" ++ "on the command line when gdb was invoked."); ++ } ++ if ((bdm_get_status () & BDM_TARGETSTOPPED) == 0) ++ bdm_stop_chip (); ++ ++ /* strip off additional (unwanted) arguments after file name */ ++ for (p = args; (*p != '\0') && (!isspace (*p)); p++) ; ++ *p = '\0'; ++ ++ if (loadExecutable (args) < 0) ++ error ("%s", downloadErrorString); ++ bdm_prog_loaded = savestring (args, strlen (args)); ++} ++ ++struct target_ops bdm_ops; ++ ++static void ++init_bdm_ops(void) ++{ ++ bdm_ops.to_shortname = "bdm"; ++ bdm_ops.to_longname = "CPU32 and Coldfire Background Debug Mode Interface for downloading and remote debugging"; ++ bdm_ops.to_doc = "Uses the Public Domain Background Debug Mode Interface connected to the\n" ++"BDM-port of the CPU32 or Coldfire based microcontroller and to a parallel port\n" ++"of the PC.\n" ++"Usage: target bdm \n" ++"where is the BDM character special file (e.g. /dev/bdm0)."; ++ bdm_ops.to_open = bdm_open; ++ bdm_ops.to_close = bdm_close; ++ bdm_ops.to_detach = bdm_detach; ++ bdm_ops.to_resume = bdm_resume; ++ bdm_ops.to_wait = bdm_wait; ++ 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 = memory_insert_breakpoint; ++ bdm_ops.to_remove_breakpoint = memory_remove_breakpoint; ++ bdm_ops.to_kill = bdm_kill; ++ bdm_ops.to_load = bdm_load; ++ bdm_ops.to_create_inferior = bdm_create_inferior; ++ bdm_ops.to_mourn_inferior = generic_mourn_inferior; ++ bdm_ops.to_can_run = bdm_can_run; ++ bdm_ops.to_stratum = process_stratum; ++ 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; ++ bdm_ops.to_magic = OPS_MAGIC; ++}; ++ ++void ++_initialize_remote_bdmcf (void) ++{ ++ init_bdm_ops (); ++ add_com ("bdm_reset", class_obscure, ++ (void (*)(char *, int))bdm_reset, ++ "Reset target and enter BDM mode."); ++ add_com ("bdm_release", class_obscure, ++ (void (*)(char *, int))bdm_release_chip, ++ "Reset target without BDM-mode."); ++ add_com ("bdm_status", class_obscure, ++ (void (*)(char *, int))bdm_get_status_interactive, ++ "Show status of bdm interface\n"); ++ add_com ("bdm_setdelay", class_obscure, ++ bdm_setdelay_interactive, ++ "set delay for download"); ++ add_com ("bdm_setdebug", class_obscure, ++ bdm_setdebug_interactive, ++ "enable/disable BDM diagnostic messages"); ++ add_com ("bdm_setdriverdebug", class_obscure, ++ bdm_setdriverdebug_interactive, ++ "enable/disable BDM driver diagnostic messages"); ++ add_com ("bdm_no_wait", class_obscure, ++ bdm_set_no_wait, ++ "Cause GDB to not wait for the target to stop when running."); ++ add_com ("bdm_wait", class_obscure, ++ bdm_set_wait, ++ "Cause GDB to wait for the target to stop when running."); ++ add_com ("bdm_stop", class_obscure, ++ bdm_issue_stop, ++ "Stop the target if running."); ++ add_target (&bdm_ops); ++} diff --git a/gdb/patches/gdb-5.0-bdm-m68k.patch b/gdb/patches/gdb-5.0-bdm-m68k.patch new file mode 100644 index 0000000..f82f29d --- /dev/null +++ b/gdb/patches/gdb-5.0-bdm-m68k.patch @@ -0,0 +1,1970 @@ +diff -urN gdb-5.0.orig/gdb/Makefile.in gdb-5.0/gdb/Makefile.in +--- gdb-5.0.orig/gdb/Makefile.in Sat May 27 16:55:48 2000 ++++ gdb-5.0/gdb/Makefile.in Tue Jan 23 16:44:03 2001 +@@ -1098,7 +1098,7 @@ + symm-tdep.c symm-nat.c \ + tahoe-tdep.c ultra3-nat.c ultra3-xdep.c umax-xdep.c \ + vax-tdep.c \ +- vx-share/xdr_ld.c vx-share/xdr_ptrace.c vx-share/xdr_rdb.c \ ++ vx-share/xdr_ld.c vx-share/xdr_ptrace.c vx-share/xdr_rdb.c remote-m68k-bdm.c \ + win32-nat.c \ + xcoffread.c xcoffsolib.c z8k-tdep.c + +@@ -1701,6 +1701,9 @@ + + remote-mm.o: remote-mm.c $(bfd_h) gdb_wait.h $(defs_h) $(inferior_h) \ + minimon.h target.h terminal.h gdb_string.h ++ ++remote-m68k-bdm.o: remote-m68k-bdm.c $(bfd_h) $(wait_h) $(defs_h) $(inferior_h) \ ++ $(gdbcore_h) target.h + + remote-nindy.o: remote-nindy.c $(floatformat_h) gdb_wait.h $(command_h) \ + $(defs_h) $(gdbcore_h) $(inferior_h) \ +diff -urN gdb-5.0.orig/gdb/config/m68k/bdm.mt gdb-5.0/gdb/config/m68k/bdm.mt +--- gdb-5.0.orig/gdb/config/m68k/bdm.mt Thu Jan 1 10:00:00 1970 ++++ gdb-5.0/gdb/config/m68k/bdm.mt Tue Jan 23 16:44:03 2001 +@@ -0,0 +1,5 @@ ++# Target: m68k bdm interface for the CPU32 and Coldfire processors. ++# ++TM_CLIBS= -lBDM ++TDEPFILES= m68k-tdep.o remote-m68k-bdm.o ++TM_FILE= tm-bdm.h +diff -urN gdb-5.0.orig/gdb/config/m68k/tm-bdm.h gdb-5.0/gdb/config/m68k/tm-bdm.h +--- gdb-5.0.orig/gdb/config/m68k/tm-bdm.h Thu Jan 1 10:00:00 1970 ++++ gdb-5.0/gdb/config/m68k/tm-bdm.h Mon Feb 12 22:52:14 2001 +@@ -0,0 +1,120 @@ ++/* ++ * Target machine description for Coldfire BDM (Moto 5200) ++ * Copyright (C) 1995 W. Eric Norum ++ * Copyright (C) 1998 Chris Johns (ccj@acm.org) ++ * ++ * Based on: ++ * 1. `A Background Debug Mode Driver Package for Motorola's ++ * 16- and 32-Bit Microcontrollers', Scott Howard, Motorola ++ * Canada, 1993. ++ * 2. `Linux device driver for public domain BDM Interface', ++ * M. Schraut, Technische Universitaet Muenchen, Lehrstuhl ++ * fuer Prozessrechner, 1995. ++ * 3. BDM support for gdb by W. Eric Norum ++ * Saskatchewan Accelerator Laboratory ++ * University of Saskatchewan ++ * 107 North Road ++ * Saskatoon, Saskatchewan, CANADA ++ * S7N 5C6 ++ * ++ * 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. ++ */ ++ ++/* ++ * Coldfire does it for us if we use PCC to get the PC ++ */ ++#define DECR_PC_AFTER_BREAK 0 ++ ++/* ++ * We have to control this directly as the CPU32 and Coldfire have different ++ * breakpoint opcodes. ++ */ ++#define BREAKPOINT_FROM_PC m68k_bdm_breakpoint_from_pc ++ ++/* ++ * Include the generic stuff ++ */ ++#include "m68k/tm-m68k.h" ++ ++/* ++ * Override some of the generic definitions ++ */ ++ ++/* ++ * For uCLinux we need to detect we have a subroutine call ++ * which is really a trap #0. This should be caught by the ++ * the IN_SIGTRAMP handler defined above, but incase it is ++ * not we should try and catch it here. ++ */ ++ ++extern CORE_ADDR m68k_bdm_saved_pc_after_call PARAMS ((struct frame_info *)); ++ ++#undef SAVED_PC_AFTER_CALL ++#define SAVED_PC_AFTER_CALL(frame) \ ++ m68k_bdm_saved_pc_after_call (frame) ++ ++/* ++ * we need 40 registers for the CPU32 and Coldfire: ++ * 8 data registers ++ * 8 address registers ++ * 2 other registers (PC, PS) ++ * 22 special registers (actual set depends on architecture) ++ * 0 floating point registers ++ */ ++#undef NUM_REGS ++#undef REGISTER_BYTES ++#define NUM_REGS 40 ++#define REGISTER_BYTES (16*4 + 2*4 + 22*4) ++ ++#undef REGISTER_NAMES ++#define REGISTER_NAME(i) bdm_register_name(i) ++extern const char *bdm_register_name(int i); ++ ++#undef FP0_REGNUM ++#undef FPC_REGNUM ++#undef FPS_REGNUM ++#undef FPI_REGNUM ++#define FP0_REGNUM 40 /* Floating point register 0 */ ++#define FPC_REGNUM FP0_REGNUM + 8 /* 68881 control register */ ++#define FPS_REGNUM FPC_REGNUM + 1 /* 68881 status register */ ++#define FPI_REGNUM FPS_REGNUM + 1 /* 68881 iaddr register */ ++ ++/* ++ * The other definitions and macros don't need to be changed: ++ * a) The Coldfire has no floating point registers ++ * b) The REGISTER_BYTES_OK macro isn't used ++ */ ++ ++#define TARGET_HAS_HARDWARE_WATCHPOINTS ++ ++/* We need to remove watchpoints when stepping, else we hit them again! */ ++ ++#define HAVE_NONSTEPPABLE_WATCHPOINT ++ ++#define STOPPED_BY_WATCHPOINT(w) cf_stopped_by_watchpoint () ++ ++/* Use these macros for watchpoint insertion/deletion. */ ++/* type can be 0: write watch, 1: read watch, 2: access watch (read/write) */ ++ ++#define TARGET_CAN_USE_HARDWARE_WATCHPOINT(type, cnt, ot) \ ++ cf_can_use_watchpoint (type, cnt, ot) ++ ++#define target_insert_watchpoint(addr, len, type) cf_insert_watchpoint (addr, len, type) ++#define target_remove_watchpoint(addr, len, type) cf_remove_watchpoint (addr, len, type) ++#define target_insert_hw_breakpoint(addr, shadow) cf_insert_hw_breakpoint (addr, shadow) ++#define target_remove_hw_breakpoint(addr, shadow) cf_remove_hw_breakpoint (addr, shadow) ++#define target_stopped_data_address() cf_stopped_data_address () +diff -urN gdb-5.0.orig/gdb/configure.tgt gdb-5.0/gdb/configure.tgt +--- gdb-5.0.orig/gdb/configure.tgt Sat May 27 16:55:49 2000 ++++ gdb-5.0/gdb/configure.tgt Tue Jan 23 16:44:03 2001 +@@ -150,6 +150,7 @@ + m68*-*bug-*) gdb_target=monitor ;; + m68*-monitor-*) gdb_target=monitor ;; + m68*-est-*) gdb_target=monitor ;; ++m68*-bdm-*) gdb_target=bdm ;; + m68*-*-aout*) gdb_target=monitor ;; + m68*-*-coff*) gdb_target=monitor ;; + m68*-*-elf*) gdb_target=monitor ;; +diff -urN gdb-5.0.orig/gdb/doc/gdb.texinfo gdb-5.0/gdb/doc/gdb.texinfo +--- gdb-5.0.orig/gdb/doc/gdb.texinfo Sat May 27 16:55:50 2000 ++++ gdb-5.0/gdb/doc/gdb.texinfo Tue Jan 23 16:44:03 2001 +@@ -10106,6 +10106,7 @@ + * i960:: Intel i960 + * M32R/D:: Mitsubishi M32R/D + * M68K:: Motorola M68K ++* Motorola BDM:: Motorola M68K/Coldfire Background Debug Mode + * M88K:: Motorola M88K + * MIPS Embedded:: MIPS Embedded + * PA:: HP PA Embedded +@@ -10747,6 +10748,10 @@ + @item target abug @var{dev} + ABug ROM monitor for M68K. + ++@kindex target bdm ++Background Debug Mode interface to Motorola 68k/Coldfire machine. ++@xref{Motorola BDM Target, ,@value{GDBN} and Motorola 68k/Coldfire BDM}. ++ + @kindex target cpu32bug + @item target cpu32bug @var{dev} + CPU32BUG monitor, running on a CPU32 (M68K) board. +@@ -10785,6 +10790,101 @@ + ROMBUG ROM monitor for OS/9000. + + @end table ++ ++ ++@node Motorola BDM ++@subsection @value{GDBN} and Motorola BDM ++ ++@cindex BDM ++@cindex CPU32 ++@cindex Coldfire ++Background Debug Mode (@dfn{BDM}) provides a full set of debug options ++including the ability to: ++@itemize @bullet ++@item Insert breakpoints ++@item Single-step ++@item Display register contents ++@item Display memory contents ++@item Modify register contents ++@item Modify memory contents ++@end itemize ++ ++A small interface circuit connects the BDM interface port on the ++target machine to a parallel printer port on the debugging host. ++A target system can be configured and a program downloaded and ++executed with no bootstrap memory on the target machine and no other ++connection between the debugging host and the target machine. ++ ++The @code{target} command tells @value{GDBN} ++to debug a program running on a target machine ++@xref{Target Commands, ,Commands for managing targets}. ++For example, the following command tells @value{GDBN} to use a BDM ++interface connected to a ColdFire processor and the @code{LPT0} parallel port: ++@example ++target bdm /dev/bdmcf0 ++@end example ++ ++Do not attempt to use the parallel port for any other purpose while ++@value{GDBN} is using it to control a BDM target. ++ ++Once the BDM target has been selected a few other commands become ++available: ++ ++@table @code ++@item bdm_reset ++@kindex bdm_reset ++Reset the target machine and enable BDM operation in the target. ++ ++@item bdm_restart ++@kindex bdm_restart ++Reset the target machine and disable BDM operation in the target. ++This command is useful only if the target machine has some kind of ++bootstrap memory installed. ++ ++@item bdm_status ++@kindex bdm_status ++Print the status of the target machine and the BDM interface. ++ ++@item bdm_setdelay @var{N} ++@kindex bdm_setdelay ++Some BDM interface circuits can not handle high-speed data transfer. ++This command lets you insert a delay between each BDM clock. ++The larger the value of @var{N}, the longer the delay. ++On most machines the default delay of @var{0} should work just fine. ++ ++@item bdm_setdebug @var{N} ++@kindex bdm_setdebug ++Setting the level (@var{N}) to a non-zero value turns on ++debugging messages in the BDM support library. ++ ++@item bdm_setdriverdebug @var{N} ++@kindex bdm_setdriverdebug ++Setting the level (@var{N}) to a non-zero value turns on ++debugging messages in the BDM device driver. ++ ++@end table ++ ++The registers which can be displayed and modified are: ++@itemize @bullet ++@item The data registers: @code{$d0}-@code{$d7} ++@item The address registers: @code{$a0}-@code{$a5}, @code{$fp}, @code{$sp} ++@item The program counter: @code{$pc} ++@item The status register: @code{$ps} ++@item The program counter at the beginning of the most recently executed ++instruction: @code{$pcc} ++@item The user stack pointer: @code{$usp} ++@item The supervisor stack pointer: @code{$ssp} ++@item The source function code register: @code{$sfc} ++@item The destinaton function code register: @code{$dfc} ++@item The vector base register: @code{$vbr} ++@item The fault address register: @code{$far} ++@item The BDM temporary register: @code{$atemp} ++@item The module base address register: @code{$mbar} ++@end itemize ++ ++Target processor interrupts are disabled during single-step (step, next, ++stepi, nexti) operations. ++ + + @node M88K + @subsection M88K +diff -urN gdb-5.0.orig/gdb/remote-m68k-bdm.c gdb-5.0/gdb/remote-m68k-bdm.c +--- gdb-5.0.orig/gdb/remote-m68k-bdm.c Thu Jan 1 10:00:00 1970 ++++ gdb-5.0/gdb/remote-m68k-bdm.c Sat Sep 1 16:49:14 2001 +@@ -0,0 +1,1676 @@ ++/* ++ * Motorola Background Debug Mode Target ++ * Copyright (C) 1995 W. Eric Norum ++ * Copyright (C) 1998 Chris Johns (ccj@acm.org) ++ * Copyright (C) 2000 Bryan Feir (bryan@sgl.crestech.ca) ++ * ++ * Based on: ++ * 1. `A Background Debug Mode Driver Package for Motorola's ++ * 16- and 32-Bit Microcontrollers', Scott Howard, Motorola ++ * Canada, 1993. ++ * 2. `Linux device driver for public domain BDM Interface', ++ * M. Schraut, Technische Universitaet Muenchen, Lehrstuhl ++ * fuer Prozessrechner, 1995. ++ * 3. BDM support for gdb by W. Eric Norum ++ * Saskatchewan Accelerator Laboratory ++ * University of Saskatchewan ++ * 107 North Road ++ * Saskatoon, Saskatchewan, CANADA ++ * S7N 5C6 ++ * 4. Coldfire support added by C Johns. ++ * 5. Hardware breakpoint support added by B Feir. ++ * ++ * 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. ++ * ++ * W. Eric Norum ++ * Saskatchewan Accelerator Laboratory ++ * University of Saskatchewan ++ * 107 North Road ++ * Saskatoon, Saskatchewan, CANADA ++ * S7N 5C6 ++ * ++ * eric@skatter.usask.ca ++ * ++ * Coldfire support by: ++ * Chris Johns ++ * Objective Design Systems ++ * 35 Cairo Street ++ * Cammeray, Sydney, 2062, Australia ++ * ++ * ccj@acm.org ++ * ++ * Coldfire hardware breakpoint support by: ++ * Bryan Feir ++ * CRESTech (Centre for Research in Earth and Space Technology) ++ * 4850 Keele Street, 1st floor ++ * Toronto, Ontario, CANADA M6E 3E5 ++ * ++ * bryan@sgl.crestech.ca ++ */ ++ ++/* ++ * $Revision: 1.1 $ $Date: 2004/03/28 23:13:10 $ $Author: codewiz $ ++ */ ++ ++#include "defs.h" ++#include "gdbcore.h" ++#include "target.h" ++#include ++#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" ++ ++extern struct target_ops bdm_ops; /* Forward declaration */ ++ ++/* ++ * The name of the BDM driver special file ++ */ ++static char *dev_name; ++static int cpu_type; ++ ++/* ++ * The different register names for the processors. ++ */ ++static const char *cpu32plus_reg_names[NUM_REGS] = { ++ "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", ++ NULL, NULL, NULL, NULL, ++ "mbar", ++ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ++}; ++ ++static const char *cpu32_reg_names[NUM_REGS] = { ++ "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", ++ "a0", "a1", "a2", "a3", "a4", "a5", "fp", "sp", ++ "ps", "pc", ++ "pcc", "usp", "ssp", "sfc", "dfc", NULL, NULL, ++ "vbr", ++ NULL, NULL, NULL, NULL, ++ NULL, ++ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ++}; ++ ++static const char *cf_reg_names[NUM_REGS] = { ++ "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", ++ "a0", "a1", "a2", "a3", "a4", "a5", "fp", "sp", ++ "ps", "pc", ++ NULL, NULL, NULL, NULL, NULL, NULL, NULL, ++ "vbr", ++ "cacr", "acr0", "acr1", "rambar", ++ "mbar", ++ "csr", "aatr", "tdr", "pbr", "pbmr", "abhr", "ablr", "dbr", "dbmr", ++}; ++ ++static const char **bdm_reg_names = cpu32plus_reg_names; ++ ++const char *bdm_register_name(int i) ++{ ++ if ((i < 0) || (i >= NUM_REGS)) ++ return NULL; ++ return bdm_reg_names[i]; ++} ++ ++static int reg_to_dev_num[] = ++{ BDM_REG_SR, ++ BDM_REG_RPC, ++ BDM_REG_PCC, ++ BDM_REG_USP, ++ BDM_REG_SSP, ++ BDM_REG_SFC, ++ BDM_REG_DFC, ++ BDM_REG_ATEMP, ++ BDM_REG_FAR, ++ BDM_REG_VBR, ++ BDM_REG_CACR, ++ BDM_REG_ACR0, ++ BDM_REG_ACR1, ++ BDM_REG_RAMBAR, ++ BDM_REG_MBAR, ++ BDM_REG_CSR, ++ BDM_REG_AATR, ++ BDM_REG_TDR, ++ BDM_REG_PBR, ++ BDM_REG_PBMR, ++ BDM_REG_ABHR, ++ BDM_REG_ABLR, ++ BDM_REG_DBR, ++ BDM_REG_DBMR ++ }; ++ ++/* ++ * The name of the most recently loaded program ++ */ ++static char *bdm_prog_loaded; ++ ++/* ++ * default delay for interface ++ */ ++#define BDM_DEFAULT_DELAY 0 ++static int bdm_delay = -1; ++ ++/* ++ * does gdb wait or not, only valid for a Coldfire processor ++ */ ++static int bdm_gdb_no_wait = 0; ++ ++/* ++ * Hold BDM ATEMP register (CPU32 only). ++ */ ++static unsigned long atemp; ++static int haveAtemp; ++ ++static int hit_watchpoint; ++ ++/* ++ * CF BDM Debug hardware version number. ++ */ ++ ++static unsigned long cf_debug_ver; ++ ++/* ++ * Not sure if this is defined somewhere. Cannot see anywhere. ++ */ ++extern int (*ui_loop_hook) (int); ++ ++/* ++ * Forward declarations ++ */ ++static void bdm_load (char *, int); ++ ++/* ++ * give target time to come up after reset ++ * time in usec ++ */ ++#define TIME_TO_COME_UP 60000 ++ ++/* ++ * Downloader routines ++ */ ++static int downLoaderReturn; ++static int downLoaderFirst; ++static unsigned long downLoadBaseAddress, downLoadStartAddress; ++static int bdmDebugLevel; ++static const char *downloadErrorString; ++ ++static void ++downloadSection (bfd *abfd, sec_ptr sec, PTR ignore) ++{ ++ unsigned long dfc; ++ unsigned long address; ++ unsigned long nleft; ++ int count; ++ file_ptr offset; ++ char cbuf[1024]; ++ ++ /* ++ * See if the section needs loading ++ */ ++ if (bdmDebugLevel) ++ printf_filtered ("Section flags:%#x", bfd_get_section_flags (abfd, sec)); ++ if ((downLoaderReturn < 0) || ++ ((bfd_get_section_flags (abfd, sec) & SEC_HAS_CONTENTS) == 0) || ++ ((bfd_get_section_flags (abfd, sec) & SEC_LOAD) == 0)) ++ return; ++ address = bfd_section_lma (abfd, sec); ++ if (bdmDebugLevel) ++ printf_filtered ("Section address:%#x", address); ++ if (downLoaderFirst && (bfd_get_section_flags (abfd, sec) & SEC_CODE)) { ++ downLoadStartAddress = bfd_get_start_address (abfd); ++ downLoadBaseAddress = address; ++ downLoaderFirst = 0; ++ if (bdmDebugLevel) ++ printf_filtered ("Start address:%#x Base address:%#x", downLoadStartAddress, downLoadBaseAddress); ++ } ++ ++ /* ++ * Set the appropriate destination address space ++ */ ++ if (bfd_get_section_flags (abfd, sec) & SEC_CODE) ++ dfc = 0x6; /* Supervisor program space */ ++ else ++ dfc = 0x5; /* Supervisor data space */ ++ if (bdmWriteSystemRegister (BDM_REG_DFC, dfc) < 0) { ++ downLoaderReturn = -1; ++ return; ++ } ++ ++ /* ++ * Load the section in `sizeof cbuf` chunks ++ */ ++ nleft = bfd_get_section_size_before_reloc (sec); ++ if (nleft == 0) ++ return; ++ offset = 0; ++ while (nleft) { ++ if (nleft > sizeof cbuf) ++ count = sizeof cbuf; ++ else ++ count = nleft; ++ if (!bfd_get_section_contents (abfd, sec, cbuf, offset, count)) { ++ downloadErrorString = "Error reading section contents"; ++ downLoaderReturn = -1; ++ return; ++ } ++ if (bdmWriteMemory (address, cbuf, count) < 0) { ++ downLoaderReturn = -1; ++ return; ++ } ++ address += count; ++ offset += count; ++ nleft -= count; ++ } ++} ++ ++/* ++ * Load an executable image into the target ++ */ ++static int ++loadExecutable (const char *name) ++{ ++ bfd *abfd; ++ unsigned long dfc; ++ unsigned long l; ++ ++ /* ++ * Make sure target is there ++ */ ++ if (!bdmCheck ()) ++ return -1; ++ ++ /* ++ * Open and verify the file ++ */ ++ bfd_init (); ++ abfd = bfd_openr (name, "default"); ++ if (abfd == NULL) { ++ downloadErrorString = bfd_errmsg (bfd_get_error()); ++ return -1; ++ } ++ if (!bfd_check_format (abfd, bfd_object)) { ++ downloadErrorString = "Not an object file"; ++ return -1; ++ } ++ ++ /* ++ * Save the destination function code register ++ */ ++ if (bdmReadSystemRegister (BDM_REG_DFC, &dfc) < 0) ++ return -1; ++ ++ /* ++ * Load each section of the executable file ++ */ ++ downLoaderFirst = 1; ++ downLoaderReturn = 0; ++ bfd_map_over_sections (abfd, downloadSection, NULL); ++ if (downLoaderReturn < 0) ++ return -1; ++ ++ /* ++ * Set up stack pointer and program counter ++ */ ++ if ((bdmReadLongWord (downLoadBaseAddress, &l) < 0) ++ || (bdmWriteSystemRegister (BDM_REG_SSP, l) < 0) ++ || (bdmReadLongWord (downLoadBaseAddress+4, &l) < 0) ++ || (bdmWriteSystemRegister (BDM_REG_RPC, l) < 0) ++ || (bdmWriteSystemRegister (BDM_REG_VBR, downLoadBaseAddress) < 0) ++ || (bdmWriteSystemRegister (BDM_REG_DFC, dfc) < 0)) ++ return -1; ++ return 0; ++} ++ ++/* ++ * The breakpoint codes for the different processors ++ */ ++static char cpu32_breakpoint[] = {0x4a, 0xfa}; ++static char cf_breakpoint[] = {0x4a, 0xc8}; ++static char *breakpointCode; ++static int breakpointSize; ++ ++static int cf_init_watchpoints(); ++ ++/* Immediately after a function call, return the saved pc before the frame ++ is setup. For uCLinux which uses a TRAP #0 for a system call we need to ++ read the first long word of the stack to see if the stack frame format is ++ type 4 and the vector is 32 (0x4080), and the opcode at the PC is ++ "move.w #0x2700,sr". If it is then get the second long from the stack. */ ++ ++CORE_ADDR ++m68k_bdm_saved_pc_after_call (frame) ++ struct frame_info *frame; ++{ ++ unsigned int op; ++ unsigned int eframe; ++ int sp; ++ ++ sp = read_register (SP_REGNUM); ++ eframe = read_memory_integer (sp, 2); ++ op = read_memory_integer (frame->pc, 4); ++ ++ /* ++ * This test could break if some changes the syste call. ++ */ ++ ++ if (eframe == 0x4080 && op == 0x46fc2700) ++ return read_memory_integer (sp + 4, 4); ++ else ++ return read_memory_integer (sp, 4); ++} ++ ++unsigned char *m68k_bdm_breakpoint_from_pc (pcptr, lenptr) ++ CORE_ADDR *pcptr; ++ int *lenptr; ++{ ++ *lenptr = breakpointSize; ++ return breakpointCode; ++} ++ ++/* ++ * Short pause ++ */ ++static void ++nap (int microseconds) ++{ ++ struct timeval tv; ++ ++ tv.tv_sec = microseconds / 1000000; ++ tv.tv_usec = microseconds % 1000000; ++ select (0, NULL, NULL, NULL, &tv); ++} ++ ++/* ++ * Display error message and jump back to main input loop ++ */ ++static void ++bdm_report_error (void) ++{ ++ error ("BDM error: %s", bdmErrorString ()); ++} ++ ++/* ++ * Initialize bdm interface port ++ */ ++static void ++bdm_init (int tty, char *arg) ++{ ++} ++ ++/* ++ * Return interface status ++ */ ++static int ++bdm_get_status (void) ++{ ++ int status; ++ ++ if ((status = bdmStatus ()) < 0) ++ bdm_report_error (); ++ return status; ++} ++ ++static void ++bdm_get_status_interactive (int pid, char *arg) ++{ ++ printf ("BDM status: 0x%x\n", bdm_get_status ()); ++} ++ ++/* ++ * release chip: reset and disable bdm mode ++ */ ++static void ++bdm_release_chip (void) ++{ ++ haveAtemp = 0; ++ registers_changed (); ++ if (bdmRelease () < 0) ++ bdm_report_error (); ++} ++ ++/* ++ * stop chip ++ */ ++static void ++bdm_stop_chip (void) ++{ ++ if (bdmStop () < 0) ++ bdm_report_error (); ++} ++ ++/* ++ * Allow chip to resume execution ++ */ ++static void ++bdm_go (void) ++{ ++ haveAtemp = 0; ++ if (bdmGo () < 0) ++ bdm_report_error (); ++} ++ ++/* ++ * Reset chip, enter BDM mode ++ */ ++static void ++bdm_reset (void) ++{ ++ registers_changed (); ++ if (bdmReset () < 0) ++ bdm_report_error (); ++ nap (TIME_TO_COME_UP); ++} ++ ++/* ++ * step cpu32 chip: execute a single instruction ++ * This is complicated by the presence of interrupts. ++ * Consider the following sequence of events: ++ * - User attempts to `continue' from a breakpoint. ++ * - Gdb calls bdm_step_chip to single-step the instruction that ++ * had been replaced by the BGND instruction. ++ * - The target processor executes the instruction and stops. ++ * - GDB replaces the instruction with a BGND instruction to ++ * force a breakpoint the next time the instruction is hit. ++ * - GDB calls bdm_go and the target resumes execution. ++ * This all seems fine, but now consider what happens when a interrupt ++ * is pending: ++ * - User attempts to `continue' from a breakpoint. ++ * - Gdb calls bdm_step_chip to single-step the instruction that ++ * had been replaced by the BGND instruction. ++ * - The target processor does not execute the replaced instruction, ++ * but rather executes the first instruction of the interrupt ++ * service routine, then stops. ++ * - GDB replaces the instruction with a BGND instruction to ++ * force a breakpoint the next time the instruction is hit. ++ * - GDB calls bdm_go and the target resumes execution. ++ * - The target finishes off the interrupt, and upon returing from ++ * the interrupt generates another breakpoint! ++ * The solution is simple -- disable interrupts when single stepping. ++ * The problem then becomes the handling of instructions which involve ++ * the program status word! ++ */ ++static void ++bdm_step_cpu32_chip (void) ++{ ++ unsigned long pc; ++ unsigned short instruction; ++ unsigned short immediate; ++ unsigned long d7; ++ unsigned long sr; ++ unsigned long nsr; ++ enum { ++ op_other, ++ op_ANDIsr, ++ op_EORIsr, ++ op_ORIsr, ++ op_TOsr, ++ op_FROMsr, ++ op_FROMsrTOd7 ++ } op; ++ ++ /* ++ * Get the existing status register ++ */ ++ if (bdmReadSystemRegister (BDM_REG_SR, &sr) < 0) ++ bdm_report_error (); ++ ++ /* ++ * Read the instuction about to be executed ++ */ ++ if ((bdmReadSystemRegister (BDM_REG_RPC, &pc) < 0) ++ || (bdmReadWord (pc, &instruction) < 0)) ++ bdm_report_error (); ++ ++ /* ++ * See what operation is to be performed ++ */ ++ if (instruction == 0x027C) ++ op = op_ANDIsr; ++ else if (instruction == 0x0A7C) ++ op = op_EORIsr; ++ else if (instruction == 0x007C) ++ op = op_ORIsr; ++ else if (instruction == 0x40C7) ++ op = op_FROMsrTOd7; ++ else if ((instruction & 0xFFC0) == 0x40C0) ++ op = op_FROMsr; ++ else if ((instruction & 0xFFC0) == 0x46C0) ++ op = op_TOsr; ++ else ++ op = op_other; ++ ++ /* ++ * Set things up for the single-step operation ++ */ ++ switch (op) { ++ case op_FROMsr: ++ /* ++ * It's storing the SR somewhere. ++ * Store the SR in D7 and change the instruction ++ * to save D7. This fails if the addressing mode ++ * is one of the esoteric modes that uses D7 as ++ * and index register, but we'll just have to hope ++ * that doesn't happen too often. ++ */ ++ if ((bdmReadRegister (7, &d7) < 0) ++ || (bdmWriteRegister (7, sr) < 0) ++ || (bdmWriteWord (pc, 0x3007 | ++ ((instruction & 0x38) << 3) | ++ ((instruction & 0x07) << 9)) < 0)) ++ bdm_report_error (); ++ break; ++ ++ case op_ANDIsr: ++ case op_EORIsr: ++ case op_ORIsr: ++ /* ++ * It's an immediate operation to the SR -- pick up the value ++ */ ++ if (bdmReadWord (pc+2, &immediate) < 0) ++ bdm_report_error (); ++ break; ++ ++ case op_TOsr: ++ case op_other: ++ break; ++ } ++ ++ /* ++ * Ensure the step is done with interrupts disabled ++ */ ++ if (bdmWriteSystemRegister (BDM_REG_SR, sr | 0x0700) < 0) ++ bdm_report_error (); ++ ++ /* ++ * Do the single-step ++ */ ++ if (bdmStep () < 0) ++ bdm_report_error (); ++ ++ /* ++ * Get the ATEMP register since the following operations may ++ * modify it. ++ */ ++ if (bdmReadSystemRegister (BDM_REG_ATEMP, &atemp) < 0) ++ bdm_report_error (); ++ haveAtemp = 1; ++ ++ /* ++ * Clean things up ++ */ ++ switch (op) { ++ case op_FROMsr: ++ if ((bdmWriteRegister (7, d7) < 0) ++ || (bdmWriteWord (pc, instruction) < 0) ++ || (bdmWriteSystemRegister (BDM_REG_SR, sr) < 0)) ++ bdm_report_error (); ++ break; ++ ++ case op_FROMsrTOd7: ++ if ((bdmReadRegister (7, &d7) < 0) ++ || (bdmWriteRegister (7, (d7 & ~0xFFFF) | (sr & 0xFFFF)) < 0) ++ || (bdmWriteSystemRegister (BDM_REG_SR, sr) < 0)) ++ bdm_report_error (); ++ break; ++ ++ case op_ANDIsr: ++ if (bdmWriteSystemRegister (BDM_REG_SR, sr & immediate) < 0) ++ bdm_report_error (); ++ break; ++ ++ case op_EORIsr: ++ if (bdmWriteSystemRegister (BDM_REG_SR, sr ^ immediate) < 0) ++ bdm_report_error (); ++ break; ++ ++ case op_ORIsr: ++ if (bdmWriteSystemRegister (BDM_REG_SR, sr | immediate) < 0) ++ bdm_report_error (); ++ break; ++ ++ case op_TOsr: ++ break; ++ ++ case op_other: ++ if ((bdmReadSystemRegister (BDM_REG_SR, &nsr) < 0) ++ || (bdmWriteSystemRegister (BDM_REG_SR, (nsr & ~0x0700) | (sr & 0x0700)) < 0)) ++ bdm_report_error (); ++ break; ++ } ++} ++ ++static void ++bdm_step_chip (void) ++{ ++ /* ++ * The cpu32 is harder to step than the Coldfire. ++ */ ++ if (cpu_type == BDM_CPU32) { ++ bdm_step_cpu32_chip(); ++ return; ++ } ++ ++ /* ++ * Do the single-step ++ */ ++ if (bdmStep () < 0) ++ bdm_report_error (); ++} ++ ++/* ++ * true if runnable ++ */ ++static int ++bdm_can_run (void) ++{ ++ return 1; ++} ++ ++static void ++bdm_setdelay(int delay) ++{ ++ if (bdmSetDelay (delay) < 0) ++ bdm_report_error (); ++} ++ ++static void ++bdm_setdelay_interactive (char *arg, int from_tty) ++{ ++ char *dummy; ++ ++ if (!arg) { ++ if (bdm_delay >= 0) ++ printf_filtered("bdm_delay is %d", bdm_delay); ++ else ++ printf_filtered("using default delay %d", BDM_DEFAULT_DELAY); ++ } ++ else { ++ bdm_delay = strtoul(arg, &dummy, 0); ++ bdm_setdelay (bdm_delay); ++ } ++} ++ ++static void ++bdm_setdebug_interactive (char *arg, int from_tty) ++{ ++ char *dummy; ++ ++ if (arg) { ++ bdmDebugLevel = strtoul(arg, &dummy, 0); ++ bdmSetDebugFlag (bdmDebugLevel); ++ } ++ else ++ error ("Argument missing"); ++} ++ ++static void ++bdm_setdriverdebug_interactive (char *arg, int from_tty) ++{ ++ char *dummy; ++ ++ if (arg) ++ bdmSetDriverDebugFlag (strtoul(arg, &dummy, 0)); ++ else ++ error ("Argument missing"); ++} ++ ++static void ++bdm_set_no_wait (char *arg, int from_tty) ++{ ++ bdm_gdb_no_wait = 1; ++} ++ ++static void ++bdm_set_wait (char *arg, int from_tty) ++{ ++ if (cpu_type == BDM_CPU32) { ++ error ("No wait mode is not supported on a CPU32"); ++ return; ++ } ++ if (bdm_get_status ()) ++ bdm_gdb_no_wait = 0; ++ else ++ error ("The target is running, please stop first"); ++} ++ ++static void ++bdm_issue_stop (char *arg, int from_tty) ++{ ++ bdm_stop_chip (); ++} ++ ++/* ++ * Open a connection the target via bdm ++ * name is the devicename of bdm and the filename to be used ++ * used for communication. ++ */ ++static void ++bdm_open (char *name, int from_tty) ++{ ++ char *p; ++ int version; ++ unsigned long csr; ++ ++ if (bdmIsOpen ()) ++ error ("Bdm is already open, must close it first"); ++ if (name == NULL) ++ error ("Use `target bdm ' 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 the bdm port device."); ++ dev_name = savestring (name, p - name); ++ ++ target_preopen (from_tty); ++ unpush_target (&bdm_ops); ++ ++ if (bdmOpen (dev_name) < 0) ++ bdm_report_error (); ++ if (bdmStatus () & (BDM_TARGETPOWER | BDM_TARGETNC)) { ++ bdmClose (); ++ error ("Target or cable problem"); ++ } ++ ++ /* ++ * Ask the driver for it's version. ++ * We are only interested in the major number when checking the ++ * driver version number. ++ */ ++ if (bdmGetDrvVersion (&version) < 0) ++ bdm_report_error (); ++ if ((version & 0xff00) != (BDM_DRV_VERSION & 0xff00)) { ++ printf_filtered ("Incorrect driver version, looking for %i.%i and found %i.%i\n", ++ BDM_DRV_VERSION >> 8, BDM_DRV_VERSION & 0xff, ++ version >> 8, version & 0xff); ++ bdmClose (); ++ error ("Can't run with wrong BDM driver"); ++ } ++ ++ /* ++ * Get the processor type. ++ */ ++ if (bdmGetProcessor (&cpu_type) < 0) ++ bdm_report_error (); ++ switch (cpu_type) { ++ case BDM_CPU32: ++ bdm_reg_names = cpu32_reg_names; ++ breakpointCode = cpu32_breakpoint; ++ breakpointSize = sizeof cpu32_breakpoint; ++ break; ++ ++ case BDM_COLDFIRE: ++ bdm_reg_names = cf_reg_names; ++ breakpointCode = cf_breakpoint; ++ breakpointSize = sizeof cf_breakpoint; ++ cf_init_watchpoints(); ++ ++ /* ++ * Read the CSR register to determine the debug module ++ * version. ++ */ ++ if (bdmReadSystemRegister (BDM_REG_CSR, &csr) < 0) ++ bdm_report_error (); ++ cf_debug_ver = (csr >> 20) & 0x0f; ++ break; ++ ++ default: ++ bdmClose (); ++ error ("Unknown processor type returned from the driver."); ++ } ++ ++ push_target (&bdm_ops); ++ ++ if (bdm_delay >= 0) ++ bdm_setdelay (bdm_delay); ++ else ++ bdm_setdelay (BDM_DEFAULT_DELAY); ++ if (from_tty) ++ printf_filtered ("Remote %s connected to %s\n", target_shortname, dev_name); ++ if (cpu_type == BDM_COLDFIRE) ++ printf_filtered (" Coldfire debug module version is %d (%s)\n", ++ cf_debug_ver, ++ cf_debug_ver == 0 ? "5206(e)" : "5307/5407(e)"); ++} ++ ++/* ++ * Terminate current application and return to system prompt. ++ * On a target, just let the program keep on running ++ */ ++static void ++bdm_kill (void) ++{ ++ if (bdm_get_status () & BDM_TARGETSTOPPED) ++ bdm_go (); ++} ++ ++static void ++bdm_close (quitting) ++int quitting; ++{ ++ if (quitting) ++ bdm_kill (); ++ bdmClose (); ++} ++ ++/* ++ * _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) ++{ ++ pop_target (); /* calls bdm_close to do the real work */ ++} ++ ++/* ++ * _resume -- Tell the remote machine to resume. ++ */ ++static void ++bdm_resume (int pid, int step, enum target_signal sig) ++{ ++ if (step) ++ bdm_step_chip (); ++ else ++ bdm_go (); ++} ++ ++/* ++ * We have fallen into an exception supported by the runtime system. ++ * by executing a `breakpoint' instruction. ++ */ ++static void ++analyze_exception (struct target_waitstatus *status) ++{ ++ unsigned long pc, sp; ++ unsigned short vec; ++ char opcode[20]; /* `big enough' */ ++ ++ if (cpu_type == BDM_CPU32) { ++ if (bdmReadSystemRegister (BDM_REG_PCC, &pc) < 0) ++ bdm_report_error (); ++ } ++ else { ++ if (bdmReadSystemRegister (BDM_REG_RPC, &pc) < 0) ++ bdm_report_error (); ++ if (pc) ++ pc -= 2; ++ } ++ status->kind = TARGET_WAITKIND_STOPPED; ++ ++ /* ++ * See if it was a `breakpoint' instruction ++ */ ++ if (bdmReadMemory (pc, opcode, breakpointSize) < 0) ++ bdm_report_error (); ++ if (memcmp (breakpointCode, opcode, breakpointSize) == 0) { ++ if (bdmWriteSystemRegister (BDM_REG_RPC, pc) < 0) ++ bdm_report_error (); ++ status->value.sig = TARGET_SIGNAL_TRAP; ++ return; ++ } ++ /* ++ * FIXME: Why an illegal instruction signal ? ++ */ ++ status->value.sig = TARGET_SIGNAL_ILL; ++} ++ ++static int sigintFlag; ++static void ++bdm_signal_handler (int s) ++{ ++ sigintFlag++; ++} ++ ++/* ++ * Wait until the remote machine stops, then return, ++ * storing status in status just as `wait' would. ++ */ ++static int ++bdm_wait (int pid, struct target_waitstatus *status) ++{ ++ unsigned long csr; ++ int bdm_stat; ++ int detach = 0; ++ int ui_count = 0; ++ void (*ofunc) (); ++ ++ hit_watchpoint = 0; ++ if (bdm_gdb_no_wait) { ++ status->kind = TARGET_WAITKIND_STOPPED; ++ status->value.sig = TARGET_SIGNAL_GRANT; ++ return 0; ++ } ++ ++ status->kind = TARGET_WAITKIND_EXITED; ++ status->value.integer = 0; ++ ++ /* ++ * Catch SIGINT signals ++ */ ++ sigintFlag = 0; ++ ofunc = signal (SIGINT, bdm_signal_handler); ++ ++ /* ++ * A work around a problem with the 5206e processor. Not sure ++ * what the issue is. It could be the processor. ++ */ ++ if (cpu_type == BDM_COLDFIRE && cf_debug_ver == 0) ++ nap (10000); ++ ++ /* ++ * Wait here till the target requires service ++ */ ++ while ((bdm_stat = bdm_get_status ()) == 0) { ++ ui_count = 0; ++ while (ui_count++ < 6) { ++ nap (50000); ++ ++ /* N.B. The UI may destroy our world (for instance by calling ++ remote_stop,) in which case we want to get out of here as ++ quickly as possible. It is not safe to touch scb, since ++ someone else might have freed it. The ui_loop_hook signals that ++ we should exit by returning 1. */ ++ ++ if (ui_loop_hook) ++ detach = ui_loop_hook (0); ++ ++ if (detach || sigintFlag) ++ bdm_stop_chip (); ++ } ++ } ++ ++ signal (SIGINT, ofunc); ++ ++ /* ++ * Determine why the target stopped ++ */ ++ 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: ++ case BDM_TARGETHALT: ++ case BDM_TARGETSTOPPED | BDM_TARGETHALT: ++ if (sigintFlag) { ++ status->kind = TARGET_WAITKIND_STOPPED; ++ status->value.sig = TARGET_SIGNAL_TSTP; ++ } ++ else { ++ if (cpu_type == BDM_CPU32) { ++ if (!haveAtemp ++ && (bdmReadSystemRegister (BDM_REG_ATEMP, &atemp) < 0)) ++ bdm_report_error (); ++ switch (atemp & 0xffff) { ++ case 0xffff: /* double bus fault */ ++ status->kind = TARGET_WAITKIND_STOPPED; ++ status->value.sig = TARGET_SIGNAL_BUS; ++ break; ++ case 0x0: /* HW bkpt */ ++ status->kind = TARGET_WAITKIND_STOPPED; ++ status->value.sig = TARGET_SIGNAL_TRAP; ++ break; ++ case 0x1: /* background mode */ ++ analyze_exception (status); ++ break; ++ default: ++ printf_filtered ("bdm_wait: Unknown atemp:%#lx\n", atemp); ++ status->kind = TARGET_WAITKIND_STOPPED; ++ status->value.sig = TARGET_SIGNAL_GRANT; ++ } ++ } ++ else { ++ if (bdmReadSystemRegister (BDM_REG_CSR, &csr) < 0) ++ bdm_report_error (); ++ if (csr & 0x08000000) { /* double bus fault */ ++ status->kind = TARGET_WAITKIND_STOPPED; ++ status->value.sig = TARGET_SIGNAL_BUS; ++ } ++ else { ++ if (csr & 0x04000000) { /* hardware trigger */ ++ hit_watchpoint = 1; ++ status->kind = TARGET_WAITKIND_STOPPED; ++ status->value.sig = TARGET_SIGNAL_TRAP; ++ } ++ else { ++ if (csr & 0x01000000) { /* -BKPT signal */ ++ status->kind = TARGET_WAITKIND_STOPPED; ++ status->value.sig = TARGET_SIGNAL_TRAP; ++ } ++ else { ++ if (csr & 0x02000000) { /* HALT/software bkpt */ ++ analyze_exception (status); ++ } ++ else { ++ printf_filtered ("bdm_wait: Unknown csr:%#lx", ++ csr); ++ status->kind = TARGET_WAITKIND_STOPPED; ++ status->value.sig = TARGET_SIGNAL_GRANT; ++ } ++ } ++ } ++ } ++ } ++ } ++ break; ++ default: ++ printf_filtered ("bdm_wait: Unknown BDM status: %#x", bdm_stat); ++ break; ++ } ++ haveAtemp = 0; ++ return 0; ++} ++ ++/* ++ * The following routines handle the Coldfire hardware breakpoints. Only one ++ * breakpoint supported so far, and it can be either a PC breakpoint or an ++ * address watchpoint. Unfortunately, the TARGET_CAN_USE_HARDWARE_WATCHPOINT ++ * macro only allows for bounds checking within one of the two types and not ++ * limits that cover the sum of both, so extra work is needed. ++ * ++ * (Actually, very few processors seem to have much support for that routine ++ * at all.) ++ * ++ * As a result, the way this is handled is that the can_use routine will allow ++ * the first breakpoint of either type to be added. Any further checking so ++ * that only one of the two can be used is done later when GDB actually tries ++ * to create the breakpoints, usually when the processor is restarted. ++ * ++ * We keep a local copy of the breakpoints list becasue the chain that GDB ++ * keeps isn't exported globally. ++ * ++ * While things could be simplified with only one breakpoint present, setting ++ * up more general routines allows for later expansion if newer versions of ++ * the ColdFire chip support more breakpoints at once. ++ * ++ * Also, the ColdFire supports things like multi-level triggers and triggers ++ * based on the data bus instead of just the address bus. The GDB commands ++ * don't allow for access to this, but much of it isn't necessary anyway, ++ * as GDB has its own method of handling 'breakpoint conditions' that is ++ * sufficient for most tasks. ++ */ ++ ++#define TDR_TRC_DDATA 0x00000000 ++#define TDR_TRC_HALT 0x40000000 ++#define TDR_TRC_DINT 0x80000000 ++#define TDR_L2_EBL 0x20000000 ++#define TDR_L2_ALL 0x1FFF0000 ++#define TDR_L2_EDLW 0x10000000 ++#define TDR_L2_EDWL 0x08000000 ++#define TDR_L2_EDWU 0x04000000 ++#define TDR_L2_EDLL 0x02000000 ++#define TDR_L2_EDLM 0x01000000 ++#define TDR_L2_EDUM 0x00800000 ++#define TDR_L2_EDUU 0x00400000 ++#define TDR_L2_DI 0x00200000 ++#define TDR_L2_EAI 0x00100000 ++#define TDR_L2_EAR 0x00080000 ++#define TDR_L2_EAL 0x00040000 ++#define TDR_L2_EPC 0x00020000 ++#define TDR_L2_PCI 0x00010000 ++#define TDR_L1_EBL 0x00002000 ++#define TDR_L1_ALL 0x00001FFF ++#define TDR_L1_EDLW 0x00001000 ++#define TDR_L1_EDWL 0x00000800 ++#define TDR_L1_EDWU 0x00000400 ++#define TDR_L1_EDLL 0x00000200 ++#define TDR_L1_EDLM 0x00000100 ++#define TDR_L1_EDUM 0x00000080 ++#define TDR_L1_EDUU 0x00000040 ++#define TDR_L1_DI 0x00000020 ++#define TDR_L1_EAI 0x00000010 ++#define TDR_L1_EAR 0x00000008 ++#define TDR_L1_EAL 0x00000004 ++#define TDR_L1_EPC 0x00000002 ++#define TDR_L1_PCI 0x00000001 ++ ++struct cf_break { ++ enum target_hw_bp_type type; ++ CORE_ADDR addr; ++ int len; ++}; ++ ++#define CF_BREAKPOINT_MAX 1 ++ ++static struct cf_break cf_breakpoints[CF_BREAKPOINT_MAX]; ++static int cf_breakpoint_count; ++ ++static int ++cf_init_watchpoints(void) ++{ ++ if (cpu_type != BDM_COLDFIRE) { ++ return(-1); ++ } ++ cf_breakpoint_count = 0; ++ if (bdmWriteSystemRegister (BDM_REG_TDR, TDR_TRC_HALT) < 0) ++ bdm_report_error (); ++ return(0); ++} ++ ++int ++cf_stopped_by_watchpoint(void) ++{ ++ return hit_watchpoint; ++} ++ ++int ++cf_can_use_watchpoint(type, cnt, ot) ++ enum target_hw_bp_type type; ++ int cnt; ++ int ot; ++{ ++ unsigned long tdr; ++ ++ if (cpu_type != BDM_COLDFIRE) { ++ return(0); ++ } ++ ++ if (type == bp_hardware_breakpoint || type == bp_read_watchpoint || ++ type == bp_hardware_watchpoint || type == bp_access_watchpoint) { ++ if (cnt <= 1) { ++ return(1); ++ } ++ } ++ ++ return(-1); ++} ++ ++int ++cf_insert_hw_breakpoint(addr, shadow) ++ CORE_ADDR addr; ++ char *shadow; ++{ ++ unsigned long tdr; ++ ++ if (cpu_type != BDM_COLDFIRE) { ++ return(-1); ++ } ++ ++ if (cf_breakpoint_count < CF_BREAKPOINT_MAX) { ++ cf_breakpoints[cf_breakpoint_count].type = hw_execute; ++ cf_breakpoints[cf_breakpoint_count].addr = addr; ++ cf_breakpoints[cf_breakpoint_count++].len = 2; ++ ++ if (bdmReadSystemRegister (BDM_REG_TDR, &tdr) < 0) ++ bdm_report_error (); ++ tdr = ((tdr & ~TDR_L1_ALL) | (TDR_L1_EBL|TDR_L1_EPC)); ++ if (bdmWriteSystemRegister (BDM_REG_PBR, addr) < 0) ++ bdm_report_error (); ++ if (bdmWriteSystemRegister (BDM_REG_PBMR, 0) < 0) ++ bdm_report_error (); ++ if (bdmWriteSystemRegister (BDM_REG_TDR, tdr) < 0) ++ bdm_report_error (); ++ if (bdmDebugLevel) ++ printf_filtered ("Insert PC Breakpoint @0x%08x\n", addr); ++ } ++ else { ++ return(-1); ++ } ++ return(0); ++} ++ ++static int ++cf_check_breakpoint(type, addr, len) ++ enum target_hw_bp_type type; ++ CORE_ADDR addr; ++ int len; ++{ ++ int i; ++ ++ for (i = 0; i < cf_breakpoint_count; i++) { ++ if (cf_breakpoints[i].type == type && ++ cf_breakpoints[i].addr == addr && ++ cf_breakpoints[i].len == len) { ++ for (; i < CF_BREAKPOINT_MAX-1; i++) { ++ cf_breakpoints[i] = cf_breakpoints[i+1]; ++ } ++ cf_breakpoint_count--; ++ return(1); ++ } ++ } ++ return(0); ++} ++ ++int ++cf_remove_hw_breakpoint(addr, shadow) ++ CORE_ADDR addr; ++ char *shadow; ++{ ++ unsigned long tdr; ++ unsigned long csr; ++ ++ if (cpu_type != BDM_COLDFIRE) { ++ return(-1); ++ } ++ ++ if (cf_check_breakpoint(hw_execute, addr, 2)) { ++ if (bdmReadSystemRegister (BDM_REG_TDR, &tdr) < 0) ++ bdm_report_error (); ++ tdr &= ~TDR_L1_EPC; ++ if ((tdr & TDR_L1_ALL) == 0) { ++ tdr &= ~TDR_L1_EBL; ++ } ++ if (bdmWriteSystemRegister (BDM_REG_TDR, tdr) < 0) ++ bdm_report_error (); ++ if (bdmDebugLevel) ++ printf_filtered ("Remove PC Breakpoint @0x%08x\n", addr); ++ } ++ else { ++ return(-1); ++ } ++ return(0); ++} ++ ++#define AATR_READONLY 0x7F85 ++#define AATR_WRITEONLY 0x7F05 ++#define AATR_READWRITE 0xFF05 ++ ++int ++cf_insert_watchpoint(addr, len, type) ++ CORE_ADDR addr; ++ int len; ++ enum target_hw_bp_type type; ++{ ++ unsigned long tdr; ++ ++ if (cpu_type != BDM_COLDFIRE) { ++ return(-1); ++ } ++ ++ if (cf_breakpoint_count < CF_BREAKPOINT_MAX) { ++ cf_breakpoints[cf_breakpoint_count].type = type; ++ cf_breakpoints[cf_breakpoint_count].addr = addr; ++ cf_breakpoints[cf_breakpoint_count++].len = len; ++ ++ if (bdmReadSystemRegister (BDM_REG_TDR, &tdr) < 0) ++ bdm_report_error (); ++ tdr = ((tdr & ~TDR_L1_ALL) | (TDR_L1_EBL|TDR_L1_EAR)); ++ if (bdmWriteSystemRegister (BDM_REG_ABLR, addr) < 0) ++ bdm_report_error (); ++ if (bdmWriteSystemRegister (BDM_REG_ABHR, addr+len-1) < 0) ++ bdm_report_error (); ++ if (type == hw_read) { ++ if (bdmWriteSystemRegister (BDM_REG_AATR, AATR_READONLY) < 0) ++ bdm_report_error (); ++ if (bdmDebugLevel) ++ printf_filtered ("Insert read Watchpoint @0x%08x-0x%08x\n", ++ addr, addr+len-1); ++ } ++ else if (type == hw_write) { ++ if (bdmWriteSystemRegister (BDM_REG_AATR, AATR_WRITEONLY) < 0) ++ bdm_report_error (); ++ if (bdmDebugLevel) ++ printf_filtered ("Insert write Watchpoint @0x%08x-0x%08x\n", ++ addr, addr+len-1); ++ } ++ else { ++ if (bdmWriteSystemRegister (BDM_REG_AATR, AATR_READWRITE) < 0) ++ bdm_report_error (); ++ if (bdmDebugLevel) ++ printf_filtered ("Insert access Watchpoint @0x%08x-0x%08x\n", ++ addr, addr+len-1); ++ } ++ if (bdmWriteSystemRegister (BDM_REG_TDR, tdr) < 0) ++ bdm_report_error (); ++ } ++ else { ++ return(-1); ++ } ++ return(0); ++} ++ ++int ++cf_remove_watchpoint(addr, len, type) ++ CORE_ADDR addr; ++ int len; ++ enum target_hw_bp_type type; ++{ ++ unsigned long tdr; ++ unsigned long csr; ++ ++ if (cpu_type != BDM_COLDFIRE) { ++ return(-1); ++ } ++ ++ if (cf_check_breakpoint(type, addr, len)) { ++ if (bdmReadSystemRegister (BDM_REG_TDR, &tdr) < 0) ++ bdm_report_error (); ++ tdr &= ~TDR_L1_EAR; ++ if ((tdr & TDR_L1_ALL) == 0) { ++ tdr &= ~TDR_L1_EBL; ++ } ++ if (bdmWriteSystemRegister (BDM_REG_TDR, tdr) < 0) ++ bdm_report_error (); ++ if (bdmDebugLevel) ++ printf_filtered ("Remove %s Watchpoint @0x%08x-0x%08x\n", ++ (type == hw_read) ? "read" : ++ ((type == hw_write) ? "write" : "access"), ++ addr, addr+len-1); ++ } ++ else { ++ return(-1); ++ } ++ return(0); ++} ++ ++int ++cf_stopped_data_address() ++{ ++ unsigned long tdr; ++ unsigned long ablr; ++ ++ if (cpu_type != BDM_COLDFIRE) { ++ return(-1); ++ } ++ ++ if (bdmReadSystemRegister (BDM_REG_TDR, &tdr) < 0) ++ bdm_report_error (); ++ if (bdmReadSystemRegister (BDM_REG_ABLR, &ablr) < 0) ++ bdm_report_error (); ++ ++ if (tdr & TDR_L1_EAR) { ++ return(ablr); ++ } ++ return(0); ++} ++ ++/* 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; ++ unsigned long entry_pt; ++ ++ clear_proceed_status (); ++ init_wait_for_inferior (); ++ if (*args) { ++ prg_file = args; ++ } ++ else { ++ prg_file = execfile; ++ } ++ if (!(prg_file) && !(bdm_prog_loaded)) ++ error ("No program specified to run\n"); ++ if (bdm_prog_loaded) ++ printf_filtered ("Note: `%s' has already been loaded.\n", bdm_prog_loaded); ++ if (query ("Do you want to download `%s'?", prg_file)) ++ bdm_load (prg_file, 0); ++ if (bdmReadSystemRegister (BDM_REG_RPC, &entry_pt) < 0) ++ bdm_report_error (); ++ proceed (entry_pt, TARGET_SIGNAL_DEFAULT, 0); ++} ++ ++/* ++ * Fetch register REGNO, or all user registers if REGNO is -1. ++ */ ++static void ++bdm_fetch_register (int regno) ++{ ++ unsigned long l; ++ char cbuf[4]; ++ int ret; ++ ++ if (regno < 0) { ++ for (regno = 0 ; regno < NUM_REGS ; regno++) ++ bdm_fetch_register (regno); ++ } ++ else { ++ /* ++ * When the target is running the ++ * cpu registers can not be accessed. ++ */ ++ if (bdm_gdb_no_wait && (bdm_get_status () == 0)) { ++ l = 0; ++ ret = 0; ++ } ++ else { ++ if (regno < 16) { ++ ret = bdmReadRegister (regno, &l); ++ } ++ else { ++ if ((regno - 16) < (sizeof (reg_to_dev_num) / sizeof (int))) { ++ ret = bdmReadSystemRegister (reg_to_dev_num[regno - 16], &l); ++ } ++ else { ++ error ("Bad register number (%d)", regno); ++ return; ++ } ++ } ++ } ++ if (ret < 0) ++ bdm_report_error (); ++ cbuf[0] = l >> 24; ++ cbuf[1] = l >> 16; ++ cbuf[2] = l >> 8; ++ cbuf[3] = l; ++ supply_register (regno, cbuf); ++ } ++} ++ ++void ++bdm_prepare_to_store (void) ++{ ++ /* Do nothing, since we can store individual regs */ ++} ++ ++/* ++ * Store register REGNO, or all user registers if REGNO == -1. ++ */ ++void ++bdm_store_register (int regno) ++{ ++ unsigned long l; ++ int ret; ++ ++ if (bdm_gdb_no_wait && (bdm_get_status () == 0)) ++ return; ++ ++ if (regno == -1) { ++ for (regno = 0 ; regno < NUM_REGS ; regno++) ++ bdm_store_register (regno); ++ } ++ else { ++ l = read_register (regno); ++ if (regno < 16) { ++ ret = bdmWriteRegister (regno, l); ++ } ++ else { ++ if ((regno - 16) < (sizeof (reg_to_dev_num) / sizeof (int))) { ++ ret = bdmWriteSystemRegister (reg_to_dev_num[regno - 16], l); ++ } ++ else { ++ error ("Bad register number (%d)", regno); ++ return; ++ } ++ } ++ if (ret < 0) ++ bdm_report_error (); ++ } ++} ++ ++/* ++ * Transfer memory contents between target and host ++ */ ++static int ++bdm_xfer_inferior_memory (CORE_ADDR memaddr, char *myaddr, int len, int write, struct target_ops *t) ++{ ++ int ret; ++ ++ if (write) ++ ret = bdmWriteMemory (memaddr, myaddr, len); ++ else ++ ret = bdmReadMemory (memaddr, myaddr, len); ++ if (ret < 0) ++ bdm_report_error (); ++ return len; ++} ++ ++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"); ++ } ++} ++ ++/* ++ * Load a file. ++ */ ++static void ++bdm_load (char *args, int from_tty) ++{ ++ char *p; ++ ++ if (bdm_prog_loaded) { ++ free (bdm_prog_loaded); ++ bdm_prog_loaded = NULL; ++ } ++ if (!args) { ++ error ( ++ "The bdmload command must include the filename to load.\n" ++ "You may want to use 'run', which uses the file given\n" ++ "on the command line when gdb was invoked."); ++ } ++ if ((bdm_get_status () & BDM_TARGETSTOPPED) == 0) ++ bdm_stop_chip (); ++ ++ /* strip off additional (unwanted) arguments after file name */ ++ for (p = args; (*p != '\0') && (!isspace (*p)); p++) ; ++ *p = '\0'; ++ ++ if (loadExecutable (args) < 0) ++ error ("%s", downloadErrorString); ++ bdm_prog_loaded = savestring (args, strlen (args)); ++} ++ ++/* ++ * Select a CPU32 processor register set. ++ */ ++static void ++bdm_select_cpu32 (char *args, int from_tty) ++{ ++ bdm_reg_names = cpu32_reg_names; ++} ++ ++struct target_ops bdm_ops; ++ ++static void ++init_bdm_ops(void) ++{ ++ bdm_ops.to_shortname = "bdm"; ++ bdm_ops.to_longname = "CPU32 and Coldfire Background Debug Mode Interface for downloading and remote debugging"; ++ bdm_ops.to_doc = "Uses the Public Domain Background Debug Mode Interface connected to the\n" ++"BDM-port of the CPU32 or Coldfire based microcontroller and to a parallel port\n" ++"of the PC.\n" ++"Usage: target bdm \n" ++"where is the BDM character special file (e.g. /dev/bdm0)."; ++ bdm_ops.to_open = bdm_open; ++ bdm_ops.to_close = bdm_close; ++ bdm_ops.to_detach = bdm_detach; ++ bdm_ops.to_resume = bdm_resume; ++ bdm_ops.to_wait = bdm_wait; ++ 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 = memory_insert_breakpoint; ++ bdm_ops.to_remove_breakpoint = memory_remove_breakpoint; ++ bdm_ops.to_kill = bdm_kill; ++ bdm_ops.to_load = bdm_load; ++ bdm_ops.to_create_inferior = bdm_create_inferior; ++ bdm_ops.to_mourn_inferior = generic_mourn_inferior; ++ bdm_ops.to_can_run = bdm_can_run; ++ bdm_ops.to_stratum = process_stratum; ++ 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; ++ bdm_ops.to_magic = OPS_MAGIC; ++}; ++ ++void ++_initialize_remote_bdmcf (void) ++{ ++ init_bdm_ops (); ++ add_com ("bdm_reset", class_obscure, ++ (void (*)(char *, int))bdm_reset, ++ "Reset target and enter BDM mode."); ++ add_com ("bdm_release", class_obscure, ++ (void (*)(char *, int))bdm_release_chip, ++ "Reset target without BDM-mode."); ++ add_com ("bdm_status", class_obscure, ++ (void (*)(char *, int))bdm_get_status_interactive, ++ "Show status of bdm interface\n"); ++ add_com ("bdm_setdelay", class_obscure, ++ bdm_setdelay_interactive, ++ "set delay for download"); ++ add_com ("bdm_setdebug", class_obscure, ++ bdm_setdebug_interactive, ++ "enable/disable BDM diagnostic messages"); ++ add_com ("bdm_setdriverdebug", class_obscure, ++ bdm_setdriverdebug_interactive, ++ "enable/disable BDM driver diagnostic messages"); ++ add_com ("bdm_no_wait", class_obscure, ++ bdm_set_no_wait, ++ "Cause GDB to not wait for the target to stop when running."); ++ add_com ("bdm_wait", class_obscure, ++ bdm_set_wait, ++ "Cause GDB to wait for the target to stop when running."); ++ add_com ("bdm_stop", class_obscure, ++ bdm_issue_stop, ++ "Stop the target if running."); ++ add_com ("bdm-select-cpu32", class_obscure, ++ bdm_select_cpu32, ++ "Selects the CPU32 register set rather than the default CPU32+."); ++ ++ add_target (&bdm_ops); ++} diff --git a/gdb/patches/gdb-5.2.1-bdm-m68k.patch b/gdb/patches/gdb-5.2.1-bdm-m68k.patch new file mode 100644 index 0000000..86867fd --- /dev/null +++ b/gdb/patches/gdb-5.2.1-bdm-m68k.patch @@ -0,0 +1,2016 @@ +diff -urN gdb-5.2.1.orig/gdb/Makefile.in gdb-5.2.1/gdb/Makefile.in +--- gdb-5.2.1.orig/gdb/Makefile.in Sun Nov 3 11:32:33 2002 ++++ gdb-5.2.1/gdb/Makefile.in Sun Nov 3 14:24:44 2002 +@@ -1910,6 +1910,9 @@ + remote-hms.o: remote-hms.c $(defs_h) $(gdbcore_h) \ + $(inferior_h) $(serial_h) $(target_h) $(terminal_h) $(regcache_h) + ++remote-m68k-bdm.o: remote-m68k-bdm.c $(bfd_h) $(wait_h) $(defs_h) $(inferior_h) \ ++ $(gdbcore_h) $(target_h) ++ + remote-mips.o: remote-mips.c $(defs_h) $(gdbcmd_h) \ + $(gdbcore_h) $(inferior_h) $(serial_h) $(symfile_h) $(target_h) \ + $(regcache_h) +diff -urN gdb-5.2.1.orig/gdb/bdm.mt gdb-5.2.1/gdb/bdm.mt +--- gdb-5.2.1.orig/gdb/bdm.mt Thu Jan 1 10:00:00 1970 ++++ gdb-5.2.1/gdb/bdm.mt Sun Nov 3 12:22:28 2002 +@@ -0,0 +1,5 @@ ++# Target: m68k bdm interface for the CPU32 and Coldfire processors. ++# ++TM_CLIBS= -lBDM ++TDEPFILES= m68k-tdep.o remote-m68k-bdm.o ++TM_FILE= tm-bdm.h +diff -urN gdb-5.2.1.orig/gdb/config/m68k/bdm.mt gdb-5.2.1/gdb/config/m68k/bdm.mt +--- gdb-5.2.1.orig/gdb/config/m68k/bdm.mt Thu Jan 1 10:00:00 1970 ++++ gdb-5.2.1/gdb/config/m68k/bdm.mt Sun Nov 3 14:33:20 2002 +@@ -0,0 +1,5 @@ ++# Target: m68k bdm interface for the CPU32 and Coldfire processors. ++# ++TM_CLIBS= -lBDM ++TDEPFILES= m68k-tdep.o remote-m68k-bdm.o ++TM_FILE= tm-bdm.h +diff -urN gdb-5.2.1.orig/gdb/config/m68k/tm-bdm.h gdb-5.2.1/gdb/config/m68k/tm-bdm.h +--- gdb-5.2.1.orig/gdb/config/m68k/tm-bdm.h Thu Jan 1 10:00:00 1970 ++++ gdb-5.2.1/gdb/config/m68k/tm-bdm.h Sun Nov 3 12:22:28 2002 +@@ -0,0 +1,120 @@ ++/* ++ * Target machine description for Coldfire BDM (Moto 5200) ++ * Copyright (C) 1995 W. Eric Norum ++ * Copyright (C) 1998 Chris Johns (ccj@acm.org) ++ * ++ * Based on: ++ * 1. `A Background Debug Mode Driver Package for Motorola's ++ * 16- and 32-Bit Microcontrollers', Scott Howard, Motorola ++ * Canada, 1993. ++ * 2. `Linux device driver for public domain BDM Interface', ++ * M. Schraut, Technische Universitaet Muenchen, Lehrstuhl ++ * fuer Prozessrechner, 1995. ++ * 3. BDM support for gdb by W. Eric Norum ++ * Saskatchewan Accelerator Laboratory ++ * University of Saskatchewan ++ * 107 North Road ++ * Saskatoon, Saskatchewan, CANADA ++ * S7N 5C6 ++ * ++ * 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. ++ */ ++ ++/* ++ * Coldfire does it for us if we use PCC to get the PC ++ */ ++#define DECR_PC_AFTER_BREAK 0 ++ ++/* ++ * We have to control this directly as the CPU32 and Coldfire have different ++ * breakpoint opcodes. ++ */ ++#define BREAKPOINT_FROM_PC m68k_bdm_breakpoint_from_pc ++ ++/* ++ * Include the generic stuff ++ */ ++#include "m68k/tm-m68k.h" ++ ++/* ++ * Override some of the generic definitions ++ */ ++ ++/* ++ * For uCLinux we need to detect we have a subroutine call ++ * which is really a trap #0. This should be caught by the ++ * the IN_SIGTRAMP handler defined above, but incase it is ++ * not we should try and catch it here. ++ */ ++ ++extern CORE_ADDR m68k_bdm_saved_pc_after_call PARAMS ((struct frame_info *)); ++ ++#undef SAVED_PC_AFTER_CALL ++#define SAVED_PC_AFTER_CALL(frame) \ ++ m68k_bdm_saved_pc_after_call (frame) ++ ++/* ++ * we need 40 registers for the CPU32 and Coldfire: ++ * 8 data registers ++ * 8 address registers ++ * 2 other registers (PC, PS) ++ * 22 special registers (actual set depends on architecture) ++ * 0 floating point registers ++ */ ++#undef NUM_REGS ++#undef REGISTER_BYTES ++#define NUM_REGS 40 ++#define REGISTER_BYTES (16*4 + 2*4 + 22*4) ++ ++#undef REGISTER_NAMES ++#define REGISTER_NAME(i) bdm_register_name(i) ++extern const char *bdm_register_name(int i); ++ ++#undef FP0_REGNUM ++#undef FPC_REGNUM ++#undef FPS_REGNUM ++#undef FPI_REGNUM ++#define FP0_REGNUM 40 /* Floating point register 0 */ ++#define FPC_REGNUM FP0_REGNUM + 8 /* 68881 control register */ ++#define FPS_REGNUM FPC_REGNUM + 1 /* 68881 status register */ ++#define FPI_REGNUM FPS_REGNUM + 1 /* 68881 iaddr register */ ++ ++/* ++ * The other definitions and macros don't need to be changed: ++ * a) The Coldfire has no floating point registers ++ * b) The REGISTER_BYTES_OK macro isn't used ++ */ ++ ++#define TARGET_HAS_HARDWARE_WATCHPOINTS ++ ++/* We need to remove watchpoints when stepping, else we hit them again! */ ++ ++#define HAVE_NONSTEPPABLE_WATCHPOINT ++ ++#define STOPPED_BY_WATCHPOINT(w) cf_stopped_by_watchpoint () ++ ++/* Use these macros for watchpoint insertion/deletion. */ ++/* type can be 0: write watch, 1: read watch, 2: access watch (read/write) */ ++ ++#define TARGET_CAN_USE_HARDWARE_WATCHPOINT(type, cnt, ot) \ ++ cf_can_use_watchpoint (type, cnt, ot) ++ ++#define target_insert_watchpoint(addr, len, type) cf_insert_watchpoint (addr, len, type) ++#define target_remove_watchpoint(addr, len, type) cf_remove_watchpoint (addr, len, type) ++#define target_insert_hw_breakpoint(addr, shadow) cf_insert_hw_breakpoint (addr, shadow) ++#define target_remove_hw_breakpoint(addr, shadow) cf_remove_hw_breakpoint (addr, shadow) ++#define target_stopped_data_address() cf_stopped_data_address () +diff -urN gdb-5.2.1.orig/gdb/configure.tgt gdb-5.2.1/gdb/configure.tgt +--- gdb-5.2.1.orig/gdb/configure.tgt Sun Nov 3 11:32:33 2002 ++++ gdb-5.2.1/gdb/configure.tgt Sun Nov 3 14:25:39 2002 +@@ -149,6 +149,8 @@ + m68000-*-sunos3*) gdb_target=sun2os3 ;; + m68000-*-sunos4*) gdb_target=sun2os4 ;; + ++m68*-bdm-*) gdb_target=bdm ;; ++ + m68*-apollo*-bsd*) gdb_target=apollo68b ;; + m68*-bull-sysv*) gdb_target=dpx2 ;; + m68*-hp-bsd*) gdb_target=hp300bsd ;; +diff -urN gdb-5.2.1.orig/gdb/doc/gdb.texinfo gdb-5.2.1/gdb/doc/gdb.texinfo +--- gdb-5.2.1.orig/gdb/doc/gdb.texinfo Sun Nov 3 11:32:33 2002 ++++ gdb-5.2.1/gdb/doc/gdb.texinfo Sun Nov 3 12:22:28 2002 +@@ -10965,6 +10965,7 @@ + * i960:: Intel i960 + * M32R/D:: Mitsubishi M32R/D + * M68K:: Motorola M68K ++* Motorola BDM:: Motorola M68K/Coldfire Background Debug Mode + * M88K:: Motorola M88K + * MIPS Embedded:: MIPS Embedded + * PA:: HP PA Embedded +@@ -11606,6 +11607,10 @@ + @item target abug @var{dev} + ABug ROM monitor for M68K. + ++@kindex target bdm ++Background Debug Mode interface to Motorola 68k/Coldfire machine. ++@xref{Motorola BDM Target, ,@value{GDBN} and Motorola 68k/Coldfire BDM}. ++ + @kindex target cpu32bug + @item target cpu32bug @var{dev} + CPU32BUG monitor, running on a CPU32 (M68K) board. +@@ -11644,6 +11649,101 @@ + ROMBUG ROM monitor for OS/9000. + + @end table ++ ++ ++@node Motorola BDM ++@subsection @value{GDBN} and Motorola BDM ++ ++@cindex BDM ++@cindex CPU32 ++@cindex Coldfire ++Background Debug Mode (@dfn{BDM}) provides a full set of debug options ++including the ability to: ++@itemize @bullet ++@item Insert breakpoints ++@item Single-step ++@item Display register contents ++@item Display memory contents ++@item Modify register contents ++@item Modify memory contents ++@end itemize ++ ++A small interface circuit connects the BDM interface port on the ++target machine to a parallel printer port on the debugging host. ++A target system can be configured and a program downloaded and ++executed with no bootstrap memory on the target machine and no other ++connection between the debugging host and the target machine. ++ ++The @code{target} command tells @value{GDBN} ++to debug a program running on a target machine ++@xref{Target Commands, ,Commands for managing targets}. ++For example, the following command tells @value{GDBN} to use a BDM ++interface connected to a ColdFire processor and the @code{LPT0} parallel port: ++@example ++target bdm /dev/bdmcf0 ++@end example ++ ++Do not attempt to use the parallel port for any other purpose while ++@value{GDBN} is using it to control a BDM target. ++ ++Once the BDM target has been selected a few other commands become ++available: ++ ++@table @code ++@item bdm_reset ++@kindex bdm_reset ++Reset the target machine and enable BDM operation in the target. ++ ++@item bdm_restart ++@kindex bdm_restart ++Reset the target machine and disable BDM operation in the target. ++This command is useful only if the target machine has some kind of ++bootstrap memory installed. ++ ++@item bdm_status ++@kindex bdm_status ++Print the status of the target machine and the BDM interface. ++ ++@item bdm_setdelay @var{N} ++@kindex bdm_setdelay ++Some BDM interface circuits can not handle high-speed data transfer. ++This command lets you insert a delay between each BDM clock. ++The larger the value of @var{N}, the longer the delay. ++On most machines the default delay of @var{0} should work just fine. ++ ++@item bdm_setdebug @var{N} ++@kindex bdm_setdebug ++Setting the level (@var{N}) to a non-zero value turns on ++debugging messages in the BDM support library. ++ ++@item bdm_setdriverdebug @var{N} ++@kindex bdm_setdriverdebug ++Setting the level (@var{N}) to a non-zero value turns on ++debugging messages in the BDM device driver. ++ ++@end table ++ ++The registers which can be displayed and modified are: ++@itemize @bullet ++@item The data registers: @code{$d0}-@code{$d7} ++@item The address registers: @code{$a0}-@code{$a5}, @code{$fp}, @code{$sp} ++@item The program counter: @code{$pc} ++@item The status register: @code{$ps} ++@item The program counter at the beginning of the most recently executed ++instruction: @code{$pcc} ++@item The user stack pointer: @code{$usp} ++@item The supervisor stack pointer: @code{$ssp} ++@item The source function code register: @code{$sfc} ++@item The destinaton function code register: @code{$dfc} ++@item The vector base register: @code{$vbr} ++@item The fault address register: @code{$far} ++@item The BDM temporary register: @code{$atemp} ++@item The module base address register: @code{$mbar} ++@end itemize ++ ++Target processor interrupts are disabled during single-step (step, next, ++stepi, nexti) operations. ++ + + @node M88K + @subsection M88K +diff -urN gdb-5.2.1.orig/gdb/remote-m68k-bdm.c gdb-5.2.1/gdb/remote-m68k-bdm.c +--- gdb-5.2.1.orig/gdb/remote-m68k-bdm.c Thu Jan 1 10:00:00 1970 ++++ gdb-5.2.1/gdb/remote-m68k-bdm.c Mon Nov 4 09:59:56 2002 +@@ -0,0 +1,1721 @@ ++/* ++ * Motorola Background Debug Mode Target ++ * Copyright (C) 1995 W. Eric Norum ++ * Copyright (C) 1998 Chris Johns (ccj@acm.org) ++ * Copyright (C) 2000 Bryan Feir (bryan@sgl.crestech.ca) ++ * ++ * Based on: ++ * 1. `A Background Debug Mode Driver Package for Motorola's ++ * 16- and 32-Bit Microcontrollers', Scott Howard, Motorola ++ * Canada, 1993. ++ * 2. `Linux device driver for public domain BDM Interface', ++ * M. Schraut, Technische Universitaet Muenchen, Lehrstuhl ++ * fuer Prozessrechner, 1995. ++ * 3. BDM support for gdb by W. Eric Norum ++ * Saskatchewan Accelerator Laboratory ++ * University of Saskatchewan ++ * 107 North Road ++ * Saskatoon, Saskatchewan, CANADA ++ * S7N 5C6 ++ * 4. Coldfire support added by C Johns. ++ * 5. Hardware breakpoint support added by B Feir. ++ * ++ * 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. ++ * ++ * W. Eric Norum ++ * Saskatchewan Accelerator Laboratory ++ * University of Saskatchewan ++ * 107 North Road ++ * Saskatoon, Saskatchewan, CANADA ++ * S7N 5C6 ++ * ++ * eric@skatter.usask.ca ++ * ++ * Coldfire support by: ++ * Chris Johns ++ * Objective Design Systems ++ * 35 Cairo Street ++ * Cammeray, Sydney, 2062, Australia ++ * ++ * ccj@acm.org ++ * ++ * Coldfire hardware breakpoint support by: ++ * Bryan Feir ++ * CRESTech (Centre for Research in Earth and Space Technology) ++ * 4850 Keele Street, 1st floor ++ * Toronto, Ontario, CANADA M6E 3E5 ++ * ++ * bryan@sgl.crestech.ca ++ */ ++ ++/* ++ * $Revision: 1.1 $ $Date: 2004/03/28 23:13:10 $ $Author: codewiz $ ++ */ ++ ++#include "defs.h" ++#include "gdbcore.h" ++#include "target.h" ++#include ++#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" ++ ++extern struct target_ops bdm_ops; /* Forward declaration */ ++ ++/* ++ * The name of the BDM driver special file ++ */ ++static char *dev_name; ++static int cpu_type; ++ ++/* ++ * The different register names for the processors. ++ */ ++static const char *cpu32plus_reg_names[NUM_REGS] = { ++ "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", ++ NULL, NULL, NULL, NULL, ++ "mbar", ++ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ++}; ++ ++static const char *cpu32_reg_names[NUM_REGS] = { ++ "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", ++ "a0", "a1", "a2", "a3", "a4", "a5", "fp", "sp", ++ "ps", "pc", ++ "pcc", "usp", "ssp", "sfc", "dfc", NULL, NULL, ++ "vbr", ++ NULL, NULL, NULL, NULL, ++ NULL, ++ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ++}; ++ ++static const char *cf_reg_names[NUM_REGS] = { ++ "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", ++ "a0", "a1", "a2", "a3", "a4", "a5", "fp", "sp", ++ "ps", "pc", ++ NULL, NULL, NULL, NULL, NULL, NULL, NULL, ++ "vbr", ++ "cacr", "acr0", "acr1", "rambar", ++ "mbar", ++ "csr", "aatr", "tdr", "pbr", "pbmr", "abhr", "ablr", "dbr", "dbmr", ++}; ++ ++static const char **bdm_reg_names = cpu32plus_reg_names; ++ ++const char *bdm_register_name(int i) ++{ ++ if ((i < 0) || (i >= NUM_REGS)) ++ return NULL; ++ return bdm_reg_names[i]; ++} ++ ++static int reg_to_dev_num[] = { ++ BDM_REG_SR, ++ BDM_REG_RPC, ++ BDM_REG_PCC, ++ BDM_REG_USP, ++ BDM_REG_SSP, ++ BDM_REG_SFC, ++ BDM_REG_DFC, ++ BDM_REG_ATEMP, ++ BDM_REG_FAR, ++ BDM_REG_VBR, ++ BDM_REG_CACR, ++ BDM_REG_ACR0, ++ BDM_REG_ACR1, ++ BDM_REG_RAMBAR, ++ BDM_REG_MBAR, ++ BDM_REG_CSR, ++ BDM_REG_AATR, ++ BDM_REG_TDR, ++ BDM_REG_PBR, ++ BDM_REG_PBMR, ++ BDM_REG_ABHR, ++ BDM_REG_ABLR, ++ BDM_REG_DBR, ++ BDM_REG_DBMR ++ }; ++ ++/* ++ * The name of the most recently loaded program ++ */ ++static char *bdm_prog_loaded; ++ ++/* ++ * Do not load the program when creating the target. ++ */ ++static int bdm_no_load; ++ ++/* ++ * default delay for interface ++ */ ++#define BDM_DEFAULT_DELAY 0 ++static int bdm_delay = -1; ++ ++/* ++ * does gdb wait or not, only valid for a Coldfire processor ++ */ ++static int bdm_gdb_no_wait = 0; ++ ++/* ++ * Hold BDM ATEMP register (CPU32 only). ++ */ ++static unsigned long atemp; ++static int haveAtemp; ++ ++static int hit_watchpoint; ++ ++/* ++ * CF BDM Debug hardware version number. ++ */ ++ ++static unsigned long cf_debug_ver; ++ ++/* ++ * Not sure if this is defined somewhere. Cannot see anywhere. ++ */ ++extern int (*ui_loop_hook) (int); ++ ++/* ++ * Forward declarations ++ */ ++static void bdm_load (char *, int); ++ ++/* ++ * give target time to come up after reset ++ * time in usec ++ */ ++#define TIME_TO_COME_UP 60000 ++ ++/* ++ * Downloader routines ++ */ ++static int downLoaderReturn; ++static int downLoaderFirst; ++static unsigned long downLoadBaseAddress, downLoadStartAddress; ++static int bdmDebugLevel; ++static const char *downloadErrorString; ++ ++static void ++downloadSection (bfd *abfd, sec_ptr sec, PTR ignore) ++{ ++ unsigned long dfc; ++ unsigned long address; ++ unsigned long nleft; ++ int count; ++ file_ptr offset; ++ char cbuf[1024]; ++ ++ /* ++ * See if the section needs loading ++ */ ++ if (bdmDebugLevel) ++ printf_filtered ("Section flags:%#x", bfd_get_section_flags (abfd, sec)); ++ if ((downLoaderReturn < 0) || ++ ((bfd_get_section_flags (abfd, sec) & SEC_HAS_CONTENTS) == 0) || ++ ((bfd_get_section_flags (abfd, sec) & SEC_LOAD) == 0)) ++ return; ++ address = bfd_section_lma (abfd, sec); ++ if (bdmDebugLevel) ++ printf_filtered ("Section address:%#x", address); ++ if (downLoaderFirst && (bfd_get_section_flags (abfd, sec) & SEC_CODE)) { ++ downLoadStartAddress = bfd_get_start_address (abfd); ++ downLoadBaseAddress = address; ++ downLoaderFirst = 0; ++ if (bdmDebugLevel) ++ printf_filtered ("Start address:%#x Base address:%#x", ++ downLoadStartAddress, downLoadBaseAddress); ++ } ++ ++ /* ++ * Set the appropriate destination address space ++ */ ++ if (bfd_get_section_flags (abfd, sec) & SEC_CODE) ++ dfc = 0x6; /* Supervisor program space */ ++ else ++ dfc = 0x5; /* Supervisor data space */ ++ if (bdmWriteSystemRegister (BDM_REG_DFC, dfc) < 0) { ++ downLoaderReturn = -1; ++ return; ++ } ++ ++ /* ++ * Load the section in `sizeof cbuf` chunks ++ */ ++ nleft = bfd_get_section_size_before_reloc (sec); ++ if (nleft == 0) ++ return; ++ offset = 0; ++ while (nleft) { ++ if (nleft > sizeof cbuf) ++ count = sizeof cbuf; ++ else ++ count = nleft; ++ if (!bfd_get_section_contents (abfd, sec, cbuf, offset, count)) { ++ downloadErrorString = "Error reading section contents"; ++ downLoaderReturn = -1; ++ return; ++ } ++ if (bdmWriteMemory (address, cbuf, count) < 0) { ++ downLoaderReturn = -1; ++ return; ++ } ++ address += count; ++ offset += count; ++ nleft -= count; ++ } ++} ++ ++/* ++ * Load an executable image into the target ++ */ ++static int ++loadExecutable (const char *name) ++{ ++ bfd *abfd; ++ unsigned long dfc; ++ unsigned long l; ++ ++ /* ++ * Make sure target is there ++ */ ++ if (!bdmCheck ()) ++ return -1; ++ ++ /* ++ * Open and verify the file ++ */ ++ bfd_init (); ++ abfd = bfd_openr (name, "default"); ++ if (abfd == NULL) { ++ downloadErrorString = bfd_errmsg (bfd_get_error()); ++ return -1; ++ } ++ if (!bfd_check_format (abfd, bfd_object)) { ++ downloadErrorString = "Not an object file"; ++ return -1; ++ } ++ ++ /* ++ * Save the destination function code register ++ */ ++ if (bdmReadSystemRegister (BDM_REG_DFC, &dfc) < 0) ++ return -1; ++ ++ /* ++ * Load each section of the executable file ++ */ ++ downLoaderFirst = 1; ++ downLoaderReturn = 0; ++ bfd_map_over_sections (abfd, downloadSection, NULL); ++ if (downLoaderReturn < 0) ++ return -1; ++ ++ /* ++ * Set up stack pointer and program counter ++ */ ++ if ((bdmReadLongWord (downLoadBaseAddress, &l) < 0) ++ || (bdmWriteSystemRegister (BDM_REG_SSP, l) < 0) ++ || (bdmReadLongWord (downLoadBaseAddress+4, &l) < 0) ++ || (bdmWriteSystemRegister (BDM_REG_RPC, l) < 0) ++ || (bdmWriteSystemRegister (BDM_REG_VBR, downLoadBaseAddress) < 0) ++ || (bdmWriteSystemRegister (BDM_REG_DFC, dfc) < 0)) ++ return -1; ++ return 0; ++} ++ ++/* ++ * The breakpoint codes for the different processors ++ */ ++static char cpu32_breakpoint[] = {0x4a, 0xfa}; ++static char cf_breakpoint[] = {0x4a, 0xc8}; ++static char *breakpointCode; ++static int breakpointSize; ++ ++static int cf_init_watchpoints(); ++ ++/* Immediately after a function call, return the saved pc before the frame ++ is setup. For uCLinux which uses a TRAP #0 for a system call we need to ++ read the first long word of the stack to see if the stack frame format is ++ type 4 and the vector is 32 (0x4080), and the opcode at the PC is ++ "move.w #0x2700,sr". If it is then get the second long from the stack. */ ++ ++CORE_ADDR ++m68k_bdm_saved_pc_after_call (frame) ++ struct frame_info *frame; ++{ ++ unsigned int op; ++ unsigned int eframe; ++ int sp; ++ ++ sp = read_register (SP_REGNUM); ++ eframe = read_memory_integer (sp, 2); ++ op = read_memory_integer (frame->pc, 4); ++ ++ /* ++ * This test could break if some changes the syste call. ++ */ ++ ++ if (eframe == 0x4080 && op == 0x46fc2700) ++ return read_memory_integer (sp + 4, 4); ++ else ++ return read_memory_integer (sp, 4); ++} ++ ++unsigned char *m68k_bdm_breakpoint_from_pc (pcptr, lenptr) ++ CORE_ADDR *pcptr; ++ int *lenptr; ++{ ++ *lenptr = breakpointSize; ++ return breakpointCode; ++} ++ ++/* ++ * Short pause ++ */ ++static void ++nap (int microseconds) ++{ ++ struct timeval tv; ++ ++ tv.tv_sec = microseconds / 1000000; ++ tv.tv_usec = microseconds % 1000000; ++ select (0, NULL, NULL, NULL, &tv); ++} ++ ++/* ++ * Display error message and jump back to main input loop ++ */ ++static void ++bdm_report_error (void) ++{ ++ error ("BDM error: %s", bdmErrorString ()); ++} ++ ++/* ++ * Initialize bdm interface port ++ */ ++static void ++bdm_init (int tty, char *arg) ++{ ++} ++ ++/* ++ * Return interface status ++ */ ++static int ++bdm_get_status (void) ++{ ++ int status; ++ ++ if ((status = bdmStatus ()) < 0) ++ bdm_report_error (); ++ return status; ++} ++ ++static void ++bdm_get_status_interactive (int pid, char *arg) ++{ ++ printf ("BDM status: 0x%x\n", bdm_get_status ()); ++} ++ ++/* ++ * release chip: reset and disable bdm mode ++ */ ++static void ++bdm_release_chip (void) ++{ ++ haveAtemp = 0; ++ registers_changed (); ++ if (bdmRelease () < 0) ++ bdm_report_error (); ++} ++ ++/* ++ * stop chip ++ */ ++static void ++bdm_stop_chip (void) ++{ ++ if (bdmStop () < 0) ++ bdm_report_error (); ++} ++ ++/* ++ * Allow chip to resume execution ++ */ ++static void ++bdm_go (void) ++{ ++ haveAtemp = 0; ++ if (bdmGo () < 0) ++ bdm_report_error (); ++} ++ ++/* ++ * Reset chip, enter BDM mode ++ */ ++static void ++bdm_reset (void) ++{ ++ registers_changed (); ++ if (bdmReset () < 0) ++ bdm_report_error (); ++ nap (TIME_TO_COME_UP); ++} ++ ++/* ++ * step cpu32 chip: execute a single instruction ++ * This is complicated by the presence of interrupts. ++ * Consider the following sequence of events: ++ * - User attempts to `continue' from a breakpoint. ++ * - Gdb calls bdm_step_chip to single-step the instruction that ++ * had been replaced by the BGND instruction. ++ * - The target processor executes the instruction and stops. ++ * - GDB replaces the instruction with a BGND instruction to ++ * force a breakpoint the next time the instruction is hit. ++ * - GDB calls bdm_go and the target resumes execution. ++ * This all seems fine, but now consider what happens when a interrupt ++ * is pending: ++ * - User attempts to `continue' from a breakpoint. ++ * - Gdb calls bdm_step_chip to single-step the instruction that ++ * had been replaced by the BGND instruction. ++ * - The target processor does not execute the replaced instruction, ++ * but rather executes the first instruction of the interrupt ++ * service routine, then stops. ++ * - GDB replaces the instruction with a BGND instruction to ++ * force a breakpoint the next time the instruction is hit. ++ * - GDB calls bdm_go and the target resumes execution. ++ * - The target finishes off the interrupt, and upon returing from ++ * the interrupt generates another breakpoint! ++ * The solution is simple -- disable interrupts when single stepping. ++ * The problem then becomes the handling of instructions which involve ++ * the program status word! ++ */ ++static void ++bdm_step_cpu32_chip (void) ++{ ++ unsigned long pc; ++ unsigned short instruction; ++ unsigned short immediate; ++ unsigned long d7; ++ unsigned long sr; ++ unsigned long nsr; ++ enum { ++ op_other, ++ op_ANDIsr, ++ op_EORIsr, ++ op_ORIsr, ++ op_TOsr, ++ op_FROMsr, ++ op_FROMsrTOd7 ++ } op; ++ ++ /* ++ * Get the existing status register ++ */ ++ if (bdmReadSystemRegister (BDM_REG_SR, &sr) < 0) ++ bdm_report_error (); ++ ++ /* ++ * Read the instuction about to be executed ++ */ ++ if ((bdmReadSystemRegister (BDM_REG_RPC, &pc) < 0) ++ || (bdmReadWord (pc, &instruction) < 0)) ++ bdm_report_error (); ++ ++ /* ++ * See what operation is to be performed ++ */ ++ if (instruction == 0x027C) ++ op = op_ANDIsr; ++ else if (instruction == 0x0A7C) ++ op = op_EORIsr; ++ else if (instruction == 0x007C) ++ op = op_ORIsr; ++ else if (instruction == 0x40C7) ++ op = op_FROMsrTOd7; ++ else if ((instruction & 0xFFC0) == 0x40C0) ++ op = op_FROMsr; ++ else if ((instruction & 0xFFC0) == 0x46C0) ++ op = op_TOsr; ++ else ++ op = op_other; ++ ++ /* ++ * Set things up for the single-step operation ++ */ ++ switch (op) { ++ case op_FROMsr: ++ /* ++ * It's storing the SR somewhere. ++ * Store the SR in D7 and change the instruction ++ * to save D7. This fails if the addressing mode ++ * is one of the esoteric modes that uses D7 as ++ * and index register, but we'll just have to hope ++ * that doesn't happen too often. ++ */ ++ if ((bdmReadRegister (7, &d7) < 0) ++ || (bdmWriteRegister (7, sr) < 0) ++ || (bdmWriteWord (pc, 0x3007 | ++ ((instruction & 0x38) << 3) | ++ ((instruction & 0x07) << 9)) < 0)) ++ bdm_report_error (); ++ break; ++ ++ case op_ANDIsr: ++ case op_EORIsr: ++ case op_ORIsr: ++ /* ++ * It's an immediate operation to the SR -- pick up the value ++ */ ++ if (bdmReadWord (pc+2, &immediate) < 0) ++ bdm_report_error (); ++ break; ++ ++ case op_TOsr: ++ case op_other: ++ break; ++ } ++ ++ /* ++ * Ensure the step is done with interrupts disabled ++ */ ++ if (bdmWriteSystemRegister (BDM_REG_SR, sr | 0x0700) < 0) ++ bdm_report_error (); ++ ++ /* ++ * Do the single-step ++ */ ++ if (bdmStep () < 0) ++ bdm_report_error (); ++ ++ /* ++ * Get the ATEMP register since the following operations may ++ * modify it. ++ */ ++ if (bdmReadSystemRegister (BDM_REG_ATEMP, &atemp) < 0) ++ bdm_report_error (); ++ haveAtemp = 1; ++ ++ /* ++ * Clean things up ++ */ ++ switch (op) { ++ case op_FROMsr: ++ if ((bdmWriteRegister (7, d7) < 0) ++ || (bdmWriteWord (pc, instruction) < 0) ++ || (bdmWriteSystemRegister (BDM_REG_SR, sr) < 0)) ++ bdm_report_error (); ++ break; ++ ++ case op_FROMsrTOd7: ++ if ((bdmReadRegister (7, &d7) < 0) ++ || (bdmWriteRegister (7, (d7 & ~0xFFFF) | (sr & 0xFFFF)) < 0) ++ || (bdmWriteSystemRegister (BDM_REG_SR, sr) < 0)) ++ bdm_report_error (); ++ break; ++ ++ case op_ANDIsr: ++ if (bdmWriteSystemRegister (BDM_REG_SR, sr & immediate) < 0) ++ bdm_report_error (); ++ break; ++ ++ case op_EORIsr: ++ if (bdmWriteSystemRegister (BDM_REG_SR, sr ^ immediate) < 0) ++ bdm_report_error (); ++ break; ++ ++ case op_ORIsr: ++ if (bdmWriteSystemRegister (BDM_REG_SR, sr | immediate) < 0) ++ bdm_report_error (); ++ break; ++ ++ case op_TOsr: ++ break; ++ ++ case op_other: ++ if ((bdmReadSystemRegister (BDM_REG_SR, &nsr) < 0) ++ || (bdmWriteSystemRegister (BDM_REG_SR, (nsr & ~0x0700) | (sr & 0x0700)) < 0)) ++ bdm_report_error (); ++ break; ++ } ++} ++ ++static void ++bdm_step_chip (void) ++{ ++ /* ++ * The cpu32 is harder to step than the Coldfire. ++ */ ++ if (cpu_type == BDM_CPU32) { ++ bdm_step_cpu32_chip(); ++ return; ++ } ++ ++ /* ++ * Do the single-step ++ */ ++ if (bdmStep () < 0) ++ bdm_report_error (); ++} ++ ++/* ++ * true if runnable ++ */ ++static int ++bdm_can_run (void) ++{ ++ return 1; ++} ++ ++static void ++bdm_setdelay(int delay) ++{ ++ if (bdmSetDelay (delay) < 0) ++ bdm_report_error (); ++} ++ ++static void ++bdm_setdelay_interactive (char *arg, int from_tty) ++{ ++ char *dummy; ++ ++ if (!arg) { ++ if (bdm_delay >= 0) ++ printf_filtered("bdm_delay is %d", bdm_delay); ++ else ++ printf_filtered("using default delay %d", BDM_DEFAULT_DELAY); ++ } ++ else { ++ bdm_delay = strtoul(arg, &dummy, 0); ++ bdm_setdelay (bdm_delay); ++ } ++} ++ ++static void ++bdm_setdebug_interactive (char *arg, int from_tty) ++{ ++ char *dummy; ++ ++ if (arg) { ++ bdmDebugLevel = strtoul(arg, &dummy, 0); ++ bdmSetDebugFlag (bdmDebugLevel); ++ } ++ else ++ error ("Argument missing"); ++} ++ ++static void ++bdm_setdriverdebug_interactive (char *arg, int from_tty) ++{ ++ char *dummy; ++ ++ if (arg) ++ bdmSetDriverDebugFlag (strtoul(arg, &dummy, 0)); ++ else ++ error ("Argument missing"); ++} ++ ++static void ++bdm_set_no_wait (char *arg, int from_tty) ++{ ++ bdm_gdb_no_wait = 1; ++} ++ ++static void ++bdm_set_wait (char *arg, int from_tty) ++{ ++ if (cpu_type == BDM_CPU32) { ++ error ("No wait mode is not supported on a CPU32"); ++ return; ++ } ++ if (bdm_get_status ()) ++ bdm_gdb_no_wait = 0; ++ else ++ error ("The target is running, please stop first"); ++} ++ ++static void ++bdm_issue_stop (char *arg, int from_tty) ++{ ++ bdm_stop_chip (); ++} ++ ++/* ++ * Open a connection the target via bdm ++ * name is the devicename of bdm and the filename to be used ++ * used for communication. ++ */ ++static void ++bdm_open (char *name, int from_tty) ++{ ++ char *p; ++ int version; ++ unsigned long csr; ++ ++ if (bdmIsOpen ()) ++ error ("Bdm is already open, must close it first"); ++ if (name == NULL) ++ error ("Use `target bdm ' 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 the bdm port device."); ++ dev_name = savestring (name, p - name); ++ ++ target_preopen (from_tty); ++ unpush_target (&bdm_ops); ++ ++ if (bdmOpen (dev_name) < 0) ++ bdm_report_error (); ++ if (bdmStatus () & (BDM_TARGETPOWER | BDM_TARGETNC)) { ++ bdmClose (); ++ error ("Target or cable problem"); ++ } ++ ++ /* ++ * Ask the driver for it's version. ++ * We are only interested in the major number when checking the ++ * driver version number. ++ */ ++ if (bdmGetDrvVersion (&version) < 0) ++ bdm_report_error (); ++ if ((version & 0xff00) != (BDM_DRV_VERSION & 0xff00)) { ++ printf_filtered ("Incorrect driver version, looking for %i.%i"\ ++ " and found %i.%i\n", ++ BDM_DRV_VERSION >> 8, BDM_DRV_VERSION & 0xff, ++ version >> 8, version & 0xff); ++ bdmClose (); ++ error ("Can't run with wrong BDM driver"); ++ } ++ ++ /* ++ * Get the processor type. ++ */ ++ if (bdmGetProcessor (&cpu_type) < 0) ++ bdm_report_error (); ++ switch (cpu_type) { ++ case BDM_CPU32: ++ bdm_reg_names = cpu32_reg_names; ++ breakpointCode = cpu32_breakpoint; ++ breakpointSize = sizeof cpu32_breakpoint; ++ break; ++ ++ case BDM_COLDFIRE: ++ bdm_reg_names = cf_reg_names; ++ breakpointCode = cf_breakpoint; ++ breakpointSize = sizeof cf_breakpoint; ++ cf_init_watchpoints(); ++ ++ /* ++ * Read the CSR register to determine the debug module ++ * version. ++ */ ++ if (bdmReadSystemRegister (BDM_REG_CSR, &csr) < 0) ++ bdm_report_error (); ++ cf_debug_ver = (csr >> 20) & 0x0f; ++ break; ++ ++ default: ++ bdmClose (); ++ error ("Unknown processor type returned from the driver."); ++ } ++ ++ push_target (&bdm_ops); ++ ++ if (bdm_delay >= 0) ++ bdm_setdelay (bdm_delay); ++ else ++ bdm_setdelay (BDM_DEFAULT_DELAY); ++ if (from_tty) ++ printf_filtered ("Remote %s connected to %s\n", ++ target_shortname, dev_name); ++ if (cpu_type == BDM_COLDFIRE) ++ printf_filtered (" Coldfire debug module version is %d (%s)\n", ++ cf_debug_ver, ++ cf_debug_ver == 0 ? "5206(e)" : "5307/5407(e)"); ++/* inferior_pid = 1; */ ++} ++ ++/* ++ * Terminate current application and return to system prompt. ++ * On a target, just let the program keep on running ++ */ ++static void ++bdm_kill (void) ++{ ++#ifdef BDM_GDB_RELEASE_CPU_ON_EXIT ++ if (bdm_get_status () & BDM_TARGETSTOPPED) ++ bdm_go (); ++#else ++ bdm_stop_chip (); ++ bdm_reset (); ++#endif ++ bdm_prog_loaded = 0; ++} ++ ++static void ++bdm_close (quitting) ++int quitting; ++{ ++ if (quitting) ++ bdm_kill (); ++ bdmClose (); ++} ++ ++/* ++ * _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) ++{ ++ pop_target (); /* calls bdm_close to do the real work */ ++} ++ ++/* ++ * _resume -- Tell the remote machine to resume. ++ */ ++static void ++bdm_resume (ptid_t pid, int step, enum target_signal sig) ++{ ++ if (step) ++ bdm_step_chip (); ++ else ++ bdm_go (); ++} ++ ++/* ++ * We have fallen into an exception supported by the runtime system. ++ * by executing a `breakpoint' instruction. ++ */ ++static void ++analyze_exception (struct target_waitstatus *status) ++{ ++ unsigned long pc, sp; ++ unsigned short vec; ++ char opcode[20]; /* `big enough' */ ++ ++ if (cpu_type == BDM_CPU32) { ++ if (bdmReadSystemRegister (BDM_REG_PCC, &pc) < 0) ++ bdm_report_error (); ++ } ++ else { ++ if (bdmReadSystemRegister (BDM_REG_RPC, &pc) < 0) ++ bdm_report_error (); ++ if (pc) ++ pc -= 2; ++ } ++ status->kind = TARGET_WAITKIND_STOPPED; ++ ++ /* ++ * See if it was a `breakpoint' instruction ++ */ ++ if (bdmReadMemory (pc, opcode, breakpointSize) < 0) ++ bdm_report_error (); ++ if (memcmp (breakpointCode, opcode, breakpointSize) == 0) { ++ if (bdmWriteSystemRegister (BDM_REG_RPC, pc) < 0) ++ bdm_report_error (); ++ status->value.sig = TARGET_SIGNAL_TRAP; ++ return; ++ } ++ /* ++ * FIXME: Why an illegal instruction signal ? ++ */ ++ status->value.sig = TARGET_SIGNAL_ILL; ++} ++ ++static int sigintFlag; ++static void ++bdm_signal_handler (int s) ++{ ++ sigintFlag++; ++} ++ ++/* ++ * 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) ++{ ++ unsigned long csr; ++ int bdm_stat; ++ int detach = 0; ++ int ui_count = 0; ++ void (*ofunc) (); ++ ++ hit_watchpoint = 0; ++ if (bdm_gdb_no_wait) { ++ status->kind = TARGET_WAITKIND_STOPPED; ++ status->value.sig = TARGET_SIGNAL_GRANT; ++ return null_ptid; ++ } ++ ++ status->kind = TARGET_WAITKIND_EXITED; ++ status->value.integer = 0; ++ ++ /* ++ * Catch SIGINT signals ++ */ ++ sigintFlag = 0; ++ ofunc = signal (SIGINT, bdm_signal_handler); ++ ++ /* ++ * A work around a problem with the 5206e processor. Not sure ++ * what the issue is. It could be the processor. ++ */ ++ if (cpu_type == BDM_COLDFIRE && cf_debug_ver == 0) ++ nap (10000); ++ ++ /* ++ * Wait here till the target requires service ++ */ ++ while ((bdm_stat = bdm_get_status ()) == 0) { ++ ui_count = 0; ++ while (ui_count++ < 6) { ++ nap (50000); ++ ++ /* N.B. The UI may destroy our world (for instance by calling ++ remote_stop,) in which case we want to get out of here as ++ quickly as possible. It is not safe to touch scb, since ++ someone else might have freed it. The ui_loop_hook signals that ++ we should exit by returning 1. */ ++ ++ if (ui_loop_hook) ++ detach = ui_loop_hook (0); ++ ++ if (detach || sigintFlag) ++ bdm_stop_chip (); ++ } ++ } ++ ++ signal (SIGINT, ofunc); ++ ++ /* ++ * Determine why the target stopped ++ */ ++ 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: ++ case BDM_TARGETHALT: ++ case BDM_TARGETSTOPPED | BDM_TARGETHALT: ++ if (sigintFlag) { ++ status->kind = TARGET_WAITKIND_STOPPED; ++ status->value.sig = TARGET_SIGNAL_TSTP; ++ } ++ else { ++ if (cpu_type == BDM_CPU32) { ++ if (!haveAtemp ++ && (bdmReadSystemRegister (BDM_REG_ATEMP, &atemp) < 0)) ++ bdm_report_error (); ++ switch (atemp & 0xffff) { ++ case 0xffff: /* double bus fault */ ++ status->kind = TARGET_WAITKIND_STOPPED; ++ status->value.sig = TARGET_SIGNAL_BUS; ++ break; ++ case 0x0: /* HW bkpt */ ++ status->kind = TARGET_WAITKIND_STOPPED; ++ status->value.sig = TARGET_SIGNAL_TRAP; ++ break; ++ case 0x1: /* background mode */ ++ analyze_exception (status); ++ break; ++ default: ++ printf_filtered ("bdm_wait: Unknown atemp:%#lx\n", atemp); ++ status->kind = TARGET_WAITKIND_STOPPED; ++ status->value.sig = TARGET_SIGNAL_GRANT; ++ } ++ } ++ else { ++ if (bdmReadSystemRegister (BDM_REG_CSR, &csr) < 0) ++ bdm_report_error (); ++ if (csr & 0x08000000) { /* double bus fault */ ++ status->kind = TARGET_WAITKIND_STOPPED; ++ status->value.sig = TARGET_SIGNAL_BUS; ++ } ++ else { ++ if (csr & 0x04000000) { /* hardware trigger */ ++ hit_watchpoint = 1; ++ status->kind = TARGET_WAITKIND_STOPPED; ++ status->value.sig = TARGET_SIGNAL_TRAP; ++ } ++ else { ++ if (csr & 0x01000000) { /* -BKPT signal */ ++ status->kind = TARGET_WAITKIND_STOPPED; ++ status->value.sig = TARGET_SIGNAL_TRAP; ++ } ++ else { ++ if (csr & 0x02000000) { /* HALT/software bkpt */ ++ analyze_exception (status); ++ } ++ else { ++ printf_filtered ("bdm_wait: Unknown csr:%#lx", ++ csr); ++ status->kind = TARGET_WAITKIND_STOPPED; ++ status->value.sig = TARGET_SIGNAL_GRANT; ++ } ++ } ++ } ++ } ++ } ++ } ++ break; ++ default: ++ printf_filtered ("bdm_wait: Unknown BDM status: %#x", bdm_stat); ++ break; ++ } ++ haveAtemp = 0; ++ return null_ptid; ++} ++ ++/* ++ * The following routines handle the Coldfire hardware breakpoints. Only one ++ * breakpoint supported so far, and it can be either a PC breakpoint or an ++ * address watchpoint. Unfortunately, the TARGET_CAN_USE_HARDWARE_WATCHPOINT ++ * macro only allows for bounds checking within one of the two types and not ++ * limits that cover the sum of both, so extra work is needed. ++ * ++ * (Actually, very few processors seem to have much support for that routine ++ * at all.) ++ * ++ * As a result, the way this is handled is that the can_use routine will allow ++ * the first breakpoint of either type to be added. Any further checking so ++ * that only one of the two can be used is done later when GDB actually tries ++ * to create the breakpoints, usually when the processor is restarted. ++ * ++ * We keep a local copy of the breakpoints list becasue the chain that GDB ++ * keeps isn't exported globally. ++ * ++ * While things could be simplified with only one breakpoint present, setting ++ * up more general routines allows for later expansion if newer versions of ++ * the ColdFire chip support more breakpoints at once. ++ * ++ * Also, the ColdFire supports things like multi-level triggers and triggers ++ * based on the data bus instead of just the address bus. The GDB commands ++ * don't allow for access to this, but much of it isn't necessary anyway, ++ * as GDB has its own method of handling 'breakpoint conditions' that is ++ * sufficient for most tasks. ++ */ ++ ++#define TDR_TRC_DDATA 0x00000000 ++#define TDR_TRC_HALT 0x40000000 ++#define TDR_TRC_DINT 0x80000000 ++#define TDR_L2_EBL 0x20000000 ++#define TDR_L2_ALL 0x1FFF0000 ++#define TDR_L2_EDLW 0x10000000 ++#define TDR_L2_EDWL 0x08000000 ++#define TDR_L2_EDWU 0x04000000 ++#define TDR_L2_EDLL 0x02000000 ++#define TDR_L2_EDLM 0x01000000 ++#define TDR_L2_EDUM 0x00800000 ++#define TDR_L2_EDUU 0x00400000 ++#define TDR_L2_DI 0x00200000 ++#define TDR_L2_EAI 0x00100000 ++#define TDR_L2_EAR 0x00080000 ++#define TDR_L2_EAL 0x00040000 ++#define TDR_L2_EPC 0x00020000 ++#define TDR_L2_PCI 0x00010000 ++#define TDR_L1_EBL 0x00002000 ++#define TDR_L1_ALL 0x00001FFF ++#define TDR_L1_EDLW 0x00001000 ++#define TDR_L1_EDWL 0x00000800 ++#define TDR_L1_EDWU 0x00000400 ++#define TDR_L1_EDLL 0x00000200 ++#define TDR_L1_EDLM 0x00000100 ++#define TDR_L1_EDUM 0x00000080 ++#define TDR_L1_EDUU 0x00000040 ++#define TDR_L1_DI 0x00000020 ++#define TDR_L1_EAI 0x00000010 ++#define TDR_L1_EAR 0x00000008 ++#define TDR_L1_EAL 0x00000004 ++#define TDR_L1_EPC 0x00000002 ++#define TDR_L1_PCI 0x00000001 ++ ++struct cf_break { ++ enum target_hw_bp_type type; ++ CORE_ADDR addr; ++ int len; ++}; ++ ++#define CF_BREAKPOINT_MAX 1 ++ ++static struct cf_break cf_breakpoints[CF_BREAKPOINT_MAX]; ++static int cf_breakpoint_count; ++ ++static int ++cf_init_watchpoints(void) ++{ ++ if (cpu_type != BDM_COLDFIRE) { ++ return(-1); ++ } ++ cf_breakpoint_count = 0; ++ if (bdmWriteSystemRegister (BDM_REG_TDR, TDR_TRC_HALT) < 0) ++ bdm_report_error (); ++ return(0); ++} ++ ++int ++cf_stopped_by_watchpoint(void) ++{ ++ return hit_watchpoint; ++} ++ ++int ++cf_can_use_watchpoint(type, cnt, ot) ++ enum target_hw_bp_type type; ++ int cnt; ++ int ot; ++{ ++ unsigned long tdr; ++ ++ if (cpu_type != BDM_COLDFIRE) { ++ return(0); ++ } ++ ++ if (type == bp_hardware_breakpoint || type == bp_read_watchpoint || ++ type == bp_hardware_watchpoint || type == bp_access_watchpoint) { ++ if (cnt <= 1) { ++ return(1); ++ } ++ } ++ ++ return(-1); ++} ++ ++int ++cf_insert_hw_breakpoint(addr, shadow) ++ CORE_ADDR addr; ++ char *shadow; ++{ ++ unsigned long tdr; ++ ++ if (cpu_type != BDM_COLDFIRE) { ++ return(-1); ++ } ++ ++ if (cf_breakpoint_count < CF_BREAKPOINT_MAX) { ++ cf_breakpoints[cf_breakpoint_count].type = hw_execute; ++ cf_breakpoints[cf_breakpoint_count].addr = addr; ++ cf_breakpoints[cf_breakpoint_count++].len = 2; ++ ++ if (bdmReadSystemRegister (BDM_REG_TDR, &tdr) < 0) ++ bdm_report_error (); ++ tdr = ((tdr & ~TDR_L1_ALL) | (TDR_L1_EBL|TDR_L1_EPC)); ++ if (bdmWriteSystemRegister (BDM_REG_PBR, addr) < 0) ++ bdm_report_error (); ++ if (bdmWriteSystemRegister (BDM_REG_PBMR, 0) < 0) ++ bdm_report_error (); ++ if (bdmWriteSystemRegister (BDM_REG_TDR, tdr) < 0) ++ bdm_report_error (); ++ if (bdmDebugLevel) ++ printf_filtered ("Insert PC Breakpoint @0x%08lx\n", addr); ++ } ++ else { ++ return(-1); ++ } ++ return(0); ++} ++ ++static int ++cf_check_breakpoint(type, addr, len) ++ enum target_hw_bp_type type; ++ CORE_ADDR addr; ++ int len; ++{ ++ int i; ++ ++ for (i = 0; i < cf_breakpoint_count; i++) { ++ if (cf_breakpoints[i].type == type && ++ cf_breakpoints[i].addr == addr && ++ cf_breakpoints[i].len == len) { ++ for (; i < CF_BREAKPOINT_MAX-1; i++) { ++ cf_breakpoints[i] = cf_breakpoints[i+1]; ++ } ++ cf_breakpoint_count--; ++ return(1); ++ } ++ } ++ return(0); ++} ++ ++int ++cf_remove_hw_breakpoint(addr, shadow) ++ CORE_ADDR addr; ++ char *shadow; ++{ ++ unsigned long tdr; ++ unsigned long csr; ++ ++ if (cpu_type != BDM_COLDFIRE) { ++ return(-1); ++ } ++ ++ if (cf_check_breakpoint(hw_execute, addr, 2)) { ++ if (bdmReadSystemRegister (BDM_REG_TDR, &tdr) < 0) ++ bdm_report_error (); ++ tdr &= ~TDR_L1_EPC; ++ if ((tdr & TDR_L1_ALL) == 0) { ++ tdr &= ~TDR_L1_EBL; ++ } ++ if (bdmWriteSystemRegister (BDM_REG_TDR, tdr) < 0) ++ bdm_report_error (); ++ if (bdmDebugLevel) ++ printf_filtered ("Remove PC Breakpoint @0x%08lx\n", addr); ++ } ++ else { ++ return(-1); ++ } ++ return(0); ++} ++ ++#define AATR_READONLY 0x7F85 ++#define AATR_WRITEONLY 0x7F05 ++#define AATR_READWRITE 0xFF05 ++ ++int ++cf_insert_watchpoint(addr, len, type) ++ CORE_ADDR addr; ++ int len; ++ enum target_hw_bp_type type; ++{ ++ unsigned long tdr; ++ ++ if (cpu_type != BDM_COLDFIRE) { ++ return(-1); ++ } ++ ++ if (cf_breakpoint_count < CF_BREAKPOINT_MAX) { ++ cf_breakpoints[cf_breakpoint_count].type = type; ++ cf_breakpoints[cf_breakpoint_count].addr = addr; ++ cf_breakpoints[cf_breakpoint_count++].len = len; ++ ++ if (bdmReadSystemRegister (BDM_REG_TDR, &tdr) < 0) ++ bdm_report_error (); ++ tdr = ((tdr & ~TDR_L1_ALL) | (TDR_L1_EBL|TDR_L1_EAR)); ++ if (bdmWriteSystemRegister (BDM_REG_ABLR, addr) < 0) ++ bdm_report_error (); ++ if (bdmWriteSystemRegister (BDM_REG_ABHR, addr+len-1) < 0) ++ bdm_report_error (); ++ if (type == hw_read) { ++ if (bdmWriteSystemRegister (BDM_REG_AATR, AATR_READONLY) < 0) ++ bdm_report_error (); ++ if (bdmDebugLevel) ++ printf_filtered ("Insert read Watchpoint @0x%08lx-0x%08lx\n", ++ addr, addr+len-1); ++ } ++ else if (type == hw_write) { ++ if (bdmWriteSystemRegister (BDM_REG_AATR, AATR_WRITEONLY) < 0) ++ bdm_report_error (); ++ if (bdmDebugLevel) ++ printf_filtered ("Insert write Watchpoint @0x%08x-0x%08x\n", ++ addr, addr+len-1); ++ } ++ else { ++ if (bdmWriteSystemRegister (BDM_REG_AATR, AATR_READWRITE) < 0) ++ bdm_report_error (); ++ if (bdmDebugLevel) ++ printf_filtered ("Insert access Watchpoint @0x%08lx-0x%08lx\n", ++ addr, addr+len-1); ++ } ++ if (bdmWriteSystemRegister (BDM_REG_TDR, tdr) < 0) ++ bdm_report_error (); ++ } ++ else { ++ return(-1); ++ } ++ return(0); ++} ++ ++int ++cf_remove_watchpoint(addr, len, type) ++ CORE_ADDR addr; ++ int len; ++ enum target_hw_bp_type type; ++{ ++ unsigned long tdr; ++ unsigned long csr; ++ ++ if (cpu_type != BDM_COLDFIRE) { ++ return(-1); ++ } ++ ++ if (cf_check_breakpoint(type, addr, len)) { ++ if (bdmReadSystemRegister (BDM_REG_TDR, &tdr) < 0) ++ bdm_report_error (); ++ tdr &= ~TDR_L1_EAR; ++ if ((tdr & TDR_L1_ALL) == 0) { ++ tdr &= ~TDR_L1_EBL; ++ } ++ if (bdmWriteSystemRegister (BDM_REG_TDR, tdr) < 0) ++ bdm_report_error (); ++ if (bdmDebugLevel) ++ printf_filtered ("Remove %s Watchpoint @0x%08lx-0x%08lx\n", ++ (type == hw_read) ? "read" : ++ ((type == hw_write) ? "write" : "access"), ++ addr, addr+len-1); ++ } ++ else { ++ return(-1); ++ } ++ return(0); ++} ++ ++int ++cf_stopped_data_address() ++{ ++ unsigned long tdr; ++ unsigned long ablr; ++ ++ if (cpu_type != BDM_COLDFIRE) { ++ return(-1); ++ } ++ ++ if (bdmReadSystemRegister (BDM_REG_TDR, &tdr) < 0) ++ bdm_report_error (); ++ if (bdmReadSystemRegister (BDM_REG_ABLR, &ablr) < 0) ++ bdm_report_error (); ++ ++ if (tdr & TDR_L1_EAR) { ++ return(ablr); ++ } ++ return(0); ++} ++ ++/* 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; ++ unsigned long entry_pt; ++ ++ clear_proceed_status (); ++ init_wait_for_inferior (); ++ if (*args) { ++ prg_file = args; ++ } ++ else { ++ prg_file = execfile; ++ } ++ if (!(prg_file) && !(bdm_prog_loaded)) ++ error ("No program specified to run\n"); ++ else ++ { ++ if (!bdm_no_load) { ++ if (bdm_prog_loaded) ++ printf_filtered ("Note: `%s' has already been loaded.\n", ++ bdm_prog_loaded); ++ if (query ("Do you want to download `%s'?", prg_file)) ++ bdm_load (prg_file, 0); ++ if (bdmReadSystemRegister (BDM_REG_RPC, &entry_pt) < 0) ++ bdm_report_error (); ++ } ++ proceed (entry_pt, TARGET_SIGNAL_DEFAULT, 0); ++ } ++/* inferior_pid = 1; */ ++} ++ ++/* ++ * Fetch register REGNO, or all user registers if REGNO is -1. ++ */ ++static void ++bdm_fetch_register (int regno) ++{ ++ unsigned long l; ++ char cbuf[4]; ++ int ret; ++ ++ if (regno < 0) { ++ for (regno = 0 ; regno < NUM_REGS ; regno++) ++ bdm_fetch_register (regno); ++ } ++ else { ++ /* ++ * When the target is running the ++ * cpu registers can not be accessed. ++ */ ++ if (bdm_gdb_no_wait && (bdm_get_status () == 0)) { ++ l = 0; ++ ret = 0; ++ } ++ else { ++ if (regno < 16) { ++ ret = bdmReadRegister (regno, &l); ++ } ++ else { ++ if ((regno - 16) < (sizeof (reg_to_dev_num) / sizeof (int))) { ++ ret = bdmReadSystemRegister (reg_to_dev_num[regno - 16], &l); ++ } ++ else { ++ error ("Bad register number (%d)", regno); ++ return; ++ } ++ } ++ } ++ if (ret < 0) ++ bdm_report_error (); ++ cbuf[0] = l >> 24; ++ cbuf[1] = l >> 16; ++ cbuf[2] = l >> 8; ++ cbuf[3] = l; ++ supply_register (regno, cbuf); ++ } ++} ++ ++void ++bdm_prepare_to_store (void) ++{ ++ /* Do nothing, since we can store individual regs */ ++} ++ ++/* ++ * Store register REGNO, or all user registers if REGNO == -1. ++ */ ++void ++bdm_store_register (int regno) ++{ ++ unsigned long l; ++ int ret; ++ ++ if (bdm_gdb_no_wait && (bdm_get_status () == 0)) ++ return; ++ ++ if (regno == -1) { ++ for (regno = 0 ; regno < NUM_REGS ; regno++) ++ bdm_store_register (regno); ++ } ++ else { ++ l = read_register (regno); ++ if (regno < 16) { ++ ret = bdmWriteRegister (regno, l); ++ } ++ else { ++ if ((regno - 16) < (sizeof (reg_to_dev_num) / sizeof (int))) { ++ ret = bdmWriteSystemRegister (reg_to_dev_num[regno - 16], l); ++ } ++ else { ++ error ("Bad register number (%d)", regno); ++ return; ++ } ++ } ++ if (ret < 0) ++ bdm_report_error (); ++ } ++} ++ ++/* ++ * Transfer memory contents between target and host ++ */ ++static int ++bdm_xfer_inferior_memory (CORE_ADDR memaddr, char *myaddr, ++ int len, int write, ++ struct mem_attrib *attrib, ++ struct target_ops *t) ++{ ++ int ret; ++ ++ if (write) ++ ret = bdmWriteMemory (memaddr, myaddr, len); ++ else ++ ret = bdmReadMemory (memaddr, myaddr, len); ++ if (ret < 0) ++ bdm_report_error (); ++ return len; ++} ++ ++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"); ++ } ++} ++ ++/* ++ * Load a file. ++ */ ++static void ++bdm_load (char *args, int from_tty) ++{ ++ char *p; ++ ++ if (bdm_prog_loaded) { ++ free (bdm_prog_loaded); ++ bdm_prog_loaded = NULL; ++ } ++ if (!args) { ++ error ( ++ "The bdmload command must include the filename to load.\n" ++ "You may want to use 'run', which uses the file given\n" ++ "on the command line when gdb was invoked."); ++ } ++ if ((bdm_get_status () & BDM_TARGETSTOPPED) == 0) ++ bdm_stop_chip (); ++ ++ /* strip off additional (unwanted) arguments after file name */ ++ for (p = args; (*p != '\0') && (!isspace (*p)); p++) ; ++ *p = '\0'; ++ ++ if (loadExecutable (args) < 0) ++ error ("%s", downloadErrorString); ++ bdm_prog_loaded = savestring (args, strlen (args)); ++} ++ ++/* ++ * Toggle the no load variable. ++ */ ++static void ++bdm_toggle_no_load (char *args, int from_tty) ++{ ++ if (bdm_no_load) { ++ bdm_no_load = 0; ++ printf_filtered ("Image not loaded on run\n"); ++ } ++ else { ++ bdm_no_load = 1; ++ printf_filtered ("Image loaded on run\n"); ++ } ++} ++ ++/* ++ * Select a CPU32 processor register set. ++ */ ++static void ++bdm_select_cpu32 (char *args, int from_tty) ++{ ++ bdm_reg_names = cpu32_reg_names; ++} ++ ++struct target_ops bdm_ops; ++ ++static void ++init_bdm_ops(void) ++{ ++ bdm_ops.to_shortname = "bdm"; ++ bdm_ops.to_longname = "CPU32 and Coldfire Background Debug Mode Interface for downloading and remote debugging"; ++ bdm_ops.to_doc = "Uses the Public Domain Background Debug Mode Interface connected to the\n" ++"BDM-port of the CPU32 or Coldfire based microcontroller and to a parallel port\n" ++"of the PC.\n" ++"Usage: target bdm \n" ++"where is the BDM character special file (e.g. /dev/bdm0)."; ++ bdm_ops.to_open = bdm_open; ++ bdm_ops.to_close = bdm_close; ++ bdm_ops.to_detach = bdm_detach; ++ bdm_ops.to_resume = bdm_resume; ++ bdm_ops.to_wait = bdm_wait; ++ 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 = memory_insert_breakpoint; ++ bdm_ops.to_remove_breakpoint = memory_remove_breakpoint; ++ bdm_ops.to_kill = bdm_kill; ++ bdm_ops.to_load = bdm_load; ++ bdm_ops.to_stop = bdm_stop_chip; ++ bdm_ops.to_create_inferior = bdm_create_inferior; ++ bdm_ops.to_mourn_inferior = generic_mourn_inferior; ++ bdm_ops.to_can_run = bdm_can_run; ++ bdm_ops.to_stratum = process_stratum; ++ 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; ++ bdm_ops.to_magic = OPS_MAGIC; ++}; ++ ++void ++_initialize_remote_bdmcf (void) ++{ ++ init_bdm_ops (); ++ add_com ("bdm_reset", class_obscure, ++ (void (*)(char *, int))bdm_reset, ++ "Reset target and enter BDM mode."); ++ add_com ("bdm_release", class_obscure, ++ (void (*)(char *, int))bdm_release_chip, ++ "Reset target without BDM-mode."); ++ add_com ("bdm_status", class_obscure, ++ (void (*)(char *, int))bdm_get_status_interactive, ++ "Show status of bdm interface\n"); ++ add_com ("bdm_setdelay", class_obscure, ++ bdm_setdelay_interactive, ++ "set delay for download"); ++ add_com ("bdm_setdebug", class_obscure, ++ bdm_setdebug_interactive, ++ "enable/disable BDM diagnostic messages"); ++ add_com ("bdm_setdriverdebug", class_obscure, ++ bdm_setdriverdebug_interactive, ++ "enable/disable BDM driver diagnostic messages"); ++ add_com ("bdm_no_wait", class_obscure, ++ bdm_set_no_wait, ++ "Cause GDB to not wait for the target to stop when running."); ++ add_com ("bdm_wait", class_obscure, ++ bdm_set_wait, ++ "Cause GDB to wait for the target to stop when running."); ++ add_com ("bdm_stop", class_obscure, ++ bdm_issue_stop, ++ "Stop the target if running."); ++ add_com ("bdm-select-cpu32", class_obscure, ++ bdm_select_cpu32, ++ "Selects the CPU32 register set rather than the default CPU32+."); ++ add_com ("bdm-no-load", class_obscure, ++ bdm_toggle_no_load, ++ "Toggle the loading of the program to memory when asked to run."); ++ ++ add_target (&bdm_ops); ++} diff --git a/gdb/patches/gdb-5.3-bdm-m68k.patch b/gdb/patches/gdb-5.3-bdm-m68k.patch new file mode 100644 index 0000000..c158a99 --- /dev/null +++ b/gdb/patches/gdb-5.3-bdm-m68k.patch @@ -0,0 +1,2043 @@ +diff -Nru insight-5.3.orig/gdb/Makefile.in insight-5.3/gdb/Makefile.in +--- insight-5.3.orig/gdb/Makefile.in 2002-11-25 23:05:38.000000000 +0100 ++++ insight-5.3/gdb/Makefile.in 2003-06-14 03:23:45.000000000 +0200 +@@ -2009,6 +2009,8 @@ + $(serial_h) $(regcache_h) + remote-hms.o: remote-hms.c $(defs_h) $(gdbcore_h) $(target_h) $(monitor_h) \ + $(serial_h) $(regcache_h) ++remote-m68k-bdm.o: remote-m68k-bdm.c $(bfd_h) $(wait_h) $(defs_h) $(inferior_h) \ ++ $(gdbcore_h) $(target_h) + remote-mips.o: remote-mips.c $(defs_h) $(inferior_h) $(bfd_h) $(symfile_h) \ + $(gdbcmd_h) $(gdbcore_h) $(serial_h) $(target_h) $(remote_utils_h) \ + $(gdb_string_h) $(gdb_stat_h) $(regcache_h) +diff -Nru insight-5.3.orig/gdb/config/m68k/bdm.mt insight-5.3/gdb/config/m68k/bdm.mt +--- insight-5.3.orig/gdb/config/m68k/bdm.mt 1970-01-01 01:00:00.000000000 +0100 ++++ insight-5.3/gdb/config/m68k/bdm.mt 2003-06-14 03:23:46.000000000 +0200 +@@ -0,0 +1,5 @@ ++# Target: m68k bdm interface for the CPU32 and Coldfire processors. ++# ++TM_CLIBS= -L$(prefix)/lib -lBDM ++TDEPFILES= m68k-tdep.o remote-m68k-bdm.o ++TM_FILE= tm-bdm.h +diff -Nru insight-5.3.orig/gdb/config/m68k/tm-bdm.h insight-5.3/gdb/config/m68k/tm-bdm.h +--- insight-5.3.orig/gdb/config/m68k/tm-bdm.h 1970-01-01 01:00:00.000000000 +0100 ++++ insight-5.3/gdb/config/m68k/tm-bdm.h 2003-06-14 03:23:46.000000000 +0200 +@@ -0,0 +1,120 @@ ++/* ++ * Target machine description for Coldfire BDM (Moto 5200) ++ * Copyright (C) 1995 W. Eric Norum ++ * Copyright (C) 1998 Chris Johns (ccj@acm.org) ++ * ++ * Based on: ++ * 1. `A Background Debug Mode Driver Package for Motorola's ++ * 16- and 32-Bit Microcontrollers', Scott Howard, Motorola ++ * Canada, 1993. ++ * 2. `Linux device driver for public domain BDM Interface', ++ * M. Schraut, Technische Universitaet Muenchen, Lehrstuhl ++ * fuer Prozessrechner, 1995. ++ * 3. BDM support for gdb by W. Eric Norum ++ * Saskatchewan Accelerator Laboratory ++ * University of Saskatchewan ++ * 107 North Road ++ * Saskatoon, Saskatchewan, CANADA ++ * S7N 5C6 ++ * ++ * 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. ++ */ ++ ++/* ++ * Coldfire does it for us if we use PCC to get the PC ++ */ ++#define DECR_PC_AFTER_BREAK 0 ++ ++/* ++ * We have to control this directly as the CPU32 and Coldfire have different ++ * breakpoint opcodes. ++ */ ++#define BREAKPOINT_FROM_PC m68k_bdm_breakpoint_from_pc ++ ++/* ++ * Include the generic stuff ++ */ ++#include "m68k/tm-m68k.h" ++ ++/* ++ * Override some of the generic definitions ++ */ ++ ++/* ++ * For uCLinux we need to detect we have a subroutine call ++ * which is really a trap #0. This should be caught by the ++ * the IN_SIGTRAMP handler defined above, but incase it is ++ * not we should try and catch it here. ++ */ ++ ++extern CORE_ADDR m68k_bdm_saved_pc_after_call PARAMS ((struct frame_info *)); ++ ++#undef SAVED_PC_AFTER_CALL ++#define SAVED_PC_AFTER_CALL(frame) \ ++ m68k_bdm_saved_pc_after_call (frame) ++ ++/* ++ * we need 40 registers for the CPU32 and Coldfire: ++ * 8 data registers ++ * 8 address registers ++ * 2 other registers (PC, PS) ++ * 22 special registers (actual set depends on architecture) ++ * 0 floating point registers ++ */ ++#undef NUM_REGS ++#undef REGISTER_BYTES ++#define NUM_REGS 40 ++#define REGISTER_BYTES (16*4 + 2*4 + 22*4) ++ ++#undef REGISTER_NAMES ++#define REGISTER_NAME(i) bdm_register_name(i) ++extern const char *bdm_register_name(int i); ++ ++#undef FP0_REGNUM ++#undef FPC_REGNUM ++#undef FPS_REGNUM ++#undef FPI_REGNUM ++#define FP0_REGNUM 40 /* Floating point register 0 */ ++#define FPC_REGNUM FP0_REGNUM + 8 /* 68881 control register */ ++#define FPS_REGNUM FPC_REGNUM + 1 /* 68881 status register */ ++#define FPI_REGNUM FPS_REGNUM + 1 /* 68881 iaddr register */ ++ ++/* ++ * The other definitions and macros don't need to be changed: ++ * a) The Coldfire has no floating point registers ++ * b) The REGISTER_BYTES_OK macro isn't used ++ */ ++ ++#define TARGET_HAS_HARDWARE_WATCHPOINTS ++ ++/* We need to remove watchpoints when stepping, else we hit them again! */ ++ ++#define HAVE_NONSTEPPABLE_WATCHPOINT ++ ++#define STOPPED_BY_WATCHPOINT(w) cf_stopped_by_watchpoint () ++ ++/* Use these macros for watchpoint insertion/deletion. */ ++/* type can be 0: write watch, 1: read watch, 2: access watch (read/write) */ ++ ++#define TARGET_CAN_USE_HARDWARE_WATCHPOINT(type, cnt, ot) \ ++ cf_can_use_watchpoint (type, cnt, ot) ++ ++#define target_insert_watchpoint(addr, len, type) cf_insert_watchpoint (addr, len, type) ++#define target_remove_watchpoint(addr, len, type) cf_remove_watchpoint (addr, len, type) ++#define target_insert_hw_breakpoint(addr, shadow) cf_insert_hw_breakpoint (addr, shadow) ++#define target_remove_hw_breakpoint(addr, shadow) cf_remove_hw_breakpoint (addr, shadow) ++#define target_stopped_data_address() cf_stopped_data_address () +diff -Nru insight-5.3.orig/gdb/configure.tgt insight-5.3/gdb/configure.tgt +--- insight-5.3.orig/gdb/configure.tgt 2002-10-20 14:14:39.000000000 +0200 ++++ insight-5.3/gdb/configure.tgt 2003-06-14 03:23:46.000000000 +0200 +@@ -140,6 +140,8 @@ + m68000-*-sunos3*) gdb_target=sun2os3 ;; + m68000-*-sunos4*) gdb_target=sun2os4 ;; + ++m68*-bdm-*) gdb_target=bdm ;; ++ + # OBSOLETE m68*-apollo*-bsd*) gdb_target=apollo68b ;; + m68*-bull-sysv*) gdb_target=dpx2 ;; + # OBSOLETE m68*-hp-bsd*) gdb_target=hp300bsd ;; +diff -Nru insight-5.3.orig/gdb/doc/gdb.texinfo insight-5.3/gdb/doc/gdb.texinfo +--- insight-5.3.orig/gdb/doc/gdb.texinfo 2002-09-27 02:21:38.000000000 +0200 ++++ insight-5.3/gdb/doc/gdb.texinfo 2003-06-14 04:11:17.000000000 +0200 +@@ -11326,6 +11326,7 @@ + * i960:: Intel i960 + * M32R/D:: Mitsubishi M32R/D + * M68K:: Motorola M68K ++* Motorola BDM:: Motorola M68K/Coldfire Background Debug Mode + @c OBSOLETE * M88K:: Motorola M88K + * MIPS Embedded:: MIPS Embedded + * PA:: HP PA Embedded +@@ -11722,6 +11723,10 @@ + @item target abug @var{dev} + ABug ROM monitor for M68K. + ++@kindex target bdm ++Background Debug Mode interface to Motorola 68k/Coldfire machine. ++@xref{Motorola BDM, ,@value{GDBN} and Motorola 68k/Coldfire BDM}. ++ + @kindex target cpu32bug + @item target cpu32bug @var{dev} + CPU32BUG monitor, running on a CPU32 (M68K) board. +@@ -11761,6 +11766,101 @@ + + @end table + ++ ++@node Motorola BDM ++@subsection @value{GDBN} and Motorola BDM ++ ++@cindex BDM ++@cindex CPU32 ++@cindex Coldfire ++Background Debug Mode (@dfn{BDM}) provides a full set of debug options ++including the ability to: ++@itemize @bullet ++@item Insert breakpoints ++@item Single-step ++@item Display register contents ++@item Display memory contents ++@item Modify register contents ++@item Modify memory contents ++@end itemize ++ ++A small interface circuit connects the BDM interface port on the ++target machine to a parallel printer port on the debugging host. ++A target system can be configured and a program downloaded and ++executed with no bootstrap memory on the target machine and no other ++connection between the debugging host and the target machine. ++ ++The @code{target} command tells @value{GDBN} ++to debug a program running on a target machine ++@xref{Target Commands, ,Commands for managing targets}. ++For example, the following command tells @value{GDBN} to use a BDM ++interface connected to a ColdFire processor and the @code{LPT0} parallel port: ++@example ++target bdm /dev/bdmcf0 ++@end example ++ ++Do not attempt to use the parallel port for any other purpose while ++@value{GDBN} is using it to control a BDM target. ++ ++Once the BDM target has been selected a few other commands become ++available: ++ ++@table @code ++@item bdm_reset ++@kindex bdm_reset ++Reset the target machine and enable BDM operation in the target. ++ ++@item bdm_restart ++@kindex bdm_restart ++Reset the target machine and disable BDM operation in the target. ++This command is useful only if the target machine has some kind of ++bootstrap memory installed. ++ ++@item bdm_status ++@kindex bdm_status ++Print the status of the target machine and the BDM interface. ++ ++@item bdm_setdelay @var{N} ++@kindex bdm_setdelay ++Some BDM interface circuits can not handle high-speed data transfer. ++This command lets you insert a delay between each BDM clock. ++The larger the value of @var{N}, the longer the delay. ++On most machines the default delay of @var{0} should work just fine. ++ ++@item bdm_setdebug @var{N} ++@kindex bdm_setdebug ++Setting the level (@var{N}) to a non-zero value turns on ++debugging messages in the BDM support library. ++ ++@item bdm_setdriverdebug @var{N} ++@kindex bdm_setdriverdebug ++Setting the level (@var{N}) to a non-zero value turns on ++debugging messages in the BDM device driver. ++ ++@end table ++ ++The registers which can be displayed and modified are: ++@itemize @bullet ++@item The data registers: @code{$d0}-@code{$d7} ++@item The address registers: @code{$a0}-@code{$a5}, @code{$fp}, @code{$sp} ++@item The program counter: @code{$pc} ++@item The status register: @code{$ps} ++@item The program counter at the beginning of the most recently executed ++instruction: @code{$pcc} ++@item The user stack pointer: @code{$usp} ++@item The supervisor stack pointer: @code{$ssp} ++@item The source function code register: @code{$sfc} ++@item The destinaton function code register: @code{$dfc} ++@item The vector base register: @code{$vbr} ++@item The fault address register: @code{$far} ++@item The BDM temporary register: @code{$atemp} ++@item The module base address register: @code{$mbar} ++@end itemize ++ ++Target processor interrupts are disabled during single-step (step, next, ++stepi, nexti) operations. ++ ++ + @c OBSOLETE @node M88K + @c OBSOLETE @subsection M88K + @c OBSOLETE +diff -Nru insight-5.3.orig/gdb/remote-m68k-bdm.c insight-5.3/gdb/remote-m68k-bdm.c +--- insight-5.3.orig/gdb/remote-m68k-bdm.c 1970-01-01 01:00:00.000000000 +0100 ++++ insight-5.3/gdb/remote-m68k-bdm.c 2003-06-14 03:23:46.000000000 +0200 +@@ -0,0 +1,1743 @@ ++/* ++ * Motorola Background Debug Mode Target ++ * Copyright (C) 1995 W. Eric Norum ++ * Copyright (C) 1998 Chris Johns (ccj@acm.org) ++ * Copyright (C) 2000 Bryan Feir (bryan@sgl.crestech.ca) ++ * ++ * Based on: ++ * 1. `A Background Debug Mode Driver Package for Motorola's ++ * 16- and 32-Bit Microcontrollers', Scott Howard, Motorola ++ * Canada, 1993. ++ * 2. `Linux device driver for public domain BDM Interface', ++ * M. Schraut, Technische Universitaet Muenchen, Lehrstuhl ++ * fuer Prozessrechner, 1995. ++ * 3. BDM support for gdb by W. Eric Norum ++ * Saskatchewan Accelerator Laboratory ++ * University of Saskatchewan ++ * 107 North Road ++ * Saskatoon, Saskatchewan, CANADA ++ * S7N 5C6 ++ * 4. Coldfire support added by C Johns. ++ * 5. Hardware breakpoint support added by B Feir. ++ * ++ * 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. ++ * ++ * W. Eric Norum ++ * Saskatchewan Accelerator Laboratory ++ * University of Saskatchewan ++ * 107 North Road ++ * Saskatoon, Saskatchewan, CANADA ++ * S7N 5C6 ++ * ++ * eric@skatter.usask.ca ++ * ++ * Coldfire support by: ++ * Chris Johns ++ * Objective Design Systems ++ * 35 Cairo Street ++ * Cammeray, Sydney, 2062, Australia ++ * ++ * ccj@acm.org ++ * ++ * Coldfire hardware breakpoint support by: ++ * Bryan Feir ++ * CRESTech (Centre for Research in Earth and Space Technology) ++ * 4850 Keele Street, 1st floor ++ * Toronto, Ontario, CANADA M6E 3E5 ++ * ++ * bryan@sgl.crestech.ca ++ */ ++ ++/* ++ * $Revision: 1.1 $ $Date: 2004/03/28 23:13:10 $ $Author: codewiz $ ++ */ ++ ++#include "defs.h" ++#include "gdbcore.h" ++#include "target.h" ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "gdbcmd.h" ++#include "command.h" ++#include "inferior.h" ++#include "value.h" ++#include "breakpoint.h" ++#include "BDMlib.h" ++ ++extern struct target_ops bdm_ops; /* Forward declaration */ ++ ++/* ++ * The name of the BDM driver special file ++ */ ++static char *dev_name; ++static int cpu_type; ++ ++/* ++ * The different register names for the processors. ++ */ ++static const char *cpu32plus_reg_names[NUM_REGS] = { ++ "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", ++ NULL, NULL, NULL, NULL, ++ "mbar", ++ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ++}; ++ ++static const char *cpu32_reg_names[NUM_REGS] = { ++ "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", ++ "a0", "a1", "a2", "a3", "a4", "a5", "fp", "sp", ++ "ps", "pc", ++ "pcc", "usp", "ssp", "sfc", "dfc", NULL, NULL, ++ "vbr", ++ NULL, NULL, NULL, NULL, ++ NULL, ++ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ++}; ++ ++static const char *cf_reg_names[NUM_REGS] = { ++ "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", ++ "a0", "a1", "a2", "a3", "a4", "a5", "fp", "sp", ++ "ps", "pc", ++ NULL, NULL, NULL, NULL, NULL, NULL, NULL, ++ "vbr", ++ "cacr", "acr0", "acr1", "rambar", ++ "mbar", ++ "csr", "aatr", "tdr", "pbr", "pbmr", "abhr", "ablr", "dbr", "dbmr", ++}; ++ ++static const char **bdm_reg_names = cpu32plus_reg_names; ++ ++const char *bdm_register_name(int i) ++{ ++ if ((i < 0) || (i >= NUM_REGS)) ++ return NULL; ++ return bdm_reg_names[i]; ++} ++ ++static int reg_to_dev_num[] = { ++ BDM_REG_SR, ++ BDM_REG_RPC, ++ BDM_REG_PCC, ++ BDM_REG_USP, ++ BDM_REG_SSP, ++ BDM_REG_SFC, ++ BDM_REG_DFC, ++ BDM_REG_ATEMP, ++ BDM_REG_FAR, ++ BDM_REG_VBR, ++ BDM_REG_CACR, ++ BDM_REG_ACR0, ++ BDM_REG_ACR1, ++ BDM_REG_RAMBAR, ++ BDM_REG_MBAR, ++ BDM_REG_CSR, ++ BDM_REG_AATR, ++ BDM_REG_TDR, ++ BDM_REG_PBR, ++ BDM_REG_PBMR, ++ BDM_REG_ABHR, ++ BDM_REG_ABLR, ++ BDM_REG_DBR, ++ BDM_REG_DBMR ++ }; ++ ++/* ++ * The name of the most recently loaded program ++ */ ++static char *bdm_prog_loaded; ++ ++/* ++ * Do not load the program when creating the target. ++ */ ++static int bdm_no_load; ++ ++/* ++ * default delay for interface ++ */ ++#define BDM_DEFAULT_DELAY 0 ++static int bdm_delay = -1; ++ ++/* ++ * does gdb wait or not, only valid for a Coldfire processor ++ */ ++static int bdm_gdb_no_wait = 0; ++ ++/* ++ * Hold BDM ATEMP register (CPU32 only). ++ */ ++static unsigned long atemp; ++static int haveAtemp; ++ ++static int hit_watchpoint; ++ ++/* ++ * CF BDM Debug hardware version number. ++ */ ++ ++static unsigned long cf_debug_ver; ++ ++/* ++ * Not sure if this is defined somewhere. Cannot see anywhere. ++ */ ++extern int (*ui_loop_hook) (int); ++ ++/* ++ * Forward declarations ++ */ ++static void bdm_load (char *, int); ++ ++/* ++ * give target time to come up after reset ++ * time in usec ++ */ ++#define TIME_TO_COME_UP 60000 ++ ++/* ++ * Downloader routines ++ */ ++static int downLoaderReturn; ++static int downLoaderFirst; ++static unsigned long downLoadBaseAddress, downLoadStartAddress; ++static unsigned long downLoadDataCount=0; ++static int bdmDebugLevel; ++static const char *downloadErrorString; ++ ++static void ++downloadSection (bfd *abfd, sec_ptr sec, PTR ignore) ++{ ++ unsigned long dfc; ++ unsigned long address; ++ unsigned long nleft, size; ++ int count; ++ file_ptr offset; ++ char cbuf[1024]; ++ ++ /* ++ * See if the section needs loading ++ */ ++ if (bdmDebugLevel) ++ printf_filtered ("Section flags:%#x\n", bfd_get_section_flags (abfd, sec)); ++ if ((downLoaderReturn < 0) || ++ ((bfd_get_section_flags (abfd, sec) & SEC_HAS_CONTENTS) == 0) || ++ ((bfd_get_section_flags (abfd, sec) & SEC_LOAD) == 0)) ++ return; ++ address = bfd_section_lma (abfd, sec); ++ if (bdmDebugLevel) ++ printf_filtered ("Section address:%#lx\n", address); ++ if (downLoaderFirst && (bfd_get_section_flags (abfd, sec) & SEC_CODE)) { ++ downLoadStartAddress = bfd_get_start_address (abfd); ++ downLoadBaseAddress = address; ++ downLoaderFirst = 0; ++ if (bdmDebugLevel) ++ printf_filtered ("Start address:%#lx Base address:%#lx\n", ++ downLoadStartAddress, downLoadBaseAddress); ++ } ++ ++ /* ++ * Set the appropriate destination address space ++ */ ++ if (bfd_get_section_flags (abfd, sec) & SEC_CODE) ++ dfc = 0x6; /* Supervisor program space */ ++ else ++ dfc = 0x5; /* Supervisor data space */ ++ if (bdmWriteSystemRegister (BDM_REG_DFC, dfc) < 0) { ++ downLoaderReturn = -1; ++ return; ++ } ++ ++ /* ++ * Load the section in `sizeof cbuf` chunks ++ */ ++ size = nleft = bfd_get_section_size_before_reloc (sec); ++ if (nleft == 0) ++ return; ++ ++ /* Is this really necessary? I guess it gives the user something ++ to look at during a long download. */ ++ ui_out_message (uiout, 0, "Loading section %s, size 0x%s lma 0x%s\n", ++ sec->name, paddr_nz (size), paddr_nz (address)); ++ ++ offset = 0; ++ while (nleft) { ++ if (nleft > sizeof cbuf) ++ count = sizeof cbuf; ++ else ++ count = nleft; ++ if (!bfd_get_section_contents (abfd, sec, cbuf, offset, count)) { ++ downloadErrorString = "Error reading section contents"; ++ downLoaderReturn = -1; ++ return; ++ } ++ if (bdmWriteMemory (address, cbuf, count) < 0) { ++ downLoaderReturn = -1; ++ return; ++ } ++ address += count; ++ offset += count; ++ nleft -= count; ++ ++ if (quit_flag ++ || (ui_load_progress_hook != NULL ++ && ui_load_progress_hook (sec->name, offset))) ++ error ("Canceled the download"); ++ ++ if (show_load_progress != NULL) ++ show_load_progress (sec->name, offset, size, size, size); ++ } ++ downLoadDataCount += size; ++} ++ ++/* ++ * Load an executable image into the target ++ */ ++static int ++loadExecutable (const char *name) ++{ ++ bfd *abfd; ++ unsigned long dfc; ++ unsigned long l; ++ ++ /* ++ * Make sure target is there ++ */ ++ if (!bdmCheck ()) ++ return -1; ++ ++ /* ++ * Open and verify the file ++ */ ++ bfd_init (); ++ abfd = bfd_openr (name, "default"); ++ if (abfd == NULL) { ++ downloadErrorString = bfd_errmsg (bfd_get_error()); ++ return -1; ++ } ++ if (!bfd_check_format (abfd, bfd_object)) { ++ downloadErrorString = "Not an object file"; ++ return -1; ++ } ++ ++ /* ++ * Save the destination function code register ++ */ ++ if (bdmReadSystemRegister (BDM_REG_DFC, &dfc) < 0) ++ return -1; ++ ++ /* ++ * Load each section of the executable file ++ */ ++ downLoadDataCount = 0; ++ downLoaderFirst = 1; ++ downLoaderReturn = 0; ++ bfd_map_over_sections (abfd, downloadSection, NULL); ++ if (downLoaderReturn < 0) ++ return -1; ++ ++ ui_out_text (uiout, "Start address "); ++ ui_out_field_fmt (uiout, "address", "0x%s", paddr_nz (downLoadStartAddress)); ++ ui_out_text (uiout, ", load size "); ++ ui_out_field_fmt (uiout, "load-size", "%lu", downLoadDataCount); ++ ui_out_text (uiout, "\n"); ++ ++ /* ++ * Set program counter ++ */ ++ if ((bdmWriteSystemRegister (BDM_REG_RPC, downLoadStartAddress) < 0) ++ || (bdmWriteSystemRegister (BDM_REG_DFC, dfc) < 0)) ++ return -1; ++ return 0; ++ ++ inferior_ptid = pid_to_ptid (1); ++ ++} ++ ++/* ++ * The breakpoint codes for the different processors ++ */ ++static char cpu32_breakpoint[] = {0x4a, 0xfa}; ++static char cf_breakpoint[] = {0x4a, 0xc8}; ++static char *breakpointCode; ++static int breakpointSize; ++ ++static int cf_init_watchpoints(); ++ ++/* Immediately after a function call, return the saved pc before the frame ++ is setup. For uCLinux which uses a TRAP #0 for a system call we need to ++ read the first long word of the stack to see if the stack frame format is ++ type 4 and the vector is 32 (0x4080), and the opcode at the PC is ++ "move.w #0x2700,sr". If it is then get the second long from the stack. */ ++ ++CORE_ADDR ++m68k_bdm_saved_pc_after_call (frame) ++ struct frame_info *frame; ++{ ++ unsigned int op; ++ unsigned int eframe; ++ int sp; ++ ++ sp = read_register (SP_REGNUM); ++ eframe = read_memory_integer (sp, 2); ++ op = read_memory_integer (frame->pc, 4); ++ ++ /* ++ * This test could break if some changes the syste call. ++ */ ++ ++ if (eframe == 0x4080 && op == 0x46fc2700) ++ return read_memory_integer (sp + 4, 4); ++ else ++ return read_memory_integer (sp, 4); ++} ++ ++unsigned char *m68k_bdm_breakpoint_from_pc (pcptr, lenptr) ++ CORE_ADDR *pcptr; ++ int *lenptr; ++{ ++ *lenptr = breakpointSize; ++ return breakpointCode; ++} ++ ++/* ++ * Short pause ++ */ ++static void ++nap (int microseconds) ++{ ++ struct timeval tv; ++ ++ tv.tv_sec = microseconds / 1000000; ++ tv.tv_usec = microseconds % 1000000; ++ select (0, NULL, NULL, NULL, &tv); ++} ++ ++/* ++ * Display error message and jump back to main input loop ++ */ ++static void ++bdm_report_error (void) ++{ ++ error ("BDM error: %s", bdmErrorString ()); ++} ++ ++/* ++ * Initialize bdm interface port ++ */ ++static void ++bdm_init (int tty, char *arg) ++{ ++} ++ ++/* ++ * Return interface status ++ */ ++static int ++bdm_get_status (void) ++{ ++ int status; ++ ++ if ((status = bdmStatus ()) < 0) ++ bdm_report_error (); ++ return status; ++} ++ ++static void ++bdm_get_status_interactive (int pid, char *arg) ++{ ++ printf ("BDM status: 0x%x\n", bdm_get_status ()); ++} ++ ++/* ++ * release chip: reset and disable bdm mode ++ */ ++static void ++bdm_release_chip (void) ++{ ++ haveAtemp = 0; ++ registers_changed (); ++ if (bdmRelease () < 0) ++ bdm_report_error (); ++} ++ ++/* ++ * stop chip ++ */ ++static void ++bdm_stop_chip (void) ++{ ++ if (bdmStop () < 0) ++ bdm_report_error (); ++} ++ ++/* ++ * Allow chip to resume execution ++ */ ++static void ++bdm_go (void) ++{ ++ haveAtemp = 0; ++ if (bdmGo () < 0) ++ bdm_report_error (); ++} ++ ++/* ++ * Reset chip, enter BDM mode ++ */ ++static void ++bdm_reset (void) ++{ ++ registers_changed (); ++ if (bdmReset () < 0) ++ bdm_report_error (); ++ nap (TIME_TO_COME_UP); ++} ++ ++/* ++ * step cpu32 chip: execute a single instruction ++ * This is complicated by the presence of interrupts. ++ * Consider the following sequence of events: ++ * - User attempts to `continue' from a breakpoint. ++ * - Gdb calls bdm_step_chip to single-step the instruction that ++ * had been replaced by the BGND instruction. ++ * - The target processor executes the instruction and stops. ++ * - GDB replaces the instruction with a BGND instruction to ++ * force a breakpoint the next time the instruction is hit. ++ * - GDB calls bdm_go and the target resumes execution. ++ * This all seems fine, but now consider what happens when a interrupt ++ * is pending: ++ * - User attempts to `continue' from a breakpoint. ++ * - Gdb calls bdm_step_chip to single-step the instruction that ++ * had been replaced by the BGND instruction. ++ * - The target processor does not execute the replaced instruction, ++ * but rather executes the first instruction of the interrupt ++ * service routine, then stops. ++ * - GDB replaces the instruction with a BGND instruction to ++ * force a breakpoint the next time the instruction is hit. ++ * - GDB calls bdm_go and the target resumes execution. ++ * - The target finishes off the interrupt, and upon returing from ++ * the interrupt generates another breakpoint! ++ * The solution is simple -- disable interrupts when single stepping. ++ * The problem then becomes the handling of instructions which involve ++ * the program status word! ++ */ ++static void ++bdm_step_cpu32_chip (void) ++{ ++ unsigned long pc; ++ unsigned short instruction; ++ unsigned short immediate; ++ unsigned long d7; ++ unsigned long sr; ++ unsigned long nsr; ++ enum { ++ op_other, ++ op_ANDIsr, ++ op_EORIsr, ++ op_ORIsr, ++ op_TOsr, ++ op_FROMsr, ++ op_FROMsrTOd7 ++ } op; ++ ++ /* ++ * Get the existing status register ++ */ ++ if (bdmReadSystemRegister (BDM_REG_SR, &sr) < 0) ++ bdm_report_error (); ++ ++ /* ++ * Read the instuction about to be executed ++ */ ++ if ((bdmReadSystemRegister (BDM_REG_RPC, &pc) < 0) ++ || (bdmReadWord (pc, &instruction) < 0)) ++ bdm_report_error (); ++ ++ /* ++ * See what operation is to be performed ++ */ ++ if (instruction == 0x027C) ++ op = op_ANDIsr; ++ else if (instruction == 0x0A7C) ++ op = op_EORIsr; ++ else if (instruction == 0x007C) ++ op = op_ORIsr; ++ else if (instruction == 0x40C7) ++ op = op_FROMsrTOd7; ++ else if ((instruction & 0xFFC0) == 0x40C0) ++ op = op_FROMsr; ++ else if ((instruction & 0xFFC0) == 0x46C0) ++ op = op_TOsr; ++ else ++ op = op_other; ++ ++ /* ++ * Set things up for the single-step operation ++ */ ++ switch (op) { ++ case op_FROMsr: ++ /* ++ * It's storing the SR somewhere. ++ * Store the SR in D7 and change the instruction ++ * to save D7. This fails if the addressing mode ++ * is one of the esoteric modes that uses D7 as ++ * and index register, but we'll just have to hope ++ * that doesn't happen too often. ++ */ ++ if ((bdmReadRegister (7, &d7) < 0) ++ || (bdmWriteRegister (7, sr) < 0) ++ || (bdmWriteWord (pc, 0x3007 | ++ ((instruction & 0x38) << 3) | ++ ((instruction & 0x07) << 9)) < 0)) ++ bdm_report_error (); ++ break; ++ ++ case op_ANDIsr: ++ case op_EORIsr: ++ case op_ORIsr: ++ /* ++ * It's an immediate operation to the SR -- pick up the value ++ */ ++ if (bdmReadWord (pc+2, &immediate) < 0) ++ bdm_report_error (); ++ break; ++ ++ case op_TOsr: ++ case op_other: ++ break; ++ } ++ ++ /* ++ * Ensure the step is done with interrupts disabled ++ */ ++ if (bdmWriteSystemRegister (BDM_REG_SR, sr | 0x0700) < 0) ++ bdm_report_error (); ++ ++ /* ++ * Do the single-step ++ */ ++ if (bdmStep () < 0) ++ bdm_report_error (); ++ ++ /* ++ * Get the ATEMP register since the following operations may ++ * modify it. ++ */ ++ if (bdmReadSystemRegister (BDM_REG_ATEMP, &atemp) < 0) ++ bdm_report_error (); ++ haveAtemp = 1; ++ ++ /* ++ * Clean things up ++ */ ++ switch (op) { ++ case op_FROMsr: ++ if ((bdmWriteRegister (7, d7) < 0) ++ || (bdmWriteWord (pc, instruction) < 0) ++ || (bdmWriteSystemRegister (BDM_REG_SR, sr) < 0)) ++ bdm_report_error (); ++ break; ++ ++ case op_FROMsrTOd7: ++ if ((bdmReadRegister (7, &d7) < 0) ++ || (bdmWriteRegister (7, (d7 & ~0xFFFF) | (sr & 0xFFFF)) < 0) ++ || (bdmWriteSystemRegister (BDM_REG_SR, sr) < 0)) ++ bdm_report_error (); ++ break; ++ ++ case op_ANDIsr: ++ if (bdmWriteSystemRegister (BDM_REG_SR, sr & immediate) < 0) ++ bdm_report_error (); ++ break; ++ ++ case op_EORIsr: ++ if (bdmWriteSystemRegister (BDM_REG_SR, sr ^ immediate) < 0) ++ bdm_report_error (); ++ break; ++ ++ case op_ORIsr: ++ if (bdmWriteSystemRegister (BDM_REG_SR, sr | immediate) < 0) ++ bdm_report_error (); ++ break; ++ ++ case op_TOsr: ++ break; ++ ++ case op_other: ++ if ((bdmReadSystemRegister (BDM_REG_SR, &nsr) < 0) ++ || (bdmWriteSystemRegister (BDM_REG_SR, (nsr & ~0x0700) | (sr & 0x0700)) < 0)) ++ bdm_report_error (); ++ break; ++ } ++} ++ ++static void ++bdm_step_chip (void) ++{ ++ /* ++ * The cpu32 is harder to step than the Coldfire. ++ */ ++ if (cpu_type == BDM_CPU32) { ++ bdm_step_cpu32_chip(); ++ return; ++ } ++ ++ /* ++ * Do the single-step ++ */ ++ if (bdmStep () < 0) ++ bdm_report_error (); ++} ++ ++/* ++ * true if runnable ++ */ ++static int ++bdm_can_run (void) ++{ ++ return 1; ++} ++ ++static void ++bdm_setdelay(int delay) ++{ ++ if (bdmSetDelay (delay) < 0) ++ bdm_report_error (); ++} ++ ++static void ++bdm_setdelay_interactive (char *arg, int from_tty) ++{ ++ char *dummy; ++ ++ if (!arg) { ++ if (bdm_delay >= 0) ++ printf_filtered("bdm_delay is %d", bdm_delay); ++ else ++ printf_filtered("using default delay %d", BDM_DEFAULT_DELAY); ++ } ++ else { ++ bdm_delay = strtoul(arg, &dummy, 0); ++ bdm_setdelay (bdm_delay); ++ } ++} ++ ++static void ++bdm_setdebug_interactive (char *arg, int from_tty) ++{ ++ char *dummy; ++ ++ if (arg) { ++ bdmDebugLevel = strtoul(arg, &dummy, 0); ++ bdmSetDebugFlag (bdmDebugLevel); ++ } ++ else ++ error ("Argument missing"); ++} ++ ++static void ++bdm_setdriverdebug_interactive (char *arg, int from_tty) ++{ ++ char *dummy; ++ ++ if (arg) ++ bdmSetDriverDebugFlag (strtoul(arg, &dummy, 0)); ++ else ++ error ("Argument missing"); ++} ++ ++static void ++bdm_set_no_wait (char *arg, int from_tty) ++{ ++ bdm_gdb_no_wait = 1; ++} ++ ++static void ++bdm_set_wait (char *arg, int from_tty) ++{ ++ if (cpu_type == BDM_CPU32) { ++ error ("No wait mode is not supported on a CPU32"); ++ return; ++ } ++ if (bdm_get_status ()) ++ bdm_gdb_no_wait = 0; ++ else ++ error ("The target is running, please stop first"); ++} ++ ++static void ++bdm_issue_stop (char *arg, int from_tty) ++{ ++ bdm_stop_chip (); ++} ++ ++/* ++ * Open a connection the target via bdm ++ * name is the devicename of bdm and the filename to be used ++ * used for communication. ++ */ ++static void ++bdm_open (char *name, int from_tty) ++{ ++ char *p; ++ int version; ++ unsigned long csr; ++ ++ if (bdmIsOpen ()) ++ error ("Bdm is already open, must close it first"); ++ if (name == NULL) ++ error ("Use `target bdm ' 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 the bdm port device."); ++ dev_name = savestring (name, p - name); ++ ++ target_preopen (from_tty); ++ unpush_target (&bdm_ops); ++ ++ if (bdmOpen (dev_name) < 0) ++ bdm_report_error (); ++ if (bdmStatus () & (BDM_TARGETPOWER | BDM_TARGETNC)) { ++ bdmClose (); ++ error ("Target or cable problem"); ++ } ++ ++ /* ++ * Ask the driver for it's version. ++ * We are only interested in the major number when checking the ++ * driver version number. ++ */ ++ if (bdmGetDrvVersion (&version) < 0) ++ bdm_report_error (); ++ if ((version & 0xff00) != (BDM_DRV_VERSION & 0xff00)) { ++ printf_filtered ("Incorrect driver version, looking for %i.%i"\ ++ " and found %i.%i\n", ++ BDM_DRV_VERSION >> 8, BDM_DRV_VERSION & 0xff, ++ version >> 8, version & 0xff); ++ bdmClose (); ++ error ("Can't run with wrong BDM driver"); ++ } ++ ++ /* ++ * Get the processor type. ++ */ ++ if (bdmGetProcessor (&cpu_type) < 0) ++ bdm_report_error (); ++ switch (cpu_type) { ++ case BDM_CPU32: ++ bdm_reg_names = cpu32_reg_names; ++ breakpointCode = cpu32_breakpoint; ++ breakpointSize = sizeof cpu32_breakpoint; ++ break; ++ ++ case BDM_COLDFIRE: ++ bdm_reg_names = cf_reg_names; ++ breakpointCode = cf_breakpoint; ++ breakpointSize = sizeof cf_breakpoint; ++ cf_init_watchpoints(); ++ ++ /* ++ * Read the CSR register to determine the debug module ++ * version. ++ */ ++ if (bdmReadSystemRegister (BDM_REG_CSR, &csr) < 0) ++ bdm_report_error (); ++ cf_debug_ver = (csr >> 20) & 0x0f; ++ break; ++ ++ default: ++ bdmClose (); ++ error ("Unknown processor type returned from the driver."); ++ } ++ ++ push_target (&bdm_ops); ++ ++ if (bdm_delay >= 0) ++ bdm_setdelay (bdm_delay); ++ else ++ bdm_setdelay (BDM_DEFAULT_DELAY); ++ if (from_tty) ++ printf_filtered ("Remote %s connected to %s\n", ++ target_shortname, dev_name); ++ if (cpu_type == BDM_COLDFIRE) ++ printf_filtered (" Coldfire debug module version is %ld (%s)\n", ++ cf_debug_ver, ++ cf_debug_ver == 0 ? "5206(e)" : "5307/5407(e)"); ++} ++ ++/* ++ * Terminate current application and return to system prompt. ++ * On a target, just let the program keep on running ++ */ ++static void ++bdm_kill (void) ++{ ++#ifdef BDM_GDB_RELEASE_CPU_ON_EXIT ++ if (bdm_get_status () & BDM_TARGETSTOPPED) ++ bdm_go (); ++#else ++ bdm_stop_chip (); ++ bdm_reset (); ++#endif ++ bdm_prog_loaded = 0; ++} ++ ++static void ++bdm_close (quitting) ++int quitting; ++{ ++ if (quitting) ++ bdm_kill (); ++ bdmClose (); ++} ++ ++/* ++ * _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) ++{ ++ pop_target (); /* calls bdm_close to do the real work */ ++} ++ ++/* ++ * _resume -- Tell the remote machine to resume. ++ */ ++static void ++bdm_resume (ptid_t pid, int step, enum target_signal sig) ++{ ++ if (step) ++ bdm_step_chip (); ++ else ++ bdm_go (); ++} ++ ++/* ++ * We have fallen into an exception supported by the runtime system. ++ * by executing a `breakpoint' instruction. ++ */ ++static void ++analyze_exception (struct target_waitstatus *status) ++{ ++ unsigned long pc, sp; ++ unsigned short vec; ++ char opcode[20]; /* `big enough' */ ++ ++ if (cpu_type == BDM_CPU32) { ++ if (bdmReadSystemRegister (BDM_REG_PCC, &pc) < 0) ++ bdm_report_error (); ++ } ++ else { ++ if (bdmReadSystemRegister (BDM_REG_RPC, &pc) < 0) ++ bdm_report_error (); ++ if (pc) ++ pc -= 2; ++ } ++ status->kind = TARGET_WAITKIND_STOPPED; ++ ++ /* ++ * See if it was a `breakpoint' instruction ++ */ ++ if (bdmReadMemory (pc, opcode, breakpointSize) < 0) ++ bdm_report_error (); ++ if (memcmp (breakpointCode, opcode, breakpointSize) == 0) { ++ if (bdmWriteSystemRegister (BDM_REG_RPC, pc) < 0) ++ bdm_report_error (); ++ status->value.sig = TARGET_SIGNAL_TRAP; ++ return; ++ } ++ /* ++ * FIXME: Why an illegal instruction signal ? ++ */ ++ status->value.sig = TARGET_SIGNAL_ILL; ++} ++ ++static int sigintFlag; ++static void ++bdm_signal_handler (int s) ++{ ++ sigintFlag++; ++} ++ ++/* ++ * 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) ++{ ++ unsigned long csr; ++ int bdm_stat; ++ int detach = 0; ++ int ui_count = 0; ++ void (*ofunc) (); ++ ++ hit_watchpoint = 0; ++ if (bdm_gdb_no_wait) { ++ status->kind = TARGET_WAITKIND_STOPPED; ++ status->value.sig = TARGET_SIGNAL_GRANT; ++ return null_ptid; ++ } ++ ++ status->kind = TARGET_WAITKIND_EXITED; ++ status->value.integer = 0; ++ ++ /* ++ * Catch SIGINT signals ++ */ ++ sigintFlag = 0; ++ ofunc = signal (SIGINT, bdm_signal_handler); ++ ++ /* ++ * A work around a problem with the 5206e processor. Not sure ++ * what the issue is. It could be the processor. ++ */ ++ if (cpu_type == BDM_COLDFIRE && cf_debug_ver == 0) ++ nap (10000); ++ ++ /* ++ * Wait here till the target requires service ++ */ ++ while ((bdm_stat = bdm_get_status ()) == 0) { ++ ui_count = 0; ++ while (ui_count++ < 6) { ++ nap (50000); ++ ++ /* N.B. The UI may destroy our world (for instance by calling ++ remote_stop,) in which case we want to get out of here as ++ quickly as possible. It is not safe to touch scb, since ++ someone else might have freed it. The ui_loop_hook signals that ++ we should exit by returning 1. */ ++ ++ if (ui_loop_hook) ++ detach = ui_loop_hook (0); ++ ++ if (detach || sigintFlag) ++ bdm_stop_chip (); ++ } ++ } ++ ++ signal (SIGINT, ofunc); ++ ++ /* ++ * Determine why the target stopped ++ */ ++ 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: ++ case BDM_TARGETHALT: ++ case BDM_TARGETSTOPPED | BDM_TARGETHALT: ++ if (sigintFlag) { ++ status->kind = TARGET_WAITKIND_STOPPED; ++ status->value.sig = TARGET_SIGNAL_TSTP; ++ } ++ else { ++ if (cpu_type == BDM_CPU32) { ++ if (!haveAtemp ++ && (bdmReadSystemRegister (BDM_REG_ATEMP, &atemp) < 0)) ++ bdm_report_error (); ++ switch (atemp & 0xffff) { ++ case 0xffff: /* double bus fault */ ++ status->kind = TARGET_WAITKIND_STOPPED; ++ status->value.sig = TARGET_SIGNAL_BUS; ++ break; ++ case 0x0: /* HW bkpt */ ++ status->kind = TARGET_WAITKIND_STOPPED; ++ status->value.sig = TARGET_SIGNAL_TRAP; ++ break; ++ case 0x1: /* background mode */ ++ analyze_exception (status); ++ break; ++ default: ++ printf_filtered ("bdm_wait: Unknown atemp:%#lx\n", atemp); ++ status->kind = TARGET_WAITKIND_STOPPED; ++ status->value.sig = TARGET_SIGNAL_GRANT; ++ } ++ } ++ else { ++ if (bdmReadSystemRegister (BDM_REG_CSR, &csr) < 0) ++ bdm_report_error (); ++ if (csr & 0x08000000) { /* double bus fault */ ++ status->kind = TARGET_WAITKIND_STOPPED; ++ status->value.sig = TARGET_SIGNAL_BUS; ++ } ++ else { ++ if (csr & 0x04000000) { /* hardware trigger */ ++ hit_watchpoint = 1; ++ status->kind = TARGET_WAITKIND_STOPPED; ++ status->value.sig = TARGET_SIGNAL_TRAP; ++ } ++ else { ++ if (csr & 0x01000000) { /* -BKPT signal */ ++ status->kind = TARGET_WAITKIND_STOPPED; ++ status->value.sig = TARGET_SIGNAL_TRAP; ++ } ++ else { ++ if (csr & 0x02000000) { /* HALT/software bkpt */ ++ analyze_exception (status); ++ } ++ else { ++ printf_filtered ("bdm_wait: Unknown csr:%#lx", ++ csr); ++ status->kind = TARGET_WAITKIND_STOPPED; ++ status->value.sig = TARGET_SIGNAL_GRANT; ++ } ++ } ++ } ++ } ++ } ++ } ++ break; ++ default: ++ printf_filtered ("bdm_wait: Unknown BDM status: %#x", bdm_stat); ++ break; ++ } ++ haveAtemp = 0; ++ return null_ptid; ++} ++ ++/* ++ * The following routines handle the Coldfire hardware breakpoints. Only one ++ * breakpoint supported so far, and it can be either a PC breakpoint or an ++ * address watchpoint. Unfortunately, the TARGET_CAN_USE_HARDWARE_WATCHPOINT ++ * macro only allows for bounds checking within one of the two types and not ++ * limits that cover the sum of both, so extra work is needed. ++ * ++ * (Actually, very few processors seem to have much support for that routine ++ * at all.) ++ * ++ * As a result, the way this is handled is that the can_use routine will allow ++ * the first breakpoint of either type to be added. Any further checking so ++ * that only one of the two can be used is done later when GDB actually tries ++ * to create the breakpoints, usually when the processor is restarted. ++ * ++ * We keep a local copy of the breakpoints list becasue the chain that GDB ++ * keeps isn't exported globally. ++ * ++ * While things could be simplified with only one breakpoint present, setting ++ * up more general routines allows for later expansion if newer versions of ++ * the ColdFire chip support more breakpoints at once. ++ * ++ * Also, the ColdFire supports things like multi-level triggers and triggers ++ * based on the data bus instead of just the address bus. The GDB commands ++ * don't allow for access to this, but much of it isn't necessary anyway, ++ * as GDB has its own method of handling 'breakpoint conditions' that is ++ * sufficient for most tasks. ++ */ ++ ++#define TDR_TRC_DDATA 0x00000000 ++#define TDR_TRC_HALT 0x40000000 ++#define TDR_TRC_DINT 0x80000000 ++#define TDR_L2_EBL 0x20000000 ++#define TDR_L2_ALL 0x1FFF0000 ++#define TDR_L2_EDLW 0x10000000 ++#define TDR_L2_EDWL 0x08000000 ++#define TDR_L2_EDWU 0x04000000 ++#define TDR_L2_EDLL 0x02000000 ++#define TDR_L2_EDLM 0x01000000 ++#define TDR_L2_EDUM 0x00800000 ++#define TDR_L2_EDUU 0x00400000 ++#define TDR_L2_DI 0x00200000 ++#define TDR_L2_EAI 0x00100000 ++#define TDR_L2_EAR 0x00080000 ++#define TDR_L2_EAL 0x00040000 ++#define TDR_L2_EPC 0x00020000 ++#define TDR_L2_PCI 0x00010000 ++#define TDR_L1_EBL 0x00002000 ++#define TDR_L1_ALL 0x00001FFF ++#define TDR_L1_EDLW 0x00001000 ++#define TDR_L1_EDWL 0x00000800 ++#define TDR_L1_EDWU 0x00000400 ++#define TDR_L1_EDLL 0x00000200 ++#define TDR_L1_EDLM 0x00000100 ++#define TDR_L1_EDUM 0x00000080 ++#define TDR_L1_EDUU 0x00000040 ++#define TDR_L1_DI 0x00000020 ++#define TDR_L1_EAI 0x00000010 ++#define TDR_L1_EAR 0x00000008 ++#define TDR_L1_EAL 0x00000004 ++#define TDR_L1_EPC 0x00000002 ++#define TDR_L1_PCI 0x00000001 ++ ++struct cf_break { ++ enum target_hw_bp_type type; ++ CORE_ADDR addr; ++ int len; ++}; ++ ++#define CF_BREAKPOINT_MAX 1 ++ ++static struct cf_break cf_breakpoints[CF_BREAKPOINT_MAX]; ++static int cf_breakpoint_count; ++ ++static int ++cf_init_watchpoints(void) ++{ ++ if (cpu_type != BDM_COLDFIRE) { ++ return(-1); ++ } ++ cf_breakpoint_count = 0; ++ if (bdmWriteSystemRegister (BDM_REG_TDR, TDR_TRC_HALT) < 0) ++ bdm_report_error (); ++ return(0); ++} ++ ++int ++cf_stopped_by_watchpoint(void) ++{ ++ return hit_watchpoint; ++} ++ ++int ++cf_can_use_watchpoint(type, cnt, ot) ++ enum target_hw_bp_type type; ++ int cnt; ++ int ot; ++{ ++ unsigned long tdr; ++ ++ if (cpu_type != BDM_COLDFIRE) { ++ return(0); ++ } ++ ++ if (type == bp_hardware_breakpoint || type == bp_read_watchpoint || ++ type == bp_hardware_watchpoint || type == bp_access_watchpoint) { ++ if (cnt <= 1) { ++ return(1); ++ } ++ } ++ ++ return(-1); ++} ++ ++int ++cf_insert_hw_breakpoint(addr, shadow) ++ CORE_ADDR addr; ++ char *shadow; ++{ ++ unsigned long tdr; ++ ++ if (cpu_type != BDM_COLDFIRE) { ++ return(-1); ++ } ++ ++ if (cf_breakpoint_count < CF_BREAKPOINT_MAX) { ++ cf_breakpoints[cf_breakpoint_count].type = hw_execute; ++ cf_breakpoints[cf_breakpoint_count].addr = addr; ++ cf_breakpoints[cf_breakpoint_count++].len = 2; ++ ++ if (bdmReadSystemRegister (BDM_REG_TDR, &tdr) < 0) ++ bdm_report_error (); ++ tdr = ((tdr & ~TDR_L1_ALL) | (TDR_L1_EBL|TDR_L1_EPC)); ++ if (bdmWriteSystemRegister (BDM_REG_PBR, addr) < 0) ++ bdm_report_error (); ++ if (bdmWriteSystemRegister (BDM_REG_PBMR, 0) < 0) ++ bdm_report_error (); ++ if (bdmWriteSystemRegister (BDM_REG_TDR, tdr) < 0) ++ bdm_report_error (); ++ if (bdmDebugLevel) ++ printf_filtered ("Insert PC Breakpoint @0x%08lx\n", addr); ++ } ++ else { ++ return(-1); ++ } ++ return(0); ++} ++ ++static int ++cf_check_breakpoint(type, addr, len) ++ enum target_hw_bp_type type; ++ CORE_ADDR addr; ++ int len; ++{ ++ int i; ++ ++ for (i = 0; i < cf_breakpoint_count; i++) { ++ if (cf_breakpoints[i].type == type && ++ cf_breakpoints[i].addr == addr && ++ cf_breakpoints[i].len == len) { ++ for (; i < CF_BREAKPOINT_MAX-1; i++) { ++ cf_breakpoints[i] = cf_breakpoints[i+1]; ++ } ++ cf_breakpoint_count--; ++ return(1); ++ } ++ } ++ return(0); ++} ++ ++int ++cf_remove_hw_breakpoint(addr, shadow) ++ CORE_ADDR addr; ++ char *shadow; ++{ ++ unsigned long tdr; ++ unsigned long csr; ++ ++ if (cpu_type != BDM_COLDFIRE) { ++ return(-1); ++ } ++ ++ if (cf_check_breakpoint(hw_execute, addr, 2)) { ++ if (bdmReadSystemRegister (BDM_REG_TDR, &tdr) < 0) ++ bdm_report_error (); ++ tdr &= ~TDR_L1_EPC; ++ if ((tdr & TDR_L1_ALL) == 0) { ++ tdr &= ~TDR_L1_EBL; ++ } ++ if (bdmWriteSystemRegister (BDM_REG_TDR, tdr) < 0) ++ bdm_report_error (); ++ if (bdmDebugLevel) ++ printf_filtered ("Remove PC Breakpoint @0x%08lx\n", addr); ++ } ++ else { ++ return(-1); ++ } ++ return(0); ++} ++ ++#define AATR_READONLY 0x7F85 ++#define AATR_WRITEONLY 0x7F05 ++#define AATR_READWRITE 0xFF05 ++ ++int ++cf_insert_watchpoint(addr, len, type) ++ CORE_ADDR addr; ++ int len; ++ enum target_hw_bp_type type; ++{ ++ unsigned long tdr; ++ ++ if (cpu_type != BDM_COLDFIRE) { ++ return(-1); ++ } ++ ++ if (cf_breakpoint_count < CF_BREAKPOINT_MAX) { ++ cf_breakpoints[cf_breakpoint_count].type = type; ++ cf_breakpoints[cf_breakpoint_count].addr = addr; ++ cf_breakpoints[cf_breakpoint_count++].len = len; ++ ++ if (bdmReadSystemRegister (BDM_REG_TDR, &tdr) < 0) ++ bdm_report_error (); ++ tdr = ((tdr & ~TDR_L1_ALL) | (TDR_L1_EBL|TDR_L1_EAR)); ++ if (bdmWriteSystemRegister (BDM_REG_ABLR, addr) < 0) ++ bdm_report_error (); ++ if (bdmWriteSystemRegister (BDM_REG_ABHR, addr+len-1) < 0) ++ bdm_report_error (); ++ if (type == hw_read) { ++ if (bdmWriteSystemRegister (BDM_REG_AATR, AATR_READONLY) < 0) ++ bdm_report_error (); ++ if (bdmDebugLevel) ++ printf_filtered ("Insert read Watchpoint @0x%08lx-0x%08lx\n", ++ addr, addr+len-1); ++ } ++ else if (type == hw_write) { ++ if (bdmWriteSystemRegister (BDM_REG_AATR, AATR_WRITEONLY) < 0) ++ bdm_report_error (); ++ if (bdmDebugLevel) ++ printf_filtered ("Insert write Watchpoint @0x%08lx-0x%08lx\n", ++ addr, addr+len-1); ++ } ++ else { ++ if (bdmWriteSystemRegister (BDM_REG_AATR, AATR_READWRITE) < 0) ++ bdm_report_error (); ++ if (bdmDebugLevel) ++ printf_filtered ("Insert access Watchpoint @0x%08lx-0x%08lx\n", ++ addr, addr+len-1); ++ } ++ if (bdmWriteSystemRegister (BDM_REG_TDR, tdr) < 0) ++ bdm_report_error (); ++ } ++ else { ++ return(-1); ++ } ++ return(0); ++} ++ ++int ++cf_remove_watchpoint(addr, len, type) ++ CORE_ADDR addr; ++ int len; ++ enum target_hw_bp_type type; ++{ ++ unsigned long tdr; ++ unsigned long csr; ++ ++ if (cpu_type != BDM_COLDFIRE) { ++ return(-1); ++ } ++ ++ if (cf_check_breakpoint(type, addr, len)) { ++ if (bdmReadSystemRegister (BDM_REG_TDR, &tdr) < 0) ++ bdm_report_error (); ++ tdr &= ~TDR_L1_EAR; ++ if ((tdr & TDR_L1_ALL) == 0) { ++ tdr &= ~TDR_L1_EBL; ++ } ++ if (bdmWriteSystemRegister (BDM_REG_TDR, tdr) < 0) ++ bdm_report_error (); ++ if (bdmDebugLevel) ++ printf_filtered ("Remove %s Watchpoint @0x%08lx-0x%08lx\n", ++ (type == hw_read) ? "read" : ++ ((type == hw_write) ? "write" : "access"), ++ addr, addr+len-1); ++ } ++ else { ++ return(-1); ++ } ++ return(0); ++} ++ ++int ++cf_stopped_data_address() ++{ ++ unsigned long tdr; ++ unsigned long ablr; ++ ++ if (cpu_type != BDM_COLDFIRE) { ++ return(-1); ++ } ++ ++ if (bdmReadSystemRegister (BDM_REG_TDR, &tdr) < 0) ++ bdm_report_error (); ++ if (bdmReadSystemRegister (BDM_REG_ABLR, &ablr) < 0) ++ bdm_report_error (); ++ ++ if (tdr & TDR_L1_EAR) { ++ return(ablr); ++ } ++ return(0); ++} ++ ++/* 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; ++ unsigned long entry_pt; ++ ++ clear_proceed_status (); ++ init_wait_for_inferior (); ++ if (*args) { ++ prg_file = args; ++ } ++ else { ++ prg_file = execfile; ++ } ++ if (!(prg_file) && !(bdm_prog_loaded)) ++ error ("No program specified to run\n"); ++ else ++ { ++ if (!bdm_no_load) { ++ if (bdm_prog_loaded) ++ printf_filtered ("Note: `%s' has already been loaded.\n", ++ bdm_prog_loaded); ++ if (query ("Do you want to download `%s'?", prg_file)) ++ bdm_load (prg_file, 0); ++ if (bdmReadSystemRegister (BDM_REG_RPC, &entry_pt) < 0) ++ bdm_report_error (); ++ } ++ proceed (entry_pt, TARGET_SIGNAL_DEFAULT, 0); ++ } ++ inferior_ptid = pid_to_ptid (1); ++} ++ ++/* ++ * Fetch register REGNO, or all user registers if REGNO is -1. ++ */ ++static void ++bdm_fetch_register (int regno) ++{ ++ unsigned long l; ++ char cbuf[4]; ++ int ret; ++ ++ if (regno < 0) { ++ for (regno = 0 ; regno < NUM_REGS ; regno++) ++ bdm_fetch_register (regno); ++ } ++ else { ++ /* ++ * When the target is running the ++ * cpu registers can not be accessed. ++ */ ++ if (bdm_gdb_no_wait && (bdm_get_status () == 0)) { ++ l = 0; ++ ret = 0; ++ } ++ else { ++ if (regno < 16) { ++ ret = bdmReadRegister (regno, &l); ++ } ++ else { ++ if ((regno - 16) < (sizeof (reg_to_dev_num) / sizeof (int))) { ++ ret = bdmReadSystemRegister (reg_to_dev_num[regno - 16], &l); ++ } ++ else { ++ error ("Bad register number (%d)", regno); ++ return; ++ } ++ } ++ } ++ if (ret < 0) ++ bdm_report_error (); ++ cbuf[0] = l >> 24; ++ cbuf[1] = l >> 16; ++ cbuf[2] = l >> 8; ++ cbuf[3] = l; ++ supply_register (regno, cbuf); ++ } ++} ++ ++void ++bdm_prepare_to_store (void) ++{ ++ /* Do nothing, since we can store individual regs */ ++} ++ ++/* ++ * Store register REGNO, or all user registers if REGNO == -1. ++ */ ++void ++bdm_store_register (int regno) ++{ ++ unsigned long l; ++ int ret; ++ ++ if (bdm_gdb_no_wait && (bdm_get_status () == 0)) ++ return; ++ ++ if (regno == -1) { ++ for (regno = 0 ; regno < NUM_REGS ; regno++) ++ bdm_store_register (regno); ++ } ++ else { ++ l = read_register (regno); ++ if (regno < 16) { ++ ret = bdmWriteRegister (regno, l); ++ } ++ else { ++ if ((regno - 16) < (sizeof (reg_to_dev_num) / sizeof (int))) { ++ ret = bdmWriteSystemRegister (reg_to_dev_num[regno - 16], l); ++ } ++ else { ++ error ("Bad register number (%d)", regno); ++ return; ++ } ++ } ++ if (ret < 0) ++ bdm_report_error (); ++ } ++} ++ ++/* ++ * Transfer memory contents between target and host ++ */ ++static int ++bdm_xfer_inferior_memory (CORE_ADDR memaddr, char *myaddr, ++ int len, int write, ++ struct mem_attrib *attrib, ++ struct target_ops *t) ++{ ++ int ret; ++ ++ if (write) ++ ret = bdmWriteMemory (memaddr, myaddr, len); ++ else ++ ret = bdmReadMemory (memaddr, myaddr, len); ++ if (ret < 0) ++ bdm_report_error (); ++ return len; ++} ++ ++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"); ++ } ++} ++ ++/* ++ * Load a file. ++ */ ++static void ++bdm_load (char *args, int from_tty) ++{ ++ char *p; ++ ++ if (bdm_prog_loaded) { ++ free (bdm_prog_loaded); ++ bdm_prog_loaded = NULL; ++ } ++ if (!args) { ++ error ( ++ "The bdmload command must include the filename to load.\n" ++ "You may want to use 'run', which uses the file given\n" ++ "on the command line when gdb was invoked."); ++ } ++ if ((bdm_get_status () & BDM_TARGETSTOPPED) == 0) ++ bdm_stop_chip (); ++ ++ /* strip off additional (unwanted) arguments after file name */ ++ for (p = args; (*p != '\0') && (!isspace (*p)); p++) ; ++ *p = '\0'; ++ ++ if (loadExecutable (args) < 0) ++ error ("%s", downloadErrorString); ++ bdm_prog_loaded = savestring (args, strlen (args)); ++} ++ ++/* ++ * Toggle the no load variable. ++ */ ++static void ++bdm_toggle_no_load (char *args, int from_tty) ++{ ++ if (bdm_no_load) { ++ bdm_no_load = 0; ++ printf_filtered ("Image not loaded on run\n"); ++ } ++ else { ++ bdm_no_load = 1; ++ printf_filtered ("Image loaded on run\n"); ++ } ++} ++ ++/* ++ * Select a CPU32 processor register set. ++ */ ++static void ++bdm_select_cpu32 (char *args, int from_tty) ++{ ++ bdm_reg_names = cpu32_reg_names; ++} ++ ++struct target_ops bdm_ops; ++ ++static void ++init_bdm_ops(void) ++{ ++ bdm_ops.to_shortname = "bdm"; ++ bdm_ops.to_longname = "CPU32 and Coldfire Background Debug Mode Interface for downloading and remote debugging"; ++ bdm_ops.to_doc = "Uses the Public Domain Background Debug Mode Interface connected to the\n" ++"BDM-port of the CPU32 or Coldfire based microcontroller and to a parallel port\n" ++"of the PC.\n" ++"Usage: target bdm \n" ++"where is the BDM character special file (e.g. /dev/bdm0)."; ++ bdm_ops.to_open = bdm_open; ++ bdm_ops.to_close = bdm_close; ++ bdm_ops.to_detach = bdm_detach; ++ bdm_ops.to_resume = bdm_resume; ++ bdm_ops.to_wait = bdm_wait; ++ 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 = memory_insert_breakpoint; ++ bdm_ops.to_remove_breakpoint = memory_remove_breakpoint; ++ bdm_ops.to_kill = bdm_kill; ++ bdm_ops.to_load = bdm_load; ++ bdm_ops.to_stop = bdm_stop_chip; ++ bdm_ops.to_create_inferior = bdm_create_inferior; ++ bdm_ops.to_mourn_inferior = generic_mourn_inferior; ++ bdm_ops.to_can_run = bdm_can_run; ++ bdm_ops.to_stratum = process_stratum; ++ 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; ++ bdm_ops.to_magic = OPS_MAGIC; ++}; ++ ++void ++_initialize_remote_bdmcf (void) ++{ ++ init_bdm_ops (); ++ add_com ("bdm_reset", class_obscure, ++ (void (*)(char *, int))bdm_reset, ++ "Reset target and enter BDM mode."); ++ add_com ("bdm_release", class_obscure, ++ (void (*)(char *, int))bdm_release_chip, ++ "Reset target without BDM-mode."); ++ add_com ("bdm_status", class_obscure, ++ (void (*)(char *, int))bdm_get_status_interactive, ++ "Show status of bdm interface\n"); ++ add_com ("bdm_setdelay", class_obscure, ++ bdm_setdelay_interactive, ++ "set delay for download"); ++ add_com ("bdm_setdebug", class_obscure, ++ bdm_setdebug_interactive, ++ "enable/disable BDM diagnostic messages"); ++ add_com ("bdm_setdriverdebug", class_obscure, ++ bdm_setdriverdebug_interactive, ++ "enable/disable BDM driver diagnostic messages"); ++ add_com ("bdm_no_wait", class_obscure, ++ bdm_set_no_wait, ++ "Cause GDB to not wait for the target to stop when running."); ++ add_com ("bdm_wait", class_obscure, ++ bdm_set_wait, ++ "Cause GDB to wait for the target to stop when running."); ++ add_com ("bdm_stop", class_obscure, ++ bdm_issue_stop, ++ "Stop the target if running."); ++ add_com ("bdm-select-cpu32", class_obscure, ++ bdm_select_cpu32, ++ "Selects the CPU32 register set rather than the default CPU32+."); ++ add_com ("bdm-no-load", class_obscure, ++ bdm_toggle_no_load, ++ "Toggle the loading of the program to memory when asked to run."); ++ ++ add_target (&bdm_ops); ++} +diff -Nru insight-5.3.orig/gdb/infcmd.c insight-5.3/gdb/infcmd.c +--- insight-5.3.orig/gdb/infcmd.c 2003-11-18 23:46:48.000000000 +0100 ++++ insight-5.3/gdb/infcmd.c 2003-11-19 10:19:02.000000000 +0100 +@@ -1337,8 +1337,10 @@ + "finish_command: function has no target type"); + + /* FIXME: Shouldn't we do the cleanups before returning? */ +- if (TYPE_CODE (value_type) == TYPE_CODE_VOID) ++ if (TYPE_CODE (value_type) == TYPE_CODE_VOID) { ++ do_cleanups (old_chain); + return; ++ } + + funcaddr = BLOCK_START (SYMBOL_BLOCK_VALUE (function)); + diff --git a/gdb/patches/gdb-6.0-bdm-m68k.patch b/gdb/patches/gdb-6.0-bdm-m68k.patch new file mode 100644 index 0000000..0cac4e3 --- /dev/null +++ b/gdb/patches/gdb-6.0-bdm-m68k.patch @@ -0,0 +1,2044 @@ +diff -Nru insight-5.3.92.orig/gdb/Makefile.in insight-5.3.92/gdb/Makefile.in +--- insight-5.3.92.orig/gdb/Makefile.in 2003-08-18 20:10:52.000000000 +0200 ++++ insight-5.3.92/gdb/Makefile.in 2003-09-21 09:42:16.000000000 +0200 +@@ -2135,6 +2135,8 @@ + $(remote_fileio_h) + remote-hms.o: remote-hms.c $(defs_h) $(gdbcore_h) $(target_h) $(monitor_h) \ + $(serial_h) $(regcache_h) ++remote-m68k-bdm.o: remote-m68k-bdm.c $(bfd_h) $(wait_h) $(defs_h) $(inferior_h) \ ++ $(gdbcore_h) $(target_h) + remote-mips.o: remote-mips.c $(defs_h) $(inferior_h) $(bfd_h) $(symfile_h) \ + $(gdbcmd_h) $(gdbcore_h) $(serial_h) $(target_h) $(remote_utils_h) \ + $(gdb_string_h) $(gdb_stat_h) $(regcache_h) +diff -Nru insight-5.3.92.orig/gdb/config/m68k/bdm.mt insight-5.3.92/gdb/config/m68k/bdm.mt +--- insight-5.3.92.orig/gdb/config/m68k/bdm.mt 1970-01-01 01:00:00.000000000 +0100 ++++ insight-5.3.92/gdb/config/m68k/bdm.mt 2003-09-21 09:59:56.000000000 +0200 +@@ -0,0 +1,5 @@ ++# Target: m68k bdm interface for the CPU32 and Coldfire processors. ++# ++TM_CLIBS= -L$(prefix)/lib -lBDM ++TDEPFILES= m68k-tdep.o remote-m68k-bdm.o ++TM_FILE= tm-bdm.h +diff -Nru insight-5.3.92.orig/gdb/config/m68k/tm-bdm.h insight-5.3.92/gdb/config/m68k/tm-bdm.h +--- insight-5.3.92.orig/gdb/config/m68k/tm-bdm.h 1970-01-01 01:00:00.000000000 +0100 ++++ insight-5.3.92/gdb/config/m68k/tm-bdm.h 2003-09-21 10:38:04.000000000 +0200 +@@ -0,0 +1,134 @@ ++/* ++ * Target machine description for Coldfire BDM (Moto 5200) ++ * Copyright (C) 1995 W. Eric Norum ++ * Copyright (C) 1998 Chris Johns (ccj@acm.org) ++ * ++ * Based on: ++ * 1. `A Background Debug Mode Driver Package for Motorola's ++ * 16- and 32-Bit Microcontrollers', Scott Howard, Motorola ++ * Canada, 1993. ++ * 2. `Linux device driver for public domain BDM Interface', ++ * M. Schraut, Technische Universitaet Muenchen, Lehrstuhl ++ * fuer Prozessrechner, 1995. ++ * 3. BDM support for gdb by W. Eric Norum ++ * Saskatchewan Accelerator Laboratory ++ * University of Saskatchewan ++ * 107 North Road ++ * Saskatoon, Saskatchewan, CANADA ++ * S7N 5C6 ++ * ++ * 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. ++ */ ++ ++#include "breakpoint.h" ++ ++/* ++ * Function prototypes ++ */ ++extern unsigned char *m68k_bdm_breakpoint_from_pc (CORE_ADDR *pcptr, int *lenptr); ++extern CORE_ADDR m68k_bdm_saved_pc_after_call (struct frame_info *); ++extern const char *bdm_register_name (int i); ++extern int cf_stopped_by_watchpoint (void); ++extern int cf_can_use_watchpoint (enum target_hw_bp_type type, int cnt, int ot); ++extern int cf_insert_watchpoint (CORE_ADDR addr, int len, enum target_hw_bp_type type); ++extern int cf_remove_watchpoint (CORE_ADDR addr, int len, enum target_hw_bp_type type); ++extern int cf_insert_hw_breakpoint (CORE_ADDR addr, char *shadow); ++extern int cf_remove_hw_breakpoint (CORE_ADDR addr, char *shadow); ++extern int cf_stopped_data_address (void); ++ ++ ++/* ++ * Coldfire does it for us if we use PCC to get the PC ++ */ ++#define DECR_PC_AFTER_BREAK 0 ++ ++/* ++ * We have to control this directly as the CPU32 and Coldfire have different ++ * breakpoint opcodes. ++ */ ++#define BREAKPOINT_FROM_PC m68k_bdm_breakpoint_from_pc ++ ++/* ++ * Include the generic stuff ++ */ ++#include "m68k/tm-m68k.h" ++ ++/* ++ * Override some of the generic definitions ++ */ ++ ++/* ++ * For uCLinux we need to detect we have a subroutine call ++ * which is really a trap #0. This should be caught by the ++ * the IN_SIGTRAMP handler defined above, but incase it is ++ * not we should try and catch it here. ++ */ ++ ++#undef SAVED_PC_AFTER_CALL ++#define SAVED_PC_AFTER_CALL(frame) \ ++ (m68k_bdm_saved_pc_after_call (frame)) ++ ++/* ++ * we need 40 registers for the CPU32 and Coldfire: ++ * 8 data registers ++ * 8 address registers ++ * 2 other registers (PC, PS) ++ * 22 special registers (actual set depends on architecture) ++ * 0 floating point registers ++ */ ++#undef NUM_REGS ++#undef REGISTER_BYTES ++#define NUM_REGS 40 ++#define REGISTER_BYTES (16*4 + 2*4 + 22*4) ++ ++#undef REGISTER_NAMES ++#define REGISTER_NAME(i) bdm_register_name(i) ++ ++#undef FP0_REGNUM ++#undef FPC_REGNUM ++#undef FPS_REGNUM ++#undef FPI_REGNUM ++#define FP0_REGNUM 40 /* Floating point register 0 */ ++#define FPC_REGNUM FP0_REGNUM + 8 /* 68881 control register */ ++#define FPS_REGNUM FPC_REGNUM + 1 /* 68881 status register */ ++#define FPI_REGNUM FPS_REGNUM + 1 /* 68881 iaddr register */ ++ ++/* ++ * The other definitions and macros don't need to be changed: ++ * a) The Coldfire has no floating point registers ++ * b) The REGISTER_BYTES_OK macro isn't used ++ */ ++ ++#define TARGET_HAS_HARDWARE_WATCHPOINTS ++ ++/* We need to remove watchpoints when stepping, else we hit them again! */ ++ ++#define HAVE_NONSTEPPABLE_WATCHPOINT 1 ++ ++#define STOPPED_BY_WATCHPOINT(w) (cf_stopped_by_watchpoint ()) ++ ++/* Use these macros for watchpoint insertion/deletion. */ ++/* type can be 0: write watch, 1: read watch, 2: access watch (read/write) */ ++ ++#define TARGET_CAN_USE_HARDWARE_WATCHPOINT(type, cnt, ot) \ ++ (cf_can_use_watchpoint (type, cnt, ot)) ++ ++#define target_insert_watchpoint(addr, len, type) (cf_insert_watchpoint (addr, len, type)) ++#define target_remove_watchpoint(addr, len, type) (cf_remove_watchpoint (addr, len, type)) ++#define target_insert_hw_breakpoint(addr, shadow) (cf_insert_hw_breakpoint (addr, shadow)) ++#define target_remove_hw_breakpoint(addr, shadow) (cf_remove_hw_breakpoint (addr, shadow)) ++#define target_stopped_data_address() (cf_stopped_data_address ()) +diff -Nru insight-5.3.92.orig/gdb/configure.tgt insight-5.3.92/gdb/configure.tgt +--- insight-5.3.92.orig/gdb/configure.tgt 2003-08-26 00:57:50.000000000 +0200 ++++ insight-5.3.92/gdb/configure.tgt 2003-09-21 09:42:16.000000000 +0200 +@@ -121,6 +121,8 @@ + m68000-*-sunos3*) gdb_target=sun2os3 ;; + m68000-*-sunos4*) gdb_target=sun2os4 ;; + ++m68*-bdm-*) gdb_target=bdm ;; ++ + m68*-bull-sysv*) gdb_target=dpx2 ;; + m68*-att-*) gdb_target=3b1 ;; + m68*-cisco*-*) gdb_target=cisco ;; +diff -Nru insight-5.3.92.orig/gdb/doc/gdb.texinfo insight-5.3.92/gdb/doc/gdb.texinfo +--- insight-5.3.92.orig/gdb/doc/gdb.texinfo 2003-08-09 17:10:35.000000000 +0200 ++++ insight-5.3.92/gdb/doc/gdb.texinfo 2003-09-21 09:42:16.000000000 +0200 +@@ -11773,6 +11773,7 @@ + * H8/500:: Hitachi H8/500 + * M32R/D:: Mitsubishi M32R/D + * M68K:: Motorola M68K ++* Motorola BDM:: Motorola M68K/Coldfire Background Debug Mode + * MIPS Embedded:: MIPS Embedded + * OpenRISC 1000:: OpenRisc 1000 + * PA:: HP PA Embedded +@@ -12047,6 +12048,10 @@ + @item target abug @var{dev} + ABug ROM monitor for M68K. + ++@kindex target bdm ++Background Debug Mode interface to Motorola 68k/Coldfire machine. ++@xref{Motorola BDM, ,@value{GDBN} and Motorola 68k/Coldfire BDM}. ++ + @kindex target cpu32bug + @item target cpu32bug @var{dev} + CPU32BUG monitor, running on a CPU32 (M68K) board. +@@ -12073,6 +12078,101 @@ + + @end table + ++ ++@node Motorola BDM ++@subsection @value{GDBN} and Motorola BDM ++ ++@cindex BDM ++@cindex CPU32 ++@cindex Coldfire ++Background Debug Mode (@dfn{BDM}) provides a full set of debug options ++including the ability to: ++@itemize @bullet ++@item Insert breakpoints ++@item Single-step ++@item Display register contents ++@item Display memory contents ++@item Modify register contents ++@item Modify memory contents ++@end itemize ++ ++A small interface circuit connects the BDM interface port on the ++target machine to a parallel printer port on the debugging host. ++A target system can be configured and a program downloaded and ++executed with no bootstrap memory on the target machine and no other ++connection between the debugging host and the target machine. ++ ++The @code{target} command tells @value{GDBN} ++to debug a program running on a target machine ++@xref{Target Commands, ,Commands for managing targets}. ++For example, the following command tells @value{GDBN} to use a BDM ++interface connected to a ColdFire processor and the @code{LPT0} parallel port: ++@example ++target bdm /dev/bdmcf0 ++@end example ++ ++Do not attempt to use the parallel port for any other purpose while ++@value{GDBN} is using it to control a BDM target. ++ ++Once the BDM target has been selected a few other commands become ++available: ++ ++@table @code ++@item bdm_reset ++@kindex bdm_reset ++Reset the target machine and enable BDM operation in the target. ++ ++@item bdm_restart ++@kindex bdm_restart ++Reset the target machine and disable BDM operation in the target. ++This command is useful only if the target machine has some kind of ++bootstrap memory installed. ++ ++@item bdm_status ++@kindex bdm_status ++Print the status of the target machine and the BDM interface. ++ ++@item bdm_setdelay @var{N} ++@kindex bdm_setdelay ++Some BDM interface circuits can not handle high-speed data transfer. ++This command lets you insert a delay between each BDM clock. ++The larger the value of @var{N}, the longer the delay. ++On most machines the default delay of @var{0} should work just fine. ++ ++@item bdm_setdebug @var{N} ++@kindex bdm_setdebug ++Setting the level (@var{N}) to a non-zero value turns on ++debugging messages in the BDM support library. ++ ++@item bdm_setdriverdebug @var{N} ++@kindex bdm_setdriverdebug ++Setting the level (@var{N}) to a non-zero value turns on ++debugging messages in the BDM device driver. ++ ++@end table ++ ++The registers which can be displayed and modified are: ++@itemize @bullet ++@item The data registers: @code{$d0}-@code{$d7} ++@item The address registers: @code{$a0}-@code{$a5}, @code{$fp}, @code{$sp} ++@item The program counter: @code{$pc} ++@item The status register: @code{$ps} ++@item The program counter at the beginning of the most recently executed ++instruction: @code{$pcc} ++@item The user stack pointer: @code{$usp} ++@item The supervisor stack pointer: @code{$ssp} ++@item The source function code register: @code{$sfc} ++@item The destinaton function code register: @code{$dfc} ++@item The vector base register: @code{$vbr} ++@item The fault address register: @code{$far} ++@item The BDM temporary register: @code{$atemp} ++@item The module base address register: @code{$mbar} ++@end itemize ++ ++Target processor interrupts are disabled during single-step (step, next, ++stepi, nexti) operations. ++ ++ + @node MIPS Embedded + @subsection MIPS Embedded + +diff -Nru insight-5.3.92.orig/gdb/remote-m68k-bdm.c insight-5.3.92/gdb/remote-m68k-bdm.c +--- insight-5.3.92.orig/gdb/remote-m68k-bdm.c 1970-01-01 01:00:00.000000000 +0100 ++++ insight-5.3.92/gdb/remote-m68k-bdm.c 2003-09-21 12:54:52.000000000 +0200 +@@ -0,0 +1,1730 @@ ++/* ++ * Motorola Background Debug Mode Target ++ * Copyright (C) 1995 W. Eric Norum ++ * Copyright (C) 1998 Chris Johns (ccj@acm.org) ++ * Copyright (C) 2000 Bryan Feir (bryan@sgl.crestech.ca) ++ * ++ * Based on: ++ * 1. `A Background Debug Mode Driver Package for Motorola's ++ * 16- and 32-Bit Microcontrollers', Scott Howard, Motorola ++ * Canada, 1993. ++ * 2. `Linux device driver for public domain BDM Interface', ++ * M. Schraut, Technische Universitaet Muenchen, Lehrstuhl ++ * fuer Prozessrechner, 1995. ++ * 3. BDM support for gdb by W. Eric Norum ++ * Saskatchewan Accelerator Laboratory ++ * University of Saskatchewan ++ * 107 North Road ++ * Saskatoon, Saskatchewan, CANADA ++ * S7N 5C6 ++ * 4. Coldfire support added by C Johns. ++ * 5. Hardware breakpoint support added by B Feir. ++ * ++ * 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. ++ * ++ * W. Eric Norum ++ * Saskatchewan Accelerator Laboratory ++ * University of Saskatchewan ++ * 107 North Road ++ * Saskatoon, Saskatchewan, CANADA ++ * S7N 5C6 ++ * ++ * eric@skatter.usask.ca ++ * ++ * Coldfire support by: ++ * Chris Johns ++ * Objective Design Systems ++ * 35 Cairo Street ++ * Cammeray, Sydney, 2062, Australia ++ * ++ * ccj@acm.org ++ * ++ * Coldfire hardware breakpoint support by: ++ * Bryan Feir ++ * CRESTech (Centre for Research in Earth and Space Technology) ++ * 4850 Keele Street, 1st floor ++ * Toronto, Ontario, CANADA M6E 3E5 ++ * ++ * bryan@sgl.crestech.ca ++ */ ++ ++/* ++ * $Revision: 1.3 $ $Date: 2004/03/28 23:10:39 $ $Author: codewiz $ ++ */ ++ ++#include "defs.h" ++#include "gdbcore.h" ++#include "target.h" ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "gdbcmd.h" ++#include "command.h" ++#include "inferior.h" ++#include "value.h" ++#include "breakpoint.h" ++#include "regcache.h" ++#include "BDMlib.h" ++ ++extern struct target_ops bdm_ops; /* Forward declaration */ ++ ++/* ++ * The name of the BDM driver special file ++ */ ++static char *dev_name; ++static int cpu_type; ++ ++/* ++ * The different register names for the processors. ++ */ ++static const char *cpu32plus_reg_names[NUM_REGS] = { ++ "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", ++ NULL, NULL, NULL, NULL, ++ "mbar", ++ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ++}; ++ ++static const char *cpu32_reg_names[NUM_REGS] = { ++ "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", ++ "a0", "a1", "a2", "a3", "a4", "a5", "fp", "sp", ++ "ps", "pc", ++ "pcc", "usp", "ssp", "sfc", "dfc", NULL, NULL, ++ "vbr", ++ NULL, NULL, NULL, NULL, ++ NULL, ++ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ++}; ++ ++static const char *cf_reg_names[NUM_REGS] = { ++ "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", ++ "a0", "a1", "a2", "a3", "a4", "a5", "fp", "sp", ++ "ps", "pc", ++ NULL, NULL, NULL, NULL, NULL, NULL, NULL, ++ "vbr", ++ "cacr", "acr0", "acr1", "rambar", ++ "mbar", ++ "csr", "aatr", "tdr", "pbr", "pbmr", "abhr", "ablr", "dbr", "dbmr", ++}; ++ ++static const char **bdm_reg_names = cpu32plus_reg_names; ++ ++const char *bdm_register_name(int i) ++{ ++ if ((i < 0) || (i >= NUM_REGS)) ++ return NULL; ++ return bdm_reg_names[i]; ++} ++ ++static int reg_to_dev_num[] = { ++ BDM_REG_SR, ++ BDM_REG_RPC, ++ BDM_REG_PCC, ++ BDM_REG_USP, ++ BDM_REG_SSP, ++ BDM_REG_SFC, ++ BDM_REG_DFC, ++ BDM_REG_ATEMP, ++ BDM_REG_FAR, ++ BDM_REG_VBR, ++ BDM_REG_CACR, ++ BDM_REG_ACR0, ++ BDM_REG_ACR1, ++ BDM_REG_RAMBAR, ++ BDM_REG_MBAR, ++ BDM_REG_CSR, ++ BDM_REG_AATR, ++ BDM_REG_TDR, ++ BDM_REG_PBR, ++ BDM_REG_PBMR, ++ BDM_REG_ABHR, ++ BDM_REG_ABLR, ++ BDM_REG_DBR, ++ BDM_REG_DBMR ++ }; ++ ++/* ++ * The name of the most recently loaded program ++ */ ++static char *bdm_prog_loaded; ++ ++/* ++ * Do not load the program when creating the target. ++ */ ++static int bdm_no_load; ++ ++/* ++ * default delay for interface ++ */ ++#define BDM_DEFAULT_DELAY 0 ++static int bdm_delay = -1; ++ ++/* ++ * does gdb wait or not, only valid for a Coldfire processor ++ */ ++static int bdm_gdb_no_wait = 0; ++ ++/* ++ * Hold BDM ATEMP register (CPU32 only). ++ */ ++static unsigned long atemp; ++static int haveAtemp; ++ ++static int hit_watchpoint; ++ ++/* ++ * CF BDM Debug hardware version number. ++ */ ++ ++static unsigned long cf_debug_ver; ++ ++/* ++ * Not sure if this is defined somewhere. Cannot see anywhere. ++ */ ++extern int (*ui_loop_hook) (int); ++ ++/* ++ * Forward declarations ++ */ ++static void bdm_load (char *, int); ++ ++/* ++ * give target time to come up after reset ++ * time in usec ++ */ ++#define TIME_TO_COME_UP 60000 ++ ++/* ++ * Downloader routines ++ */ ++static int downLoaderReturn; ++static int downLoaderFirst; ++static unsigned long downLoadBaseAddress, downLoadStartAddress; ++static unsigned long downLoadDataCount=0; ++static int bdmDebugLevel; ++static const char *downloadErrorString; ++ ++static void ++downloadSection (bfd *abfd, sec_ptr sec, PTR ignore) ++{ ++ unsigned long dfc; ++ unsigned long address; ++ unsigned long nleft, size; ++ int count; ++ file_ptr offset; ++ char cbuf[1024]; ++ ++ /* ++ * See if the section needs loading ++ */ ++ if (bdmDebugLevel) ++ printf_filtered ("Section flags:%#x\n", bfd_get_section_flags (abfd, sec)); ++ if ((downLoaderReturn < 0) || ++ ((bfd_get_section_flags (abfd, sec) & SEC_HAS_CONTENTS) == 0) || ++ ((bfd_get_section_flags (abfd, sec) & SEC_LOAD) == 0)) ++ return; ++ address = bfd_section_lma (abfd, sec); ++ if (bdmDebugLevel) ++ printf_filtered ("Section address:%#lx\n", address); ++ if (downLoaderFirst && (bfd_get_section_flags (abfd, sec) & SEC_CODE)) { ++ downLoadStartAddress = bfd_get_start_address (abfd); ++ downLoadBaseAddress = address; ++ downLoaderFirst = 0; ++ if (bdmDebugLevel) ++ printf_filtered ("Start address:%#lx Base address:%#lx\n", ++ downLoadStartAddress, downLoadBaseAddress); ++ } ++ ++ /* ++ * Set the appropriate destination address space ++ */ ++ if (bfd_get_section_flags (abfd, sec) & SEC_CODE) ++ dfc = 0x6; /* Supervisor program space */ ++ else ++ dfc = 0x5; /* Supervisor data space */ ++ if (bdmWriteSystemRegister (BDM_REG_DFC, dfc) < 0) { ++ downLoaderReturn = -1; ++ return; ++ } ++ ++ /* ++ * Load the section in `sizeof cbuf` chunks ++ */ ++ size = nleft = bfd_get_section_size_before_reloc (sec); ++ if (nleft == 0) ++ return; ++ ++ /* Is this really necessary? I guess it gives the user something ++ to look at during a long download. */ ++ ui_out_message (uiout, 0, "Loading section %s, size 0x%s lma 0x%s\n", ++ sec->name, paddr_nz (size), paddr_nz (address)); ++ ++ offset = 0; ++ while (nleft) { ++ if (nleft > sizeof cbuf) ++ count = sizeof cbuf; ++ else ++ count = nleft; ++ if (!bfd_get_section_contents (abfd, sec, cbuf, offset, count)) { ++ downloadErrorString = "Error reading section contents"; ++ downLoaderReturn = -1; ++ return; ++ } ++ if (bdmWriteMemory (address, cbuf, count) < 0) { ++ downLoaderReturn = -1; ++ return; ++ } ++ ++ address += count; ++ offset += count; ++ nleft -= count; ++ if (quit_flag ++ || (ui_load_progress_hook != NULL ++ && ui_load_progress_hook (sec->name, offset))) ++ error ("Canceled the download"); ++ ++ if (show_load_progress != NULL) ++ show_load_progress (sec->name, offset, size, size, size); ++ } ++ downLoadDataCount += size; ++} ++ ++/* ++ * Load an executable image into the target ++ */ ++static int ++loadExecutable (const char *name) ++{ ++ bfd *abfd; ++ unsigned long dfc; ++ unsigned long l; ++ ++ /* ++ * Make sure target is there ++ */ ++ if (!bdmCheck ()) ++ return -1; ++ ++ /* ++ * Open and verify the file ++ */ ++ bfd_init (); ++ abfd = bfd_openr (name, "default"); ++ if (abfd == NULL) { ++ downloadErrorString = bfd_errmsg (bfd_get_error()); ++ return -1; ++ } ++ if (!bfd_check_format (abfd, bfd_object)) { ++ downloadErrorString = "Not an object file"; ++ return -1; ++ } ++ ++ /* ++ * Save the destination function code register ++ */ ++ if (bdmReadSystemRegister (BDM_REG_DFC, &dfc) < 0) ++ return -1; ++ ++ /* ++ * Load each section of the executable file ++ */ ++ downLoadDataCount = 0; ++ downLoaderFirst = 1; ++ downLoaderReturn = 0; ++ bfd_map_over_sections (abfd, downloadSection, NULL); ++ if (downLoaderReturn < 0) ++ return -1; ++ ++ ui_out_text (uiout, "Start address "); ++ ui_out_field_fmt (uiout, "address", "0x%s", paddr_nz (downLoadStartAddress)); ++ ui_out_text (uiout, ", load size "); ++ ui_out_field_fmt (uiout, "load-size", "%lu", downLoadDataCount); ++ ui_out_text (uiout, "\n"); ++ ++ /* ++ * Set program counter ++ */ ++ if ((bdmWriteSystemRegister (BDM_REG_RPC, downLoadStartAddress) < 0) ++ || (bdmWriteSystemRegister (BDM_REG_DFC, dfc) < 0)) ++ return -1; ++ return 0; ++ ++ inferior_ptid = pid_to_ptid (1); ++ ++} ++ ++/* ++ * The breakpoint codes for the different processors ++ */ ++static char cpu32_breakpoint[] = {0x4a, 0xfa}; ++static char cf_breakpoint[] = {0x4a, 0xc8}; ++static char *breakpointCode; ++static int breakpointSize; ++ ++static int cf_init_watchpoints(); ++ ++#ifdef SYSCALL_TRAP ++/* Immediately after a function call, return the saved pc before the frame ++ is setup. For uCLinux which uses a TRAP #0 for a system call we need to ++ read the first long word of the stack to see if the stack frame format is ++ type 4 and the vector is 32 (0x4080), and the opcode at the PC is ++ "move.w #0x2700,sr". If it is then get the second long from the stack. */ ++ ++CORE_ADDR ++m68k_bdm_saved_pc_after_call (struct frame_info *frame) ++{ ++ unsigned int op; ++ unsigned int eframe; ++ int sp; ++ ++ sp = read_register (SP_REGNUM); ++ eframe = read_memory_integer (sp, 2); ++ op = read_memory_integer (frame->pc, 4); ++ ++ /* ++ * This test could break if some changes the syste call. ++ */ ++ ++ if (eframe == 0x4080 && op == 0x46fc2700) ++ return read_memory_integer (sp + 4, 4); ++ else ++ return read_memory_integer (sp, 4); ++} ++#endif /* SYSCALL_TRAP */ ++ ++unsigned char *m68k_bdm_breakpoint_from_pc (CORE_ADDR *pcptr, int *lenptr) ++{ ++ *lenptr = breakpointSize; ++ return breakpointCode; ++} ++ ++/* ++ * Short pause ++ */ ++static void ++nap (int microseconds) ++{ ++ struct timeval tv; ++ ++ tv.tv_sec = microseconds / 1000000; ++ tv.tv_usec = microseconds % 1000000; ++ select (0, NULL, NULL, NULL, &tv); ++} ++ ++/* ++ * Display error message and jump back to main input loop ++ */ ++static void ++bdm_report_error (void) ++{ ++ error ("BDM error: %s", bdmErrorString ()); ++} ++ ++/* ++ * Initialize bdm interface port ++ */ ++static void ++bdm_init (int tty, char *arg) ++{ ++} ++ ++/* ++ * Return interface status ++ */ ++static int ++bdm_get_status (void) ++{ ++ int status; ++ ++ if ((status = bdmStatus ()) < 0) ++ bdm_report_error (); ++ return status; ++} ++ ++static void ++bdm_get_status_interactive (int pid, char *arg) ++{ ++ printf ("BDM status: 0x%x\n", bdm_get_status ()); ++} ++ ++/* ++ * release chip: reset and disable bdm mode ++ */ ++static void ++bdm_release_chip (void) ++{ ++ haveAtemp = 0; ++ registers_changed (); ++ if (bdmRelease () < 0) ++ bdm_report_error (); ++} ++ ++/* ++ * stop chip ++ */ ++static void ++bdm_stop_chip (void) ++{ ++ if (bdmStop () < 0) ++ bdm_report_error (); ++} ++ ++/* ++ * Allow chip to resume execution ++ */ ++static void ++bdm_go (void) ++{ ++ haveAtemp = 0; ++ if (bdmGo () < 0) ++ bdm_report_error (); ++} ++ ++/* ++ * Reset chip, enter BDM mode ++ */ ++static void ++bdm_reset (void) ++{ ++ registers_changed (); ++ if (bdmReset () < 0) ++ bdm_report_error (); ++ nap (TIME_TO_COME_UP); ++} ++ ++/* ++ * step cpu32 chip: execute a single instruction ++ * This is complicated by the presence of interrupts. ++ * Consider the following sequence of events: ++ * - User attempts to `continue' from a breakpoint. ++ * - Gdb calls bdm_step_chip to single-step the instruction that ++ * had been replaced by the BGND instruction. ++ * - The target processor executes the instruction and stops. ++ * - GDB replaces the instruction with a BGND instruction to ++ * force a breakpoint the next time the instruction is hit. ++ * - GDB calls bdm_go and the target resumes execution. ++ * This all seems fine, but now consider what happens when a interrupt ++ * is pending: ++ * - User attempts to `continue' from a breakpoint. ++ * - Gdb calls bdm_step_chip to single-step the instruction that ++ * had been replaced by the BGND instruction. ++ * - The target processor does not execute the replaced instruction, ++ * but rather executes the first instruction of the interrupt ++ * service routine, then stops. ++ * - GDB replaces the instruction with a BGND instruction to ++ * force a breakpoint the next time the instruction is hit. ++ * - GDB calls bdm_go and the target resumes execution. ++ * - The target finishes off the interrupt, and upon returing from ++ * the interrupt generates another breakpoint! ++ * The solution is simple -- disable interrupts when single stepping. ++ * The problem then becomes the handling of instructions which involve ++ * the program status word! ++ */ ++static void ++bdm_step_cpu32_chip (void) ++{ ++ unsigned long pc; ++ unsigned short instruction; ++ unsigned short immediate; ++ unsigned long d7; ++ unsigned long sr; ++ unsigned long nsr; ++ enum { ++ op_other, ++ op_ANDIsr, ++ op_EORIsr, ++ op_ORIsr, ++ op_TOsr, ++ op_FROMsr, ++ op_FROMsrTOd7 ++ } op; ++ ++ /* ++ * Get the existing status register ++ */ ++ if (bdmReadSystemRegister (BDM_REG_SR, &sr) < 0) ++ bdm_report_error (); ++ ++ /* ++ * Read the instuction about to be executed ++ */ ++ if ((bdmReadSystemRegister (BDM_REG_RPC, &pc) < 0) ++ || (bdmReadWord (pc, &instruction) < 0)) ++ bdm_report_error (); ++ ++ /* ++ * See what operation is to be performed ++ */ ++ if (instruction == 0x027C) ++ op = op_ANDIsr; ++ else if (instruction == 0x0A7C) ++ op = op_EORIsr; ++ else if (instruction == 0x007C) ++ op = op_ORIsr; ++ else if (instruction == 0x40C7) ++ op = op_FROMsrTOd7; ++ else if ((instruction & 0xFFC0) == 0x40C0) ++ op = op_FROMsr; ++ else if ((instruction & 0xFFC0) == 0x46C0) ++ op = op_TOsr; ++ else ++ op = op_other; ++ ++ /* ++ * Set things up for the single-step operation ++ */ ++ switch (op) { ++ case op_FROMsr: ++ /* ++ * It's storing the SR somewhere. ++ * Store the SR in D7 and change the instruction ++ * to save D7. This fails if the addressing mode ++ * is one of the esoteric modes that uses D7 as ++ * and index register, but we'll just have to hope ++ * that doesn't happen too often. ++ */ ++ if ((bdmReadRegister (7, &d7) < 0) ++ || (bdmWriteRegister (7, sr) < 0) ++ || (bdmWriteWord (pc, 0x3007 | ++ ((instruction & 0x38) << 3) | ++ ((instruction & 0x07) << 9)) < 0)) ++ bdm_report_error (); ++ break; ++ ++ case op_ANDIsr: ++ case op_EORIsr: ++ case op_ORIsr: ++ /* ++ * It's an immediate operation to the SR -- pick up the value ++ */ ++ if (bdmReadWord (pc+2, &immediate) < 0) ++ bdm_report_error (); ++ break; ++ ++ case op_TOsr: ++ case op_other: ++ break; ++ } ++ ++ /* ++ * Ensure the step is done with interrupts disabled ++ */ ++ if (bdmWriteSystemRegister (BDM_REG_SR, sr | 0x0700) < 0) ++ bdm_report_error (); ++ ++ /* ++ * Do the single-step ++ */ ++ if (bdmStep () < 0) ++ bdm_report_error (); ++ ++ /* ++ * Get the ATEMP register since the following operations may ++ * modify it. ++ */ ++ if (bdmReadSystemRegister (BDM_REG_ATEMP, &atemp) < 0) ++ bdm_report_error (); ++ haveAtemp = 1; ++ ++ /* ++ * Clean things up ++ */ ++ switch (op) { ++ case op_FROMsr: ++ if ((bdmWriteRegister (7, d7) < 0) ++ || (bdmWriteWord (pc, instruction) < 0) ++ || (bdmWriteSystemRegister (BDM_REG_SR, sr) < 0)) ++ bdm_report_error (); ++ break; ++ ++ case op_FROMsrTOd7: ++ if ((bdmReadRegister (7, &d7) < 0) ++ || (bdmWriteRegister (7, (d7 & ~0xFFFF) | (sr & 0xFFFF)) < 0) ++ || (bdmWriteSystemRegister (BDM_REG_SR, sr) < 0)) ++ bdm_report_error (); ++ break; ++ ++ case op_ANDIsr: ++ if (bdmWriteSystemRegister (BDM_REG_SR, sr & immediate) < 0) ++ bdm_report_error (); ++ break; ++ ++ case op_EORIsr: ++ if (bdmWriteSystemRegister (BDM_REG_SR, sr ^ immediate) < 0) ++ bdm_report_error (); ++ break; ++ ++ case op_ORIsr: ++ if (bdmWriteSystemRegister (BDM_REG_SR, sr | immediate) < 0) ++ bdm_report_error (); ++ break; ++ ++ case op_TOsr: ++ break; ++ ++ case op_other: ++ if ((bdmReadSystemRegister (BDM_REG_SR, &nsr) < 0) ++ || (bdmWriteSystemRegister (BDM_REG_SR, (nsr & ~0x0700) | (sr & 0x0700)) < 0)) ++ bdm_report_error (); ++ break; ++ } ++} ++ ++static void ++bdm_step_chip (void) ++{ ++ /* ++ * The cpu32 is harder to step than the Coldfire. ++ */ ++ if (cpu_type == BDM_CPU32) { ++ bdm_step_cpu32_chip(); ++ return; ++ } ++ ++ /* ++ * Do the single-step ++ */ ++ if (bdmStep () < 0) ++ bdm_report_error (); ++} ++ ++/* ++ * true if runnable ++ */ ++static int ++bdm_can_run (void) ++{ ++ return 1; ++} ++ ++static void ++bdm_setdelay(int delay) ++{ ++ if (bdmSetDelay (delay) < 0) ++ bdm_report_error (); ++} ++ ++static void ++bdm_setdelay_interactive (char *arg, int from_tty) ++{ ++ char *dummy; ++ ++ if (!arg) { ++ if (bdm_delay >= 0) ++ printf_filtered("bdm_delay is %d", bdm_delay); ++ else ++ printf_filtered("using default delay %d", BDM_DEFAULT_DELAY); ++ } ++ else { ++ bdm_delay = strtoul(arg, &dummy, 0); ++ bdm_setdelay (bdm_delay); ++ } ++} ++ ++static void ++bdm_setdebug_interactive (char *arg, int from_tty) ++{ ++ char *dummy; ++ ++ if (arg) { ++ bdmDebugLevel = strtoul(arg, &dummy, 0); ++ bdmSetDebugFlag (bdmDebugLevel); ++ } ++ else ++ error ("Argument missing"); ++} ++ ++static void ++bdm_setdriverdebug_interactive (char *arg, int from_tty) ++{ ++ char *dummy; ++ ++ if (arg) ++ bdmSetDriverDebugFlag (strtoul(arg, &dummy, 0)); ++ else ++ error ("Argument missing"); ++} ++ ++static void ++bdm_set_no_wait (char *arg, int from_tty) ++{ ++ bdm_gdb_no_wait = 1; ++} ++ ++static void ++bdm_set_wait (char *arg, int from_tty) ++{ ++ if (cpu_type == BDM_CPU32) { ++ error ("No wait mode is not supported on a CPU32"); ++ return; ++ } ++ if (bdm_get_status ()) ++ bdm_gdb_no_wait = 0; ++ else ++ error ("The target is running, please stop first"); ++} ++ ++static void ++bdm_issue_stop (char *arg, int from_tty) ++{ ++ bdm_stop_chip (); ++} ++ ++/* ++ * Open a connection the target via bdm ++ * name is the devicename of bdm and the filename to be used ++ * used for communication. ++ */ ++static void ++bdm_open (char *name, int from_tty) ++{ ++ char *p; ++ int version; ++ unsigned long csr; ++ ++ if (bdmIsOpen ()) ++ error ("Bdm is already open, must close it first"); ++ if (name == NULL) ++ error ("Use `target bdm ' 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 the bdm port device."); ++ dev_name = savestring (name, p - name); ++ ++ target_preopen (from_tty); ++ unpush_target (&bdm_ops); ++ ++ if (bdmOpen (dev_name) < 0) ++ bdm_report_error (); ++ if (bdmStatus () & (BDM_TARGETPOWER | BDM_TARGETNC)) { ++ bdmClose (); ++ error ("Target or cable problem"); ++ } ++ ++ /* ++ * Ask the driver for it's version. ++ * We are only interested in the major number when checking the ++ * driver version number. ++ */ ++ if (bdmGetDrvVersion (&version) < 0) ++ bdm_report_error (); ++ if ((version & 0xff00) != (BDM_DRV_VERSION & 0xff00)) { ++ printf_filtered ("Incorrect driver version, looking for %i.%i"\ ++ " and found %i.%i\n", ++ BDM_DRV_VERSION >> 8, BDM_DRV_VERSION & 0xff, ++ version >> 8, version & 0xff); ++ bdmClose (); ++ error ("Can't run with wrong BDM driver"); ++ } ++ ++ /* ++ * Get the processor type. ++ */ ++ if (bdmGetProcessor (&cpu_type) < 0) ++ bdm_report_error (); ++ switch (cpu_type) { ++ case BDM_CPU32: ++ bdm_reg_names = cpu32_reg_names; ++ breakpointCode = cpu32_breakpoint; ++ breakpointSize = sizeof cpu32_breakpoint; ++ break; ++ ++ case BDM_COLDFIRE: ++ bdm_reg_names = cf_reg_names; ++ breakpointCode = cf_breakpoint; ++ breakpointSize = sizeof cf_breakpoint; ++ cf_init_watchpoints(); ++ ++ /* ++ * Read the CSR register to determine the debug module ++ * version. ++ */ ++ if (bdmReadSystemRegister (BDM_REG_CSR, &csr) < 0) ++ bdm_report_error (); ++ cf_debug_ver = (csr >> 20) & 0x0f; ++ break; ++ ++ default: ++ bdmClose (); ++ error ("Unknown processor type returned from the driver."); ++ } ++ ++ push_target (&bdm_ops); ++ ++ if (bdm_delay >= 0) ++ bdm_setdelay (bdm_delay); ++ else ++ bdm_setdelay (BDM_DEFAULT_DELAY); ++ if (from_tty) ++ printf_filtered ("Remote %s connected to %s\n", ++ target_shortname, dev_name); ++ if (cpu_type == BDM_COLDFIRE) ++ printf_filtered (" Coldfire debug module version is %ld (%s)\n", ++ cf_debug_ver, ++ cf_debug_ver == 0 ? "5206(e)" : "5307/5407(e)"); ++} ++ ++/* ++ * Terminate current application and return to system prompt. ++ * On a target, just let the program keep on running ++ */ ++static void ++bdm_kill (void) ++{ ++#ifdef BDM_GDB_RELEASE_CPU_ON_EXIT ++ if (bdm_get_status () & BDM_TARGETSTOPPED) ++ bdm_go (); ++#else ++ bdm_stop_chip (); ++ bdm_reset (); ++#endif ++ bdm_prog_loaded = 0; ++} ++ ++static void ++bdm_close (quitting) ++int quitting; ++{ ++ if (quitting) ++ bdm_kill (); ++ bdmClose (); ++} ++ ++/* ++ * _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) ++{ ++ pop_target (); /* calls bdm_close to do the real work */ ++} ++ ++/* ++ * _resume -- Tell the remote machine to resume. ++ */ ++static void ++bdm_resume (ptid_t pid, int step, enum target_signal sig) ++{ ++ if (step) ++ bdm_step_chip (); ++ else ++ bdm_go (); ++} ++ ++/* ++ * We have fallen into an exception supported by the runtime system. ++ * by executing a `breakpoint' instruction. ++ */ ++static void ++analyze_exception (struct target_waitstatus *status) ++{ ++ unsigned long pc, sp; ++ unsigned short vec; ++ char opcode[20]; /* `big enough' */ ++ ++ if (cpu_type == BDM_CPU32) { ++ if (bdmReadSystemRegister (BDM_REG_PCC, &pc) < 0) ++ bdm_report_error (); ++ } ++ else { ++ if (bdmReadSystemRegister (BDM_REG_RPC, &pc) < 0) ++ bdm_report_error (); ++ if (pc) ++ pc -= 2; ++ } ++ status->kind = TARGET_WAITKIND_STOPPED; ++ ++ /* ++ * See if it was a `breakpoint' instruction ++ */ ++ if (bdmReadMemory (pc, opcode, breakpointSize) < 0) ++ bdm_report_error (); ++ if (memcmp (breakpointCode, opcode, breakpointSize) == 0) { ++ if (bdmWriteSystemRegister (BDM_REG_RPC, pc) < 0) ++ bdm_report_error (); ++ status->value.sig = TARGET_SIGNAL_TRAP; ++ return; ++ } ++ /* ++ * FIXME: Why an illegal instruction signal ? ++ */ ++ status->value.sig = TARGET_SIGNAL_ILL; ++} ++ ++static int sigintFlag; ++static void ++bdm_signal_handler (int s) ++{ ++ sigintFlag++; ++} ++ ++/* ++ * 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) ++{ ++ unsigned long csr; ++ int bdm_stat; ++ int detach = 0; ++ int ui_count = 0; ++ void (*ofunc) (); ++ ++ hit_watchpoint = 0; ++ if (bdm_gdb_no_wait) { ++ status->kind = TARGET_WAITKIND_STOPPED; ++ status->value.sig = TARGET_SIGNAL_GRANT; ++ return null_ptid; ++ } ++ ++ status->kind = TARGET_WAITKIND_EXITED; ++ status->value.integer = 0; ++ ++ /* ++ * Catch SIGINT signals ++ */ ++ sigintFlag = 0; ++ ofunc = signal (SIGINT, bdm_signal_handler); ++ ++ /* ++ * A work around a problem with the 5206e processor. Not sure ++ * what the issue is. It could be the processor. ++ */ ++ if (cpu_type == BDM_COLDFIRE && cf_debug_ver == 0) ++ nap (10000); ++ ++ /* ++ * Wait here till the target requires service ++ */ ++ while ((bdm_stat = bdm_get_status ()) == 0) { ++ ui_count = 0; ++ while (ui_count++ < 6) { ++ nap (50000); ++ ++ /* N.B. The UI may destroy our world (for instance by calling ++ remote_stop,) in which case we want to get out of here as ++ quickly as possible. It is not safe to touch scb, since ++ someone else might have freed it. The ui_loop_hook signals that ++ we should exit by returning 1. */ ++ ++ if (ui_loop_hook) ++ detach = ui_loop_hook (0); ++ ++ if (detach || sigintFlag) ++ bdm_stop_chip (); ++ } ++ } ++ ++ signal (SIGINT, ofunc); ++ ++ /* ++ * Determine why the target stopped ++ */ ++ 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: ++ case BDM_TARGETHALT: ++ case BDM_TARGETSTOPPED | BDM_TARGETHALT: ++ if (sigintFlag) { ++ status->kind = TARGET_WAITKIND_STOPPED; ++ status->value.sig = TARGET_SIGNAL_TSTP; ++ } ++ else { ++ if (cpu_type == BDM_CPU32) { ++ if (!haveAtemp ++ && (bdmReadSystemRegister (BDM_REG_ATEMP, &atemp) < 0)) ++ bdm_report_error (); ++ switch (atemp & 0xffff) { ++ case 0xffff: /* double bus fault */ ++ status->kind = TARGET_WAITKIND_STOPPED; ++ status->value.sig = TARGET_SIGNAL_BUS; ++ break; ++ case 0x0: /* HW bkpt */ ++ status->kind = TARGET_WAITKIND_STOPPED; ++ status->value.sig = TARGET_SIGNAL_TRAP; ++ break; ++ case 0x1: /* background mode */ ++ analyze_exception (status); ++ break; ++ default: ++ printf_filtered ("bdm_wait: Unknown atemp:%#lx\n", atemp); ++ status->kind = TARGET_WAITKIND_STOPPED; ++ status->value.sig = TARGET_SIGNAL_GRANT; ++ } ++ } ++ else { ++ if (bdmReadSystemRegister (BDM_REG_CSR, &csr) < 0) ++ bdm_report_error (); ++ if (csr & 0x08000000) { /* double bus fault */ ++ status->kind = TARGET_WAITKIND_STOPPED; ++ status->value.sig = TARGET_SIGNAL_BUS; ++ } ++ else { ++ if (csr & 0x04000000) { /* hardware trigger */ ++ hit_watchpoint = 1; ++ status->kind = TARGET_WAITKIND_STOPPED; ++ status->value.sig = TARGET_SIGNAL_TRAP; ++ } ++ else { ++ if (csr & 0x01000000) { /* -BKPT signal */ ++ status->kind = TARGET_WAITKIND_STOPPED; ++ status->value.sig = TARGET_SIGNAL_TRAP; ++ } ++ else { ++ if (csr & 0x02000000) { /* HALT/software bkpt */ ++ analyze_exception (status); ++ } ++ else { ++ printf_filtered ("bdm_wait: Unknown csr:%#lx", ++ csr); ++ status->kind = TARGET_WAITKIND_STOPPED; ++ status->value.sig = TARGET_SIGNAL_GRANT; ++ } ++ } ++ } ++ } ++ } ++ } ++ break; ++ default: ++ printf_filtered ("bdm_wait: Unknown BDM status: %#x", bdm_stat); ++ break; ++ } ++ haveAtemp = 0; ++ return null_ptid; ++} ++ ++/* ++ * The following routines handle the Coldfire hardware breakpoints. Only one ++ * breakpoint supported so far, and it can be either a PC breakpoint or an ++ * address watchpoint. Unfortunately, the TARGET_CAN_USE_HARDWARE_WATCHPOINT ++ * macro only allows for bounds checking within one of the two types and not ++ * limits that cover the sum of both, so extra work is needed. ++ * ++ * (Actually, very few processors seem to have much support for that routine ++ * at all.) ++ * ++ * As a result, the way this is handled is that the can_use routine will allow ++ * the first breakpoint of either type to be added. Any further checking so ++ * that only one of the two can be used is done later when GDB actually tries ++ * to create the breakpoints, usually when the processor is restarted. ++ * ++ * We keep a local copy of the breakpoints list becasue the chain that GDB ++ * keeps isn't exported globally. ++ * ++ * While things could be simplified with only one breakpoint present, setting ++ * up more general routines allows for later expansion if newer versions of ++ * the ColdFire chip support more breakpoints at once. ++ * ++ * Also, the ColdFire supports things like multi-level triggers and triggers ++ * based on the data bus instead of just the address bus. The GDB commands ++ * don't allow for access to this, but much of it isn't necessary anyway, ++ * as GDB has its own method of handling 'breakpoint conditions' that is ++ * sufficient for most tasks. ++ */ ++ ++#define TDR_TRC_DDATA 0x00000000 ++#define TDR_TRC_HALT 0x40000000 ++#define TDR_TRC_DINT 0x80000000 ++#define TDR_L2_EBL 0x20000000 ++#define TDR_L2_ALL 0x1FFF0000 ++#define TDR_L2_EDLW 0x10000000 ++#define TDR_L2_EDWL 0x08000000 ++#define TDR_L2_EDWU 0x04000000 ++#define TDR_L2_EDLL 0x02000000 ++#define TDR_L2_EDLM 0x01000000 ++#define TDR_L2_EDUM 0x00800000 ++#define TDR_L2_EDUU 0x00400000 ++#define TDR_L2_DI 0x00200000 ++#define TDR_L2_EAI 0x00100000 ++#define TDR_L2_EAR 0x00080000 ++#define TDR_L2_EAL 0x00040000 ++#define TDR_L2_EPC 0x00020000 ++#define TDR_L2_PCI 0x00010000 ++#define TDR_L1_EBL 0x00002000 ++#define TDR_L1_ALL 0x00001FFF ++#define TDR_L1_EDLW 0x00001000 ++#define TDR_L1_EDWL 0x00000800 ++#define TDR_L1_EDWU 0x00000400 ++#define TDR_L1_EDLL 0x00000200 ++#define TDR_L1_EDLM 0x00000100 ++#define TDR_L1_EDUM 0x00000080 ++#define TDR_L1_EDUU 0x00000040 ++#define TDR_L1_DI 0x00000020 ++#define TDR_L1_EAI 0x00000010 ++#define TDR_L1_EAR 0x00000008 ++#define TDR_L1_EAL 0x00000004 ++#define TDR_L1_EPC 0x00000002 ++#define TDR_L1_PCI 0x00000001 ++ ++struct cf_break { ++ enum target_hw_bp_type type; ++ CORE_ADDR addr; ++ int len; ++}; ++ ++#define CF_BREAKPOINT_MAX 1 ++ ++static struct cf_break cf_breakpoints[CF_BREAKPOINT_MAX]; ++static int cf_breakpoint_count; ++ ++static int ++cf_init_watchpoints(void) ++{ ++ if (cpu_type != BDM_COLDFIRE) { ++ return(-1); ++ } ++ cf_breakpoint_count = 0; ++ if (bdmWriteSystemRegister (BDM_REG_TDR, TDR_TRC_HALT) < 0) ++ bdm_report_error (); ++ return(0); ++} ++ ++int ++cf_stopped_by_watchpoint(void) ++{ ++ return hit_watchpoint; ++} ++ ++int ++cf_can_use_watchpoint(enum target_hw_bp_type type, int cnt, int ot) ++{ ++ unsigned long tdr; ++ ++ if (cpu_type != BDM_COLDFIRE) { ++ return(0); ++ } ++ ++ if (type == bp_hardware_breakpoint || type == bp_read_watchpoint || ++ type == bp_hardware_watchpoint || type == bp_access_watchpoint) { ++ if (cnt <= 1) { ++ return(1); ++ } ++ } ++ ++ return(-1); ++} ++ ++int ++cf_insert_hw_breakpoint(CORE_ADDR addr, char *shadow) ++{ ++ unsigned long tdr; ++ ++ if (cpu_type != BDM_COLDFIRE) { ++ return(-1); ++ } ++ ++ if (cf_breakpoint_count < CF_BREAKPOINT_MAX) { ++ cf_breakpoints[cf_breakpoint_count].type = hw_execute; ++ cf_breakpoints[cf_breakpoint_count].addr = addr; ++ cf_breakpoints[cf_breakpoint_count++].len = 2; ++ ++ if (bdmReadSystemRegister (BDM_REG_TDR, &tdr) < 0) ++ bdm_report_error (); ++ tdr = ((tdr & ~TDR_L1_ALL) | (TDR_L1_EBL|TDR_L1_EPC)); ++ if (bdmWriteSystemRegister (BDM_REG_PBR, addr) < 0) ++ bdm_report_error (); ++ if (bdmWriteSystemRegister (BDM_REG_PBMR, 0) < 0) ++ bdm_report_error (); ++ if (bdmWriteSystemRegister (BDM_REG_TDR, tdr) < 0) ++ bdm_report_error (); ++ if (bdmDebugLevel) ++ printf_filtered ("Insert PC Breakpoint @0x%08lx\n", addr); ++ } ++ else { ++ return(-1); ++ } ++ return(0); ++} ++ ++static int ++cf_check_breakpoint(type, addr, len) ++ enum target_hw_bp_type type; ++ CORE_ADDR addr; ++ int len; ++{ ++ int i; ++ ++ for (i = 0; i < cf_breakpoint_count; i++) { ++ if (cf_breakpoints[i].type == type && ++ cf_breakpoints[i].addr == addr && ++ cf_breakpoints[i].len == len) { ++ for (; i < CF_BREAKPOINT_MAX-1; i++) { ++ cf_breakpoints[i] = cf_breakpoints[i+1]; ++ } ++ cf_breakpoint_count--; ++ return(1); ++ } ++ } ++ return(0); ++} ++ ++int ++cf_remove_hw_breakpoint(CORE_ADDR addr, char *shadow) ++{ ++ unsigned long tdr; ++ unsigned long csr; ++ ++ if (cpu_type != BDM_COLDFIRE) { ++ return(-1); ++ } ++ ++ if (cf_check_breakpoint(hw_execute, addr, 2)) { ++ if (bdmReadSystemRegister (BDM_REG_TDR, &tdr) < 0) ++ bdm_report_error (); ++ tdr &= ~TDR_L1_EPC; ++ if ((tdr & TDR_L1_ALL) == 0) { ++ tdr &= ~TDR_L1_EBL; ++ } ++ if (bdmWriteSystemRegister (BDM_REG_TDR, tdr) < 0) ++ bdm_report_error (); ++ if (bdmDebugLevel) ++ printf_filtered ("Remove PC Breakpoint @0x%08lx\n", addr); ++ } ++ else { ++ return(-1); ++ } ++ return(0); ++} ++ ++#define AATR_READONLY 0x7F85 ++#define AATR_WRITEONLY 0x7F05 ++#define AATR_READWRITE 0xFF05 ++ ++int ++cf_insert_watchpoint(CORE_ADDR addr, int len, enum target_hw_bp_type type) ++{ ++ unsigned long tdr; ++ ++ if (cpu_type != BDM_COLDFIRE) { ++ return(-1); ++ } ++ ++ if (cf_breakpoint_count < CF_BREAKPOINT_MAX) { ++ cf_breakpoints[cf_breakpoint_count].type = type; ++ cf_breakpoints[cf_breakpoint_count].addr = addr; ++ cf_breakpoints[cf_breakpoint_count++].len = len; ++ ++ if (bdmReadSystemRegister (BDM_REG_TDR, &tdr) < 0) ++ bdm_report_error (); ++ tdr = ((tdr & ~TDR_L1_ALL) | (TDR_L1_EBL|TDR_L1_EAR)); ++ if (bdmWriteSystemRegister (BDM_REG_ABLR, addr) < 0) ++ bdm_report_error (); ++ if (bdmWriteSystemRegister (BDM_REG_ABHR, addr+len-1) < 0) ++ bdm_report_error (); ++ if (type == hw_read) { ++ if (bdmWriteSystemRegister (BDM_REG_AATR, AATR_READONLY) < 0) ++ bdm_report_error (); ++ if (bdmDebugLevel) ++ printf_filtered ("Insert read Watchpoint @0x%08lx-0x%08lx\n", ++ addr, addr+len-1); ++ } ++ else if (type == hw_write) { ++ if (bdmWriteSystemRegister (BDM_REG_AATR, AATR_WRITEONLY) < 0) ++ bdm_report_error (); ++ if (bdmDebugLevel) ++ printf_filtered ("Insert write Watchpoint @0x%08lx-0x%08lx\n", ++ (long unsigned int)addr, addr+len-1); ++ } ++ else { ++ if (bdmWriteSystemRegister (BDM_REG_AATR, AATR_READWRITE) < 0) ++ bdm_report_error (); ++ if (bdmDebugLevel) ++ printf_filtered ("Insert access Watchpoint @0x%08lx-0x%08lx\n", ++ addr, addr+len-1); ++ } ++ if (bdmWriteSystemRegister (BDM_REG_TDR, tdr) < 0) ++ bdm_report_error (); ++ } ++ else { ++ return(-1); ++ } ++ return(0); ++} ++ ++int ++cf_remove_watchpoint(CORE_ADDR addr, int len, enum target_hw_bp_type type) ++{ ++ unsigned long tdr; ++ unsigned long csr; ++ ++ if (cpu_type != BDM_COLDFIRE) { ++ return(-1); ++ } ++ ++ if (cf_check_breakpoint(type, addr, len)) { ++ if (bdmReadSystemRegister (BDM_REG_TDR, &tdr) < 0) ++ bdm_report_error (); ++ tdr &= ~TDR_L1_EAR; ++ if ((tdr & TDR_L1_ALL) == 0) { ++ tdr &= ~TDR_L1_EBL; ++ } ++ if (bdmWriteSystemRegister (BDM_REG_TDR, tdr) < 0) ++ bdm_report_error (); ++ if (bdmDebugLevel) ++ printf_filtered ("Remove %s Watchpoint @0x%08lx-0x%08lx\n", ++ (type == hw_read) ? "read" : ++ ((type == hw_write) ? "write" : "access"), ++ addr, addr+len-1); ++ } ++ else { ++ return(-1); ++ } ++ return(0); ++} ++ ++int ++cf_stopped_data_address(void) ++{ ++ unsigned long tdr; ++ unsigned long ablr; ++ ++ if (cpu_type != BDM_COLDFIRE) { ++ return(-1); ++ } ++ ++ if (bdmReadSystemRegister (BDM_REG_TDR, &tdr) < 0) ++ bdm_report_error (); ++ if (bdmReadSystemRegister (BDM_REG_ABLR, &ablr) < 0) ++ bdm_report_error (); ++ ++ if (tdr & TDR_L1_EAR) { ++ return(ablr); ++ } ++ return(0); ++} ++ ++/* 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; ++ unsigned long entry_pt; ++ ++ clear_proceed_status (); ++ init_wait_for_inferior (); ++ if (*args) { ++ prg_file = args; ++ } ++ else { ++ prg_file = execfile; ++ } ++ if (!(prg_file) && !(bdm_prog_loaded)) ++ error ("No program specified to run\n"); ++ else ++ { ++ if (!bdm_no_load) { ++ if (bdm_prog_loaded) ++ printf_filtered ("Note: `%s' has already been loaded.\n", ++ bdm_prog_loaded); ++ if (query ("Do you want to download `%s'?", prg_file)) ++ bdm_load (prg_file, 0); ++ if (bdmReadSystemRegister (BDM_REG_RPC, &entry_pt) < 0) ++ bdm_report_error (); ++ } ++ proceed (entry_pt, TARGET_SIGNAL_DEFAULT, 0); ++ } ++ inferior_ptid = pid_to_ptid (1); ++} ++ ++/* ++ * Fetch register REGNO, or all user registers if REGNO is -1. ++ */ ++static void ++bdm_fetch_register (int regno) ++{ ++ unsigned long l; ++ char cbuf[4]; ++ int ret; ++ ++ if (regno < 0) { ++ for (regno = 0 ; regno < NUM_REGS ; regno++) ++ bdm_fetch_register (regno); ++ } ++ else { ++ /* ++ * When the target is running the ++ * cpu registers can not be accessed. ++ */ ++ if (bdm_gdb_no_wait && (bdm_get_status () == 0)) { ++ l = 0; ++ ret = 0; ++ } ++ else { ++ if (regno < 16) { ++ ret = bdmReadRegister (regno, &l); ++ } ++ else { ++ if ((regno - 16) < (sizeof (reg_to_dev_num) / sizeof (int))) { ++ ret = bdmReadSystemRegister (reg_to_dev_num[regno - 16], &l); ++ } ++ else { ++ error ("Bad register number (%d)", regno); ++ return; ++ } ++ } ++ } ++ if (ret < 0) ++ bdm_report_error (); ++ cbuf[0] = l >> 24; ++ cbuf[1] = l >> 16; ++ cbuf[2] = l >> 8; ++ cbuf[3] = l; ++ supply_register (regno, cbuf); ++ } ++} ++ ++void ++bdm_prepare_to_store (void) ++{ ++ /* Do nothing, since we can store individual regs */ ++} ++ ++/* ++ * Store register REGNO, or all user registers if REGNO == -1. ++ */ ++void ++bdm_store_register (int regno) ++{ ++ unsigned long l; ++ int ret; ++ ++ if (bdm_gdb_no_wait && (bdm_get_status () == 0)) ++ return; ++ ++ if (regno == -1) { ++ for (regno = 0 ; regno < NUM_REGS ; regno++) ++ bdm_store_register (regno); ++ } ++ else { ++ l = read_register (regno); ++ if (regno < 16) { ++ ret = bdmWriteRegister (regno, l); ++ } ++ else { ++ if ((regno - 16) < (sizeof (reg_to_dev_num) / sizeof (int))) { ++ ret = bdmWriteSystemRegister (reg_to_dev_num[regno - 16], l); ++ } ++ else { ++ error ("Bad register number (%d)", regno); ++ return; ++ } ++ } ++ if (ret < 0) ++ bdm_report_error (); ++ } ++} ++ ++/* ++ * Transfer memory contents between target and host ++ */ ++static int ++bdm_xfer_inferior_memory (CORE_ADDR memaddr, char *myaddr, ++ int len, int write, ++ struct mem_attrib *attrib, ++ struct target_ops *t) ++{ ++ int ret; ++ ++ if (write) ++ ret = bdmWriteMemory (memaddr, myaddr, len); ++ else ++ ret = bdmReadMemory (memaddr, myaddr, len); ++ if (ret < 0) ++ bdm_report_error (); ++ return len; ++} ++ ++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"); ++ } ++} ++ ++/* ++ * Load a file. ++ */ ++static void ++bdm_load (char *args, int from_tty) ++{ ++ char *p; ++ ++ if (bdm_prog_loaded) { ++ free (bdm_prog_loaded); ++ bdm_prog_loaded = NULL; ++ } ++ if (!args) { ++ error ( ++ "The bdmload command must include the filename to load.\n" ++ "You may want to use 'run', which uses the file given\n" ++ "on the command line when gdb was invoked."); ++ } ++ if ((bdm_get_status () & BDM_TARGETSTOPPED) == 0) ++ bdm_stop_chip (); ++ ++ /* strip off additional (unwanted) arguments after file name */ ++ for (p = args; (*p != '\0') && (!isspace (*p)); p++) ; ++ *p = '\0'; ++ ++ if (loadExecutable (args) < 0) ++ error ("%s", downloadErrorString); ++ bdm_prog_loaded = savestring (args, strlen (args)); ++} ++ ++/* ++ * Toggle the no load variable. ++ */ ++static void ++bdm_toggle_no_load (char *args, int from_tty) ++{ ++ if (bdm_no_load) { ++ bdm_no_load = 0; ++ printf_filtered ("Image not loaded on run\n"); ++ } ++ else { ++ bdm_no_load = 1; ++ printf_filtered ("Image loaded on run\n"); ++ } ++} ++ ++/* ++ * Select a CPU32 processor register set. ++ */ ++static void ++bdm_select_cpu32 (char *args, int from_tty) ++{ ++ bdm_reg_names = cpu32_reg_names; ++} ++ ++struct target_ops bdm_ops; ++ ++static void ++init_bdm_ops(void) ++{ ++ bdm_ops.to_shortname = "bdm"; ++ bdm_ops.to_longname = "CPU32 and Coldfire Background Debug Mode Interface for downloading and remote debugging"; ++ bdm_ops.to_doc = "Uses the Public Domain Background Debug Mode Interface connected to the\n" ++"BDM-port of the CPU32 or Coldfire based microcontroller and to a parallel port\n" ++"of the PC.\n" ++"Usage: target bdm \n" ++"where is the BDM character special file (e.g. /dev/bdm0)."; ++ bdm_ops.to_open = bdm_open; ++ bdm_ops.to_close = bdm_close; ++ bdm_ops.to_detach = bdm_detach; ++ bdm_ops.to_resume = bdm_resume; ++ bdm_ops.to_wait = bdm_wait; ++ 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 = memory_insert_breakpoint; ++ bdm_ops.to_remove_breakpoint = memory_remove_breakpoint; ++ bdm_ops.to_kill = bdm_kill; ++ bdm_ops.to_load = bdm_load; ++ bdm_ops.to_stop = bdm_stop_chip; ++ bdm_ops.to_create_inferior = bdm_create_inferior; ++ bdm_ops.to_mourn_inferior = generic_mourn_inferior; ++ bdm_ops.to_can_run = bdm_can_run; ++ bdm_ops.to_stratum = process_stratum; ++ 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; ++ bdm_ops.to_magic = OPS_MAGIC; ++}; ++ ++void ++_initialize_remote_bdmcf (void) ++{ ++ init_bdm_ops (); ++ add_com ("bdm_reset", class_obscure, ++ (void (*)(char *, int))bdm_reset, ++ "Reset target and enter BDM mode."); ++ add_com ("bdm_release", class_obscure, ++ (void (*)(char *, int))bdm_release_chip, ++ "Reset target without BDM-mode."); ++ add_com ("bdm_status", class_obscure, ++ (void (*)(char *, int))bdm_get_status_interactive, ++ "Show status of bdm interface\n"); ++ add_com ("bdm_setdelay", class_obscure, ++ bdm_setdelay_interactive, ++ "set delay for download"); ++ add_com ("bdm_setdebug", class_obscure, ++ bdm_setdebug_interactive, ++ "enable/disable BDM diagnostic messages"); ++ add_com ("bdm_setdriverdebug", class_obscure, ++ bdm_setdriverdebug_interactive, ++ "enable/disable BDM driver diagnostic messages"); ++ add_com ("bdm_no_wait", class_obscure, ++ bdm_set_no_wait, ++ "Cause GDB to not wait for the target to stop when running."); ++ add_com ("bdm_wait", class_obscure, ++ bdm_set_wait, ++ "Cause GDB to wait for the target to stop when running."); ++ add_com ("bdm_stop", class_obscure, ++ bdm_issue_stop, ++ "Stop the target if running."); ++ add_com ("bdm-select-cpu32", class_obscure, ++ bdm_select_cpu32, ++ "Selects the CPU32 register set rather than the default CPU32+."); ++ add_com ("bdm-no-load", class_obscure, ++ bdm_toggle_no_load, ++ "Toggle the loading of the program to memory when asked to run."); ++ ++ add_target (&bdm_ops); ++} +diff -Nru insight-5.3.92.orig/gdb/infcmd.c insight-5.3.92/gdb/infcmd.c +--- insight-5.3.92.orig/gdb/infcmd.c 2003-11-18 23:46:48.000000000 +0100 ++++ insight-5.3.92/gdb/infcmd.c 2003-11-19 10:19:02.000000000 +0100 +@@ -1271,8 +1271,10 @@ + "finish_command: function has no target type"); + + /* FIXME: Shouldn't we do the cleanups before returning? */ +- if (TYPE_CODE (value_type) == TYPE_CODE_VOID) ++ if (TYPE_CODE (value_type) == TYPE_CODE_VOID) { ++ do_cleanups (old_chain); + return; ++ } + + funcaddr = BLOCK_START (SYMBOL_BLOCK_VALUE (function)); + diff --git a/gdb/patches/gdb-6.1-bdm-m68k.patch b/gdb/patches/gdb-6.1-bdm-m68k.patch new file mode 100644 index 0000000..facb925 --- /dev/null +++ b/gdb/patches/gdb-6.1-bdm-m68k.patch @@ -0,0 +1,2204 @@ +diff -Nru gdb-6.1/gdb/config/m68k/bdm.mt gdb-6.1-1/gdb/config/m68k/bdm.mt +--- gdb-6.1/gdb/config/m68k/bdm.mt 1970-01-01 10:00:00.000000000 +1000 ++++ gdb-6.1-1/gdb/config/m68k/bdm.mt 2004-05-30 16:17:18.000000000 +1000 +@@ -0,0 +1,5 @@ ++# Target: m68k bdm interface for the CPU32 and Coldfire processors. ++# ++TM_CLIBS= -L$(prefix)/lib -lBDM ++TDEPFILES= m68k-tdep.o remote-m68k-bdm.o ++TM_FILE= tm-bdm.h +diff -Nru gdb-6.1/gdb/config/m68k/tm-bdm.h gdb-6.1-1/gdb/config/m68k/tm-bdm.h +--- gdb-6.1/gdb/config/m68k/tm-bdm.h 1970-01-01 10:00:00.000000000 +1000 ++++ gdb-6.1-1/gdb/config/m68k/tm-bdm.h 2004-05-30 16:49:38.000000000 +1000 +@@ -0,0 +1,135 @@ ++/* ++ * Target machine description for Coldfire BDM (Moto 5200) ++ * Copyright (C) 1995 W. Eric Norum ++ * Copyright (C) 1998 Chris Johns (ccj@acm.org) ++ * ++ * Based on: ++ * 1. `A Background Debug Mode Driver Package for Motorola's ++ * 16- and 32-Bit Microcontrollers', Scott Howard, Motorola ++ * Canada, 1993. ++ * 2. `Linux device driver for public domain BDM Interface', ++ * M. Schraut, Technische Universitaet Muenchen, Lehrstuhl ++ * fuer Prozessrechner, 1995. ++ * 3. BDM support for gdb by W. Eric Norum ++ * Saskatchewan Accelerator Laboratory ++ * University of Saskatchewan ++ * 107 North Road ++ * Saskatoon, Saskatchewan, CANADA ++ * S7N 5C6 ++ * ++ * 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. ++ */ ++ ++#include "breakpoint.h" ++ ++/* ++ * Function prototypes ++ */ ++extern unsigned char *m68k_bdm_breakpoint_from_pc (CORE_ADDR *pcptr, int *lenptr); ++extern CORE_ADDR m68k_bdm_saved_pc_after_call (struct frame_info *); ++extern const char *bdm_register_name (int i); ++extern int cf_stopped_by_watchpoint (void); ++extern int cf_can_use_watchpoint (enum target_hw_bp_type type, int cnt, int ot); ++extern int cf_insert_watchpoint (CORE_ADDR addr, int len, enum target_hw_bp_type type); ++extern int cf_remove_watchpoint (CORE_ADDR addr, int len, enum target_hw_bp_type type); ++extern int cf_insert_hw_breakpoint (CORE_ADDR addr, char *shadow); ++extern int cf_remove_hw_breakpoint (CORE_ADDR addr, char *shadow); ++extern int cf_stopped_data_address (void); ++ ++ ++/* ++ * Coldfire does it for us if we use PCC to get the PC ++ */ ++#define DECR_PC_AFTER_BREAK 0 ++ ++/* ++ * We have to control this directly as the CPU32 and Coldfire have different ++ * breakpoint opcodes. ++ */ ++#define BREAKPOINT_FROM_PC m68k_bdm_breakpoint_from_pc ++ ++/* ++ * Include the generic stuff ++ */ ++#include "m68k/tm-m68k.h" ++ ++/* ++ * Override some of the generic definitions ++ */ ++ ++/* ++ * For uCLinux we need to detect we have a subroutine call ++ * which is really a trap #0. This should be caught by the ++ * the IN_SIGTRAMP handler defined above, but incase it is ++ * not we should try and catch it here. ++ */ ++ ++#undef SAVED_PC_AFTER_CALL ++#define SAVED_PC_AFTER_CALL(frame) \ ++ (m68k_bdm_saved_pc_after_call (frame)) ++ ++/* ++ * we need 40 registers for the CPU32 and Coldfire: ++ * 8 data registers ++ * 8 address registers ++ * 2 other registers (PC, PS) ++ * 8 EMAC registers ++ * 22 special registers (actual set depends on architecture) ++ * 0 floating point registers ++ */ ++#undef NUM_REGS ++#undef REGISTER_BYTES ++#define NUM_REGS 48 ++#define REGISTER_BYTES (16*4 + 2*4 + 8*4 + 22*4) ++ ++#undef REGISTER_NAMES ++#define REGISTER_NAME(i) bdm_register_name(i) ++ ++#undef FP0_REGNUM ++#undef FPC_REGNUM ++#undef FPS_REGNUM ++#undef FPI_REGNUM ++#define FP0_REGNUM NUM_REGS /* Floating point register 0 */ ++#define FPC_REGNUM FP0_REGNUM + 8 /* 68881 control register */ ++#define FPS_REGNUM FPC_REGNUM + 1 /* 68881 status register */ ++#define FPI_REGNUM FPS_REGNUM + 1 /* 68881 iaddr register */ ++ ++/* ++ * The other definitions and macros don't need to be changed: ++ * a) The Coldfire has no floating point registers ++ * b) The REGISTER_BYTES_OK macro isn't used ++ */ ++ ++#define TARGET_HAS_HARDWARE_WATCHPOINTS ++ ++/* We need to remove watchpoints when stepping, else we hit them again! */ ++ ++#define HAVE_NONSTEPPABLE_WATCHPOINT 1 ++ ++#define STOPPED_BY_WATCHPOINT(w) (cf_stopped_by_watchpoint ()) ++ ++/* Use these macros for watchpoint insertion/deletion. */ ++/* type can be 0: write watch, 1: read watch, 2: access watch (read/write) */ ++ ++#define TARGET_CAN_USE_HARDWARE_WATCHPOINT(type, cnt, ot) \ ++ (cf_can_use_watchpoint (type, cnt, ot)) ++ ++#define target_insert_watchpoint(addr, len, type) (cf_insert_watchpoint (addr, len, type)) ++#define target_remove_watchpoint(addr, len, type) (cf_remove_watchpoint (addr, len, type)) ++#define target_insert_hw_breakpoint(addr, shadow) (cf_insert_hw_breakpoint (addr, shadow)) ++#define target_remove_hw_breakpoint(addr, shadow) (cf_remove_hw_breakpoint (addr, shadow)) ++#define target_stopped_data_address() (cf_stopped_data_address ()) +diff -Nru gdb-6.1/gdb/configure.tgt gdb-6.1-1/gdb/configure.tgt +--- gdb-6.1/gdb/configure.tgt 2004-05-30 16:08:34.000000000 +1000 ++++ gdb-6.1-1/gdb/configure.tgt 2004-05-30 16:30:38.000000000 +1000 +@@ -111,6 +111,7 @@ + # OBSOLETE m68000-*-sunos3*) gdb_target=sun2os3 ;; + # OBSOLETE m68000-*-sunos4*) gdb_target=sun2os4 ;; + ++m68*-bdm-*) gdb_target=bdm ;; + # OBSOLETE m68*-bull-sysv*) gdb_target=dpx2 ;; + # OBSOLETE m68*-att-*) gdb_target=3b1 ;; + m68*-cisco*-*) gdb_target=cisco ;; +diff -Nru gdb-6.1/gdb/doc/gdb.texinfo gdb-6.1-1/gdb/doc/gdb.texinfo +--- gdb-6.1/gdb/doc/gdb.texinfo 2004-05-30 16:08:36.000000000 +1000 ++++ gdb-6.1-1/gdb/doc/gdb.texinfo 2004-05-30 16:17:18.000000000 +1000 +@@ -11979,6 +11979,7 @@ + * H8/500:: Renesas H8/500 + * M32R/D:: Renesas M32R/D + * M68K:: Motorola M68K ++* Motorola BDM:: Motorola M68K/Coldfire Background Debug Mode + * MIPS Embedded:: MIPS Embedded + * OpenRISC 1000:: OpenRisc 1000 + * PA:: HP PA Embedded +@@ -12257,6 +12258,10 @@ + @item target abug @var{dev} + ABug ROM monitor for M68K. + ++@kindex target bdm ++Background Debug Mode interface to Motorola 68k/Coldfire machine. ++@xref{Motorola BDM, ,@value{GDBN} and Motorola 68k/Coldfire BDM}. ++ + @kindex target cpu32bug + @item target cpu32bug @var{dev} + CPU32BUG monitor, running on a CPU32 (M68K) board. +@@ -12283,6 +12288,101 @@ + + @end table + ++ ++@node Motorola BDM ++@subsection @value{GDBN} and Motorola BDM ++ ++@cindex BDM ++@cindex CPU32 ++@cindex Coldfire ++Background Debug Mode (@dfn{BDM}) provides a full set of debug options ++including the ability to: ++@itemize @bullet ++@item Insert breakpoints ++@item Single-step ++@item Display register contents ++@item Display memory contents ++@item Modify register contents ++@item Modify memory contents ++@end itemize ++ ++A small interface circuit connects the BDM interface port on the ++target machine to a parallel printer port on the debugging host. ++A target system can be configured and a program downloaded and ++executed with no bootstrap memory on the target machine and no other ++connection between the debugging host and the target machine. ++ ++The @code{target} command tells @value{GDBN} ++to debug a program running on a target machine ++@xref{Target Commands, ,Commands for managing targets}. ++For example, the following command tells @value{GDBN} to use a BDM ++interface connected to a ColdFire processor and the @code{LPT0} parallel port: ++@example ++target bdm /dev/bdmcf0 ++@end example ++ ++Do not attempt to use the parallel port for any other purpose while ++@value{GDBN} is using it to control a BDM target. ++ ++Once the BDM target has been selected a few other commands become ++available: ++ ++@table @code ++@item bdm_reset ++@kindex bdm_reset ++Reset the target machine and enable BDM operation in the target. ++ ++@item bdm_restart ++@kindex bdm_restart ++Reset the target machine and disable BDM operation in the target. ++This command is useful only if the target machine has some kind of ++bootstrap memory installed. ++ ++@item bdm_status ++@kindex bdm_status ++Print the status of the target machine and the BDM interface. ++ ++@item bdm_setdelay @var{N} ++@kindex bdm_setdelay ++Some BDM interface circuits can not handle high-speed data transfer. ++This command lets you insert a delay between each BDM clock. ++The larger the value of @var{N}, the longer the delay. ++On most machines the default delay of @var{0} should work just fine. ++ ++@item bdm_setdebug @var{N} ++@kindex bdm_setdebug ++Setting the level (@var{N}) to a non-zero value turns on ++debugging messages in the BDM support library. ++ ++@item bdm_setdriverdebug @var{N} ++@kindex bdm_setdriverdebug ++Setting the level (@var{N}) to a non-zero value turns on ++debugging messages in the BDM device driver. ++ ++@end table ++ ++The registers which can be displayed and modified are: ++@itemize @bullet ++@item The data registers: @code{$d0}-@code{$d7} ++@item The address registers: @code{$a0}-@code{$a5}, @code{$fp}, @code{$sp} ++@item The program counter: @code{$pc} ++@item The status register: @code{$ps} ++@item The program counter at the beginning of the most recently executed ++instruction: @code{$pcc} ++@item The user stack pointer: @code{$usp} ++@item The supervisor stack pointer: @code{$ssp} ++@item The source function code register: @code{$sfc} ++@item The destinaton function code register: @code{$dfc} ++@item The vector base register: @code{$vbr} ++@item The fault address register: @code{$far} ++@item The BDM temporary register: @code{$atemp} ++@item The module base address register: @code{$mbar} ++@end itemize ++ ++Target processor interrupts are disabled during single-step (step, next, ++stepi, nexti) operations. ++ ++ + @node MIPS Embedded + @subsection MIPS Embedded + +diff -Nru gdb-6.1/gdb/infcmd.c gdb-6.1-1/gdb/infcmd.c +--- gdb-6.1/gdb/infcmd.c 2004-05-30 16:08:35.000000000 +1000 ++++ gdb-6.1-1/gdb/infcmd.c 2004-05-30 16:33:25.000000000 +1000 +@@ -1281,8 +1281,10 @@ + "finish_command: function has no target type"); + + /* FIXME: Shouldn't we do the cleanups before returning? */ +- if (TYPE_CODE (value_type) == TYPE_CODE_VOID) ++ if (TYPE_CODE (value_type) == TYPE_CODE_VOID) { ++ do_cleanups (old_chain); + return; ++ } + + CHECK_TYPEDEF (value_type); + gcc_compiled = BLOCK_GCC_COMPILED (SYMBOL_BLOCK_VALUE (function)); +diff -Nru gdb-6.1/gdb/Makefile.in gdb-6.1-1/gdb/Makefile.in +--- gdb-6.1/gdb/Makefile.in 2004-05-30 16:08:33.000000000 +1000 ++++ gdb-6.1-1/gdb/Makefile.in 2004-05-30 16:28:15.000000000 +1000 +@@ -1343,7 +1343,7 @@ + ppcnbsd-nat.o ppcnbsd-tdep.o \ + procfs.c \ + remote-e7000.c \ +- remote-hms.c remote-m32r-sdi.c remote-mips.c \ ++ remote-hms.c remote-m32r-sdi.c remote-m68k-bdm.c remote-mips.c \ + remote-rdp.c remote-sim.c \ + remote-st.c remote-utils.c dcache.c \ + remote-vx.c \ +@@ -2187,6 +2187,8 @@ + $(serial_h) $(regcache_h) + remote-m32r-sdi.o: remote-m32r-sdi.c $(defs_h) $(gdbcmd_h) $(gdbcore_h) \ + $(inferior_h) $(target_h) $(regcache_h) $(gdb_string_h) $(serial_h) ++remote-m68k-bdm.o: remote-m68k-bdm.c $(defs_h) $(gdbcmd_h) $(gdbcore_h) \ ++ $(defs_h) $(inferior_h) $(target_h) $(wait_h) + remote-mips.o: remote-mips.c $(defs_h) $(inferior_h) $(bfd_h) $(symfile_h) \ + $(gdbcmd_h) $(gdbcore_h) $(serial_h) $(target_h) $(remote_utils_h) \ + $(gdb_string_h) $(gdb_stat_h) $(regcache_h) $(mips_tdep_h) +diff -Nru gdb-6.1/gdb/remote-m68k-bdm.c gdb-6.1-1/gdb/remote-m68k-bdm.c +--- gdb-6.1/gdb/remote-m68k-bdm.c 1970-01-01 10:00:00.000000000 +1000 ++++ gdb-6.1-1/gdb/remote-m68k-bdm.c 2004-05-30 16:36:56.000000000 +1000 +@@ -0,0 +1,1881 @@ ++/* ++ * Motorola Background Debug Mode Target ++ * Copyright (C) 1995 W. Eric Norum ++ * Copyright (C) 1998 Chris Johns (ccj@acm.org) ++ * Copyright (C) 2000 Bryan Feir (bryan@sgl.crestech.ca) ++ * ++ * Based on: ++ * 1. `A Background Debug Mode Driver Package for Motorola's ++ * 16- and 32-Bit Microcontrollers', Scott Howard, Motorola ++ * Canada, 1993. ++ * 2. `Linux device driver for public domain BDM Interface', ++ * M. Schraut, Technische Universitaet Muenchen, Lehrstuhl ++ * fuer Prozessrechner, 1995. ++ * 3. BDM support for gdb by W. Eric Norum ++ * Saskatchewan Accelerator Laboratory ++ * University of Saskatchewan ++ * 107 North Road ++ * Saskatoon, Saskatchewan, CANADA ++ * S7N 5C6 ++ * 4. Coldfire support added by C Johns. ++ * 5. Hardware breakpoint support added by B Feir. ++ * ++ * 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. ++ * ++ * W. Eric Norum ++ * Saskatchewan Accelerator Laboratory ++ * University of Saskatchewan ++ * 107 North Road ++ * Saskatoon, Saskatchewan, CANADA ++ * S7N 5C6 ++ * ++ * eric@skatter.usask.ca ++ * ++ * Coldfire support by: ++ * Chris Johns ++ * Objective Design Systems ++ * 35 Cairo Street ++ * Cammeray, Sydney, 2062, Australia ++ * ++ * ccj@acm.org ++ * ++ * Coldfire hardware breakpoint support by: ++ * Bryan Feir ++ * CRESTech (Centre for Research in Earth and Space Technology) ++ * 4850 Keele Street, 1st floor ++ * Toronto, Ontario, CANADA M6E 3E5 ++ * ++ * bryan@sgl.crestech.ca ++ */ ++ ++/* ++ * $Revision: 1.1 $ $Date: 2004/05/30 07:13:05 $ $Author: cjohns $ ++ */ ++ ++#include "defs.h" ++#include "gdbcore.h" ++#include "target.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 "regcache.h" ++#include "BDMlib.h" ++ ++extern struct target_ops bdm_ops; /* Forward declaration */ ++ ++/* ++ * The name of the BDM driver special file ++ */ ++static char *dev_name; ++static int cpu_type; ++ ++/* ++ * The different register names for the processors. ++ */ ++static const char *cpu32plus_reg_names[NUM_REGS] = { ++ "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", ++ NULL, NULL, NULL, NULL, ++ "mbar", ++ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ++ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ++}; ++ ++static const char *cpu32_reg_names[NUM_REGS] = { ++ "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", ++ "a0", "a1", "a2", "a3", "a4", "a5", "fp", "sp", ++ "ps", "pc", ++ "pcc", "usp", "ssp", "sfc", "dfc", NULL, NULL, ++ "vbr", ++ NULL, NULL, NULL, NULL, ++ NULL, ++ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ++ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ++}; ++ ++static const char *cf_reg_names[NUM_REGS] = { ++ "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", ++ "a0", "a1", "a2", "a3", "a4", "a5", "fp", "sp", ++ "ps", "pc", ++ NULL, NULL, NULL, NULL, NULL, NULL, NULL, ++ "vbr", ++ "cacr", "acr0", "acr1", "rambar", ++ "mbar", ++ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ++ "csr", "aatr", "tdr", "pbr", "pbmr", "abhr", "ablr", "dbr", "dbmr", ++}; ++ ++static const char *cf5272_reg_names[NUM_REGS] = { ++ "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", ++ "a0", "a1", "a2", "a3", "a4", "a5", "fp", "sp", ++ "ps", "pc", ++ NULL, NULL, NULL, NULL, NULL, NULL, NULL, ++ "vbr", ++ "cacr", "acr0", "acr1", "rambar", ++ "mbar", ++ "macsr", "mask", "acc", NULL, NULL, NULL, NULL, NULL, ++ "csr", "aatr", "tdr", "pbr", "pbmr", "abhr", "ablr", "dbr", "dbmr", ++}; ++ ++static const char *cf5282_reg_names[NUM_REGS] = { ++ "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", ++ "a0", "a1", "a2", "a3", "a4", "a5", "fp", "sp", ++ "ps", "pc", ++ NULL, NULL, NULL, NULL, NULL, NULL, NULL, ++ "vbr", ++ "cacr", "acr0", "acr1", "rambar", ++ "flashbar", ++ "macsr", "mask", "acc0", "acc1", "acc2", "acc3", "accext01", "accext32", ++ "csr", "aatr", "tdr", "pbr", "pbmr", "abhr", "ablr", "dbr", "dbmr", ++}; ++ ++static const char **bdm_reg_names = cpu32_reg_names; ++ ++const char *bdm_register_name(int i) ++{ ++ if ((i < 0) || (i >= NUM_REGS)) ++ return NULL; ++ return bdm_reg_names[i]; ++} ++ ++static int reg_to_dev_num[] = { ++ BDM_REG_SR, /* 0 */ ++ BDM_REG_RPC, ++ BDM_REG_PCC, ++ BDM_REG_USP, ++ BDM_REG_SSP, ++ BDM_REG_SFC, /* 5 */ ++ BDM_REG_DFC, ++ BDM_REG_ATEMP, ++ BDM_REG_FAR, ++ BDM_REG_VBR, ++ BDM_REG_CACR, /* 10 */ ++ BDM_REG_ACR0, ++ BDM_REG_ACR1, ++ BDM_REG_RAMBAR, ++ BDM_REG_MBAR, ++ -1, /* 15 */ ++ -1, ++ -1, ++ -1, ++ -1, ++ -1, ++ -1, ++ -1, ++ BDM_REG_CSR, ++ BDM_REG_AATR, ++ BDM_REG_TDR, ++ BDM_REG_PBR, ++ BDM_REG_PBMR, ++ BDM_REG_ABHR, ++ BDM_REG_ABLR, ++ BDM_REG_DBR, ++ BDM_REG_DBMR ++ }; ++ ++#define BDM_FREE_PROG_LOADED() \ ++do {xfree (bdm_prog_loaded); bdm_prog_loaded = NULL; } while (0) ++ ++/* ++ * The name of the most recently loaded program ++ */ ++static char *bdm_prog_loaded; ++ ++/* ++ * Do not load the program when creating the target if set to 1. ++ */ ++static int bdm_no_load; ++ ++/* ++ * Default delay for interface ++ */ ++#define BDM_DEFAULT_DELAY 0 ++static int bdm_delay = -1; ++ ++/* ++ * does gdb wait or not, only valid for a Coldfire processor ++ */ ++static int bdm_gdb_no_wait = 0; ++ ++/* ++ * Hold BDM ATEMP register (CPU32 only). ++ */ ++static unsigned long atemp; ++static int have_atemp; ++ ++/* ++ * Target hit a watchpoint. ++ */ ++static int hit_watchpoint; ++ ++/* ++ * CF BDM Debug hardware version number. ++ */ ++ ++static unsigned long cf_debug_ver; ++ ++/* ++ * Have we set a debug level. ++ */ ++static int bdm_debug_level; ++/* ++ * Not sure if this is defined somewhere. Cannot see anywhere. ++ */ ++extern int (*ui_loop_hook) (int); ++ ++/* ++ * give target time to come up after reset ++ * time in usec ++ */ ++#define TIME_TO_COME_UP 60000 ++ ++/* ++ * We are quitting, so do not call error and therefore ++ * jump back into the main event handler. ++ */ ++static int bdm_gdb_is_quitting; ++ ++static void bdm_close (int quitting); ++ ++/* ++ * The load processor. ++ */ ++static void bdm_load (char *filename, int from_tty); ++ ++/* ++ * Our pid. ++ */ ++ptid_t bdm_ptid; ++ ++/* ++ * The breakpoint codes for the different processors ++ */ ++static char cpu32_breakpoint[] = {0x4a, 0xfa}; ++static char cf_breakpoint[] = {0x4a, 0xc8}; ++static char *breakpointCode; ++static int breakpointSize; ++ ++/* ++ * Display error message and jump back to main input loop ++ */ ++static void ++bdm_report_error (void) ++{ ++ if (!bdm_gdb_is_quitting) ++ error ("BDM driver error: %s", bdmErrorString ()); ++} ++ ++/* ++ * The following routines handle the Coldfire hardware breakpoints. Only one ++ * breakpoint supported so far, and it can be either a PC breakpoint or an ++ * address watchpoint. Unfortunately, the TARGET_CAN_USE_HARDWARE_WATCHPOINT ++ * macro only allows for bounds checking within one of the two types and not ++ * limits that cover the sum of both, so extra work is needed. ++ * ++ * (Actually, very few processors seem to have much support for that routine ++ * at all.) ++ * ++ * As a result, the way this is handled is that the can_use routine will allow ++ * the first breakpoint of either type to be added. Any further checking so ++ * that only one of the two can be used is done later when GDB actually tries ++ * to create the breakpoints, usually when the processor is restarted. ++ * ++ * We keep a local copy of the breakpoints list becasue the chain that GDB ++ * keeps isn't exported globally. ++ * ++ * While things could be simplified with only one breakpoint present, setting ++ * up more general routines allows for later expansion if newer versions of ++ * the ColdFire chip support more breakpoints at once. ++ * ++ * Also, the ColdFire supports things like multi-level triggers and triggers ++ * based on the data bus instead of just the address bus. The GDB commands ++ * don't allow for access to this, but much of it isn't necessary anyway, ++ * as GDB has its own method of handling 'breakpoint conditions' that is ++ * sufficient for most tasks. ++ */ ++ ++#define TDR_TRC_DDATA 0x00000000 ++#define TDR_TRC_HALT 0x40000000 ++#define TDR_TRC_DINT 0x80000000 ++#define TDR_L2_EBL 0x20000000 ++#define TDR_L2_ALL 0x1FFF0000 ++#define TDR_L2_EDLW 0x10000000 ++#define TDR_L2_EDWL 0x08000000 ++#define TDR_L2_EDWU 0x04000000 ++#define TDR_L2_EDLL 0x02000000 ++#define TDR_L2_EDLM 0x01000000 ++#define TDR_L2_EDUM 0x00800000 ++#define TDR_L2_EDUU 0x00400000 ++#define TDR_L2_DI 0x00200000 ++#define TDR_L2_EAI 0x00100000 ++#define TDR_L2_EAR 0x00080000 ++#define TDR_L2_EAL 0x00040000 ++#define TDR_L2_EPC 0x00020000 ++#define TDR_L2_PCI 0x00010000 ++#define TDR_L1_EBL 0x00002000 ++#define TDR_L1_ALL 0x00001FFF ++#define TDR_L1_EDLW 0x00001000 ++#define TDR_L1_EDWL 0x00000800 ++#define TDR_L1_EDWU 0x00000400 ++#define TDR_L1_EDLL 0x00000200 ++#define TDR_L1_EDLM 0x00000100 ++#define TDR_L1_EDUM 0x00000080 ++#define TDR_L1_EDUU 0x00000040 ++#define TDR_L1_DI 0x00000020 ++#define TDR_L1_EAI 0x00000010 ++#define TDR_L1_EAR 0x00000008 ++#define TDR_L1_EAL 0x00000004 ++#define TDR_L1_EPC 0x00000002 ++#define TDR_L1_PCI 0x00000001 ++ ++struct cf_break { ++ enum target_hw_bp_type type; ++ CORE_ADDR addr; ++ int len; ++}; ++ ++#define CF_BREAKPOINT_MAX 1 ++ ++static struct cf_break cf_breakpoints[CF_BREAKPOINT_MAX]; ++static int cf_breakpoint_count; ++ ++static int ++cf_init_watchpoints(void) ++{ ++ if (cpu_type != BDM_COLDFIRE) { ++ return(-1); ++ } ++ cf_breakpoint_count = 0; ++ if (bdmWriteSystemRegister (BDM_REG_TDR, TDR_TRC_HALT) < 0) ++ bdm_report_error (); ++ return(0); ++} ++ ++int ++cf_stopped_by_watchpoint(void) ++{ ++ return hit_watchpoint; ++} ++ ++int ++cf_can_use_watchpoint(enum target_hw_bp_type type, int cnt, int ot) ++{ ++ unsigned long tdr; ++ ++ if (cpu_type != BDM_COLDFIRE) { ++ return(0); ++ } ++ ++ if (type == bp_hardware_breakpoint || type == bp_read_watchpoint || ++ type == bp_hardware_watchpoint || type == bp_access_watchpoint) { ++ if (cnt <= 1) { ++ return(1); ++ } ++ } ++ ++ return(-1); ++} ++ ++int ++cf_insert_hw_breakpoint(CORE_ADDR addr, char *shadow) ++{ ++ unsigned long tdr; ++ ++ if (cpu_type != BDM_COLDFIRE) { ++ return(-1); ++ } ++ ++ if (cf_breakpoint_count < CF_BREAKPOINT_MAX) { ++ cf_breakpoints[cf_breakpoint_count].type = hw_execute; ++ cf_breakpoints[cf_breakpoint_count].addr = addr; ++ cf_breakpoints[cf_breakpoint_count++].len = 2; ++ ++ if (bdmReadSystemRegister (BDM_REG_TDR, &tdr) < 0) ++ bdm_report_error (); ++ tdr = ((tdr & ~TDR_L1_ALL) | (TDR_L1_EBL|TDR_L1_EPC)); ++ if (bdmWriteSystemRegister (BDM_REG_PBR, addr) < 0) ++ bdm_report_error (); ++ if (bdmWriteSystemRegister (BDM_REG_PBMR, 0) < 0) ++ bdm_report_error (); ++ if (bdmWriteSystemRegister (BDM_REG_TDR, tdr) < 0) ++ bdm_report_error (); ++ if (bdm_debug_level) ++ printf_filtered ("Insert PC Breakpoint @0x%08lx\n", addr); ++ } ++ else { ++ return(-1); ++ } ++ return(0); ++} ++ ++static int ++cf_check_breakpoint(type, addr, len) ++ enum target_hw_bp_type type; ++ CORE_ADDR addr; ++ int len; ++{ ++ int i; ++ ++ for (i = 0; i < cf_breakpoint_count; i++) { ++ if (cf_breakpoints[i].type == type && ++ cf_breakpoints[i].addr == addr && ++ cf_breakpoints[i].len == len) { ++ for (; i < CF_BREAKPOINT_MAX-1; i++) { ++ cf_breakpoints[i] = cf_breakpoints[i+1]; ++ } ++ cf_breakpoint_count--; ++ return(1); ++ } ++ } ++ return(0); ++} ++ ++int ++cf_remove_hw_breakpoint(CORE_ADDR addr, char *shadow) ++{ ++ unsigned long tdr; ++ unsigned long csr; ++ ++ if (cpu_type != BDM_COLDFIRE) { ++ return(-1); ++ } ++ ++ if (cf_check_breakpoint(hw_execute, addr, 2)) { ++ if (bdmReadSystemRegister (BDM_REG_TDR, &tdr) < 0) ++ bdm_report_error (); ++ tdr &= ~TDR_L1_EPC; ++ if ((tdr & TDR_L1_ALL) == 0) { ++ tdr &= ~TDR_L1_EBL; ++ } ++ if (bdmWriteSystemRegister (BDM_REG_TDR, tdr) < 0) ++ bdm_report_error (); ++ if (bdm_debug_level) ++ printf_filtered ("Remove PC Breakpoint @0x%08lx\n", addr); ++ } ++ else { ++ return(-1); ++ } ++ return(0); ++} ++ ++#define AATR_READONLY 0x7F85 ++#define AATR_WRITEONLY 0x7F05 ++#define AATR_READWRITE 0xFF05 ++ ++int ++cf_insert_watchpoint(CORE_ADDR addr, int len, enum target_hw_bp_type type) ++{ ++ unsigned long tdr; ++ ++ if (cpu_type != BDM_COLDFIRE) { ++ return(-1); ++ } ++ ++ if (cf_breakpoint_count < CF_BREAKPOINT_MAX) { ++ cf_breakpoints[cf_breakpoint_count].type = type; ++ cf_breakpoints[cf_breakpoint_count].addr = addr; ++ cf_breakpoints[cf_breakpoint_count++].len = len; ++ ++ if (bdmReadSystemRegister (BDM_REG_TDR, &tdr) < 0) ++ bdm_report_error (); ++ tdr = ((tdr & ~TDR_L1_ALL) | (TDR_L1_EBL|TDR_L1_EAR)); ++ if (bdmWriteSystemRegister (BDM_REG_ABLR, addr) < 0) ++ bdm_report_error (); ++ if (bdmWriteSystemRegister (BDM_REG_ABHR, addr+len-1) < 0) ++ bdm_report_error (); ++ if (type == hw_read) { ++ if (bdmWriteSystemRegister (BDM_REG_AATR, AATR_READONLY) < 0) ++ bdm_report_error (); ++ if (bdm_debug_level) ++ printf_filtered ("Insert read Watchpoint @0x%08lx-0x%08lx\n", ++ addr, addr+len-1); ++ } ++ else if (type == hw_write) { ++ if (bdmWriteSystemRegister (BDM_REG_AATR, AATR_WRITEONLY) < 0) ++ bdm_report_error (); ++ if (bdm_debug_level) ++ printf_filtered ("Insert write Watchpoint @0x%08lx-0x%08lx\n", ++ (long unsigned int)addr, addr+len-1); ++ } ++ else { ++ if (bdmWriteSystemRegister (BDM_REG_AATR, AATR_READWRITE) < 0) ++ bdm_report_error (); ++ if (bdm_debug_level) ++ printf_filtered ("Insert access Watchpoint @0x%08lx-0x%08lx\n", ++ addr, addr+len-1); ++ } ++ if (bdmWriteSystemRegister (BDM_REG_TDR, tdr) < 0) ++ bdm_report_error (); ++ } ++ else { ++ return(-1); ++ } ++ return(0); ++} ++ ++int ++cf_remove_watchpoint(CORE_ADDR addr, int len, enum target_hw_bp_type type) ++{ ++ unsigned long tdr; ++ unsigned long csr; ++ ++ if (cpu_type != BDM_COLDFIRE) { ++ return(-1); ++ } ++ ++ if (cf_check_breakpoint(type, addr, len)) { ++ if (bdmReadSystemRegister (BDM_REG_TDR, &tdr) < 0) ++ bdm_report_error (); ++ tdr &= ~TDR_L1_EAR; ++ if ((tdr & TDR_L1_ALL) == 0) { ++ tdr &= ~TDR_L1_EBL; ++ } ++ if (bdmWriteSystemRegister (BDM_REG_TDR, tdr) < 0) ++ bdm_report_error (); ++ if (bdm_debug_level) ++ printf_filtered ("Remove %s Watchpoint @0x%08lx-0x%08lx\n", ++ (type == hw_read) ? "read" : ++ ((type == hw_write) ? "write" : "access"), ++ addr, addr+len-1); ++ } ++ else { ++ return(-1); ++ } ++ return(0); ++} ++ ++int ++cf_stopped_data_address(void) ++{ ++ unsigned long tdr; ++ unsigned long ablr; ++ ++ if (cpu_type != BDM_COLDFIRE) { ++ return(-1); ++ } ++ ++ if (bdmReadSystemRegister (BDM_REG_TDR, &tdr) < 0) ++ bdm_report_error (); ++ if (bdmReadSystemRegister (BDM_REG_ABLR, &ablr) < 0) ++ bdm_report_error (); ++ ++ if (tdr & TDR_L1_EAR) { ++ return(ablr); ++ } ++ return(0); ++} ++ ++#ifdef SYSCALL_TRAP ++/* Immediately after a function call, return the saved pc before the frame ++ is setup. For uCLinux which uses a TRAP #0 for a system call we need to ++ read the first long word of the stack to see if the stack frame format is ++ type 4 and the vector is 32 (0x4080), and the opcode at the PC is ++ "move.w #0x2700,sr". If it is then get the second long from the stack. */ ++ ++CORE_ADDR ++m68k_bdm_saved_pc_after_call (struct frame_info *frame) ++{ ++ unsigned int op; ++ unsigned int eframe; ++ int sp; ++ ++ sp = read_register (SP_REGNUM); ++ eframe = read_memory_integer (sp, 2); ++ op = read_memory_integer (frame->pc, 4); ++ ++ /* ++ * This test could break if some changes the syste call. ++ */ ++ ++ if (eframe == 0x4080 && op == 0x46fc2700) ++ return read_memory_integer (sp + 4, 4); ++ else ++ return read_memory_integer (sp, 4); ++} ++#endif /* SYSCALL_TRAP */ ++ ++unsigned char *m68k_bdm_breakpoint_from_pc (CORE_ADDR *pcptr, int *lenptr) ++{ ++ *lenptr = breakpointSize; ++ return breakpointCode; ++} ++ ++/* ++ * Short pause ++ */ ++static void ++nap (int microseconds) ++{ ++#if defined (__MINGW32__) ++ Sleep (microseconds / 1000); ++#else ++ struct timeval tv; ++ ++ tv.tv_sec = microseconds / 1000000; ++ tv.tv_usec = microseconds % 1000000; ++ select (0, NULL, NULL, NULL, &tv); ++#endif ++} ++ ++/* ++ * Return interface status ++ */ ++static int ++bdm_get_status (void) ++{ ++ int status; ++ ++ if ((status = bdmStatus ()) < 0) ++ bdm_report_error (); ++ return status; ++} ++ ++static void ++bdm_get_status_interactive (int pid, char *arg) ++{ ++ printf_filtered ("BDM status: 0x%x\n", bdm_get_status ()); ++} ++ ++/* ++ * release chip: reset and disable bdm mode ++ */ ++static void ++bdm_release_chip (void) ++{ ++ have_atemp = 0; ++ registers_changed (); ++ inferior_ptid = bdm_ptid = null_ptid; ++ if (bdmRelease () < 0) ++ bdm_report_error (); ++} ++ ++/* ++ * stop chip ++ */ ++static void ++bdm_stop_chip (void) ++{ ++ if (bdm_debug_level) ++ printf_filtered ("bdm stop chip called\n"); ++ if (bdmStop () < 0) ++ bdm_report_error (); ++} ++ ++/* ++ * Allow chip to resume execution ++ */ ++static void ++bdm_go (void) ++{ ++ have_atemp = 0; ++ if (bdmGo () < 0) ++ bdm_report_error (); ++} ++ ++/* ++ * Reset chip, enter BDM mode ++ */ ++static void ++bdm_reset (void) ++{ ++ have_atemp = 0; ++ registers_changed (); ++ inferior_ptid = bdm_ptid = null_ptid; ++ if (bdmReset () < 0) ++ bdm_report_error (); ++ nap (TIME_TO_COME_UP); ++} ++ ++/* ++ * step cpu32 chip: execute a single instruction ++ * This is complicated by the presence of interrupts. ++ * Consider the following sequence of events: ++ * - User attempts to `continue' from a breakpoint. ++ * - Gdb calls bdm_step_chip to single-step the instruction that ++ * had been replaced by the BGND instruction. ++ * - The target processor executes the instruction and stops. ++ * - GDB replaces the instruction with a BGND instruction to ++ * force a breakpoint the next time the instruction is hit. ++ * - GDB calls bdm_go and the target resumes execution. ++ * This all seems fine, but now consider what happens when a interrupt ++ * is pending: ++ * - User attempts to `continue' from a breakpoint. ++ * - Gdb calls bdm_step_chip to single-step the instruction that ++ * had been replaced by the BGND instruction. ++ * - The target processor does not execute the replaced instruction, ++ * but rather executes the first instruction of the interrupt ++ * service routine, then stops. ++ * - GDB replaces the instruction with a BGND instruction to ++ * force a breakpoint the next time the instruction is hit. ++ * - GDB calls bdm_go and the target resumes execution. ++ * - The target finishes off the interrupt, and upon returing from ++ * the interrupt generates another breakpoint! ++ * The solution is simple -- disable interrupts when single stepping. ++ * The problem then becomes the handling of instructions which involve ++ * the program status word! ++ */ ++static void ++bdm_step_cpu32_chip (void) ++{ ++ unsigned long pc; ++ unsigned short instruction; ++ unsigned short immediate; ++ unsigned long d7; ++ unsigned long sr; ++ unsigned long nsr; ++ enum { ++ op_other, ++ op_ANDIsr, ++ op_EORIsr, ++ op_ORIsr, ++ op_TOsr, ++ op_FROMsr, ++ op_FROMsrTOd7 ++ } op; ++ ++ /* ++ * Get the existing status register ++ */ ++ if (bdmReadSystemRegister (BDM_REG_SR, &sr) < 0) ++ bdm_report_error (); ++ ++ /* ++ * Read the instuction about to be executed ++ */ ++ if ((bdmReadSystemRegister (BDM_REG_RPC, &pc) < 0) ++ || (bdmReadWord (pc, &instruction) < 0)) ++ bdm_report_error (); ++ ++ /* ++ * See what operation is to be performed ++ */ ++ if (instruction == 0x027C) ++ op = op_ANDIsr; ++ else if (instruction == 0x0A7C) ++ op = op_EORIsr; ++ else if (instruction == 0x007C) ++ op = op_ORIsr; ++ else if (instruction == 0x40C7) ++ op = op_FROMsrTOd7; ++ else if ((instruction & 0xFFC0) == 0x40C0) ++ op = op_FROMsr; ++ else if ((instruction & 0xFFC0) == 0x46C0) ++ op = op_TOsr; ++ else ++ op = op_other; ++ ++ /* ++ * Set things up for the single-step operation ++ */ ++ switch (op) { ++ case op_FROMsr: ++ /* ++ * It's storing the SR somewhere. ++ * Store the SR in D7 and change the instruction ++ * to save D7. This fails if the addressing mode ++ * is one of the esoteric modes that uses D7 as ++ * and index register, but we'll just have to hope ++ * that doesn't happen too often. ++ */ ++ if ((bdmReadRegister (7, &d7) < 0) ++ || (bdmWriteRegister (7, sr) < 0) ++ || (bdmWriteWord (pc, 0x3007 | ++ ((instruction & 0x38) << 3) | ++ ((instruction & 0x07) << 9)) < 0)) ++ bdm_report_error (); ++ break; ++ ++ case op_ANDIsr: ++ case op_EORIsr: ++ case op_ORIsr: ++ /* ++ * It's an immediate operation to the SR -- pick up the value ++ */ ++ if (bdmReadWord (pc+2, &immediate) < 0) ++ bdm_report_error (); ++ break; ++ ++ case op_TOsr: ++ case op_other: ++ break; ++ } ++ ++ /* ++ * Ensure the step is done with interrupts disabled ++ */ ++ if (bdmWriteSystemRegister (BDM_REG_SR, sr | 0x0700) < 0) ++ bdm_report_error (); ++ ++ /* ++ * Do the single-step ++ */ ++ if (bdmStep () < 0) ++ bdm_report_error (); ++ ++ /* ++ * Get the ATEMP register since the following operations may ++ * modify it. ++ */ ++ if (bdmReadSystemRegister (BDM_REG_ATEMP, &atemp) < 0) ++ bdm_report_error (); ++ have_atemp = 1; ++ ++ /* ++ * Clean things up ++ */ ++ switch (op) { ++ case op_FROMsr: ++ if ((bdmWriteRegister (7, d7) < 0) ++ || (bdmWriteWord (pc, instruction) < 0) ++ || (bdmWriteSystemRegister (BDM_REG_SR, sr) < 0)) ++ bdm_report_error (); ++ break; ++ ++ case op_FROMsrTOd7: ++ if ((bdmReadRegister (7, &d7) < 0) ++ || (bdmWriteRegister (7, (d7 & ~0xFFFF) | (sr & 0xFFFF)) < 0) ++ || (bdmWriteSystemRegister (BDM_REG_SR, sr) < 0)) ++ bdm_report_error (); ++ break; ++ ++ case op_ANDIsr: ++ if (bdmWriteSystemRegister (BDM_REG_SR, sr & immediate) < 0) ++ bdm_report_error (); ++ break; ++ ++ case op_EORIsr: ++ if (bdmWriteSystemRegister (BDM_REG_SR, sr ^ immediate) < 0) ++ bdm_report_error (); ++ break; ++ ++ case op_ORIsr: ++ if (bdmWriteSystemRegister (BDM_REG_SR, sr | immediate) < 0) ++ bdm_report_error (); ++ break; ++ ++ case op_TOsr: ++ break; ++ ++ case op_other: ++ if ((bdmReadSystemRegister (BDM_REG_SR, &nsr) < 0) ++ || (bdmWriteSystemRegister (BDM_REG_SR, (nsr & ~0x0700) | (sr & 0x0700)) < 0)) ++ bdm_report_error (); ++ break; ++ } ++} ++ ++static void ++bdm_step_chip (void) ++{ ++ /* ++ * The cpu32 is harder to step than the Coldfire. ++ */ ++ if (cpu_type == BDM_CPU32) { ++ bdm_step_cpu32_chip(); ++ return; ++ } ++ ++ /* ++ * Do the single-step ++ */ ++ if (bdmStep () < 0) ++ bdm_report_error (); ++} ++ ++/* ++ * true if runnable ++ */ ++static int ++bdm_can_run (void) ++{ ++ if (bdm_debug_level) ++ printf_filtered ("bdm can run called\n"); ++ return 1; ++} ++ ++static void ++bdm_setdelay(int delay) ++{ ++ if (bdmSetDelay (delay) < 0) ++ bdm_report_error (); ++} ++ ++static void ++bdm_setdelay_interactive (char *arg, int from_tty) ++{ ++ char *dummy; ++ ++ if (!arg) { ++ if (bdm_delay >= 0) ++ printf_filtered("bdm_delay is %d", bdm_delay); ++ else ++ printf_filtered("using default delay %d", BDM_DEFAULT_DELAY); ++ } ++ else { ++ bdm_delay = strtoul(arg, &dummy, 0); ++ bdm_setdelay (bdm_delay); ++ } ++} ++ ++static void ++bdm_setdebug_interactive (char *arg, int from_tty) ++{ ++ char *dummy; ++ if (arg) { ++ bdm_debug_level = strtoul(arg, &dummy, 0); ++ bdmSetDebugFlag (bdm_debug_level); ++ } ++ else ++ error ("Argument missing"); ++} ++ ++static void ++bdm_setdriverdebug_interactive (char *arg, int from_tty) ++{ ++ char *dummy; ++ if (arg) ++ bdmSetDriverDebugFlag (strtoul(arg, &dummy, 0)); ++ else ++ error ("Argument missing"); ++} ++ ++static void ++bdm_set_no_wait (char *arg, int from_tty) ++{ ++ bdm_gdb_no_wait = 1; ++} ++ ++static void ++bdm_set_wait (char *arg, int from_tty) ++{ ++ if (cpu_type == BDM_CPU32) { ++ error ("No wait mode is not supported on a CPU32"); ++ return; ++ } ++ if (bdm_get_status ()) ++ bdm_gdb_no_wait = 0; ++ else ++ error ("The target is running, please stop first"); ++} ++ ++static void ++bdm_issue_stop (char *arg, int from_tty) ++{ ++ bdm_stop_chip (); ++} ++ ++/* ++ * Open a connection the target via bdm ++ * name is the devicename of bdm and the filename to be used ++ * used for communication. ++ */ ++static void ++bdm_open (char *name, int from_tty) ++{ ++ char *p; ++ int version; ++ unsigned long csr; ++ ++ if (bdm_debug_level) ++ printf_filtered ("bdm open called\n"); ++ ++ if (bdmIsOpen ()) ++ bdm_close (0); ++ if (name == NULL) ++ error ("Use `target bdm ' to use the bdm target"); ++ ++ bdm_ptid = null_ptid; ++ ++ /* ++ * 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 the bdm port device."); ++ dev_name = savestring (name, p - name); ++ ++ target_preopen (from_tty); ++ unpush_target (&bdm_ops); ++ ++ if (bdmOpen (dev_name) < 0) ++ bdm_report_error (); ++ if (bdmStatus () & (BDM_TARGETPOWER | BDM_TARGETNC)) { ++ bdmClose (); ++ error ("Target or cable problem"); ++ } ++ ++ /* ++ * Ask the driver for it's version. ++ * We are only interested in the major number when checking the ++ * driver version number. ++ */ ++ if (bdmGetDrvVersion (&version) < 0) ++ bdm_report_error (); ++ if ((version & 0xff00) != (BDM_DRV_VERSION & 0xff00)) { ++ printf_filtered ("Incorrect driver version, looking for %i.%i"\ ++ " and found %i.%i\n", ++ BDM_DRV_VERSION >> 8, BDM_DRV_VERSION & 0xff, ++ version >> 8, version & 0xff); ++ bdmClose (); ++ error ("Can't run with incorrect BDM driver version"); ++ } ++ ++ /* ++ * Get the processor type. ++ */ ++ if (bdmGetProcessor (&cpu_type) < 0) ++ bdm_report_error (); ++ switch (cpu_type) { ++ case BDM_CPU32: ++ bdm_reg_names = cpu32_reg_names; ++ breakpointCode = cpu32_breakpoint; ++ breakpointSize = sizeof cpu32_breakpoint; ++ break; ++ ++ case BDM_COLDFIRE: ++ bdm_reg_names = cf_reg_names; ++ breakpointCode = cf_breakpoint; ++ breakpointSize = sizeof cf_breakpoint; ++ cf_init_watchpoints(); ++ ++ /* ++ * Read the CSR register to determine the debug module ++ * version. ++ */ ++ if (bdmReadSystemRegister (BDM_REG_CSR, &csr) < 0) ++ bdm_report_error (); ++ cf_debug_ver = (csr >> 20) & 0x0f; ++ ++ /* ++ * If the processor is a version 0 read the PC and VBR ++ * an if they can be read read the mbar. If that fails ++ * we have a 5282. ++ */ ++ reg_to_dev_num[13] = BDM_REG_RAMBAR; ++ reg_to_dev_num[14] = BDM_REG_MBAR; ++ reg_to_dev_num[15] = -1; ++ reg_to_dev_num[16] = -1; ++ reg_to_dev_num[17] = -1; ++ reg_to_dev_num[18] = -1; ++ reg_to_dev_num[19] = -1; ++ reg_to_dev_num[20] = -1; ++ reg_to_dev_num[21] = -1; ++ reg_to_dev_num[22] = -1; ++ ++ if (cf_debug_ver == 0) { ++ unsigned long junk; ++ if ((bdmReadSystemRegister (BDM_REG_RPC, &junk) == 0) && ++ (bdmReadSystemRegister (BDM_REG_VBR, &junk) == 0)) { ++ if (bdmReadSystemRegister (BDM_REG_MBAR, &junk) < 0) { ++ bdm_reg_names = cf5282_reg_names; ++ reg_to_dev_num[13] = 0xc05; ++ reg_to_dev_num[14] = 0xc04; ++ reg_to_dev_num[15] = 0x804; ++ reg_to_dev_num[16] = 0x805; ++ reg_to_dev_num[17] = 0x806; ++ reg_to_dev_num[18] = 0x809; ++ reg_to_dev_num[19] = 0x80a; ++ reg_to_dev_num[20] = 0x80b; ++ reg_to_dev_num[21] = 0x807; ++ reg_to_dev_num[22] = 0x808; ++ printf_filtered ("Detected MCF5282\n"); ++ } ++ else { ++ bdm_reg_names = cf5272_reg_names; ++ reg_to_dev_num[13] = BDM_REG_RAMBAR; ++ reg_to_dev_num[14] = BDM_REG_MBAR; ++ reg_to_dev_num[15] = 0x804; ++ reg_to_dev_num[16] = 0x805; ++ reg_to_dev_num[17] = 0x806; ++ printf_filtered ("Detected V2 core\n"); ++ } ++ } ++ } ++ break; ++ ++ default: ++ bdmClose (); ++ error ("Unknown processor type returned from the driver."); ++ } ++ ++ push_target (&bdm_ops); ++ ++ if (bdm_delay >= 0) ++ bdm_setdelay (bdm_delay); ++ else ++ bdm_setdelay (BDM_DEFAULT_DELAY); ++ if (from_tty) ++ printf_filtered ("GDB target %s connected to %s\n", ++ target_shortname, dev_name); ++ if (cpu_type == BDM_COLDFIRE) ++ printf_filtered (" Coldfire debug module version is %ld (%s)\n", ++ cf_debug_ver, ++ cf_debug_ver == 0 ? "5206(e)/5272/5282" : "5307/5407(e)"); ++} ++ ++/* ++ * Terminate current application and return to system prompt. ++ * On a target, just let the program keep on running ++ */ ++static void ++bdm_kill (void) ++{ ++ if (bdm_debug_level) ++ printf_filtered ("bdm kill called\n"); ++#ifdef BDM_GDB_RELEASE_CPU_ON_EXIT ++ if (bdm_get_status () & BDM_TARGETSTOPPED) ++ bdm_go (); ++#else ++ bdm_stop_chip (); ++ bdm_reset (); ++#endif ++ BDM_FREE_PROG_LOADED (); ++} ++ ++static void ++bdm_close (int quitting) ++{ ++ if (bdm_debug_level) ++ printf_filtered ("bdm close called\n"); ++ bdm_gdb_is_quitting = quitting; ++ have_atemp = 0; ++ if (quitting) ++ bdm_kill (); ++ bdmClose (); ++ BDM_FREE_PROG_LOADED (); ++ inferior_ptid = bdm_ptid = null_ptid; ++} ++ ++static void ++bdm_attach (char *args, int from_tty) ++{ ++ if (bdm_debug_level) ++ printf_filtered ("bdm attach called\n"); ++ bdm_open (args, from_tty); ++} ++ ++/* ++ * _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) ++{ ++ if (bdm_debug_level) ++ printf_filtered ("bdm detach called\n"); ++ BDM_FREE_PROG_LOADED (); ++ inferior_ptid = bdm_ptid = null_ptid; ++ pop_target (); /* calls bdm_close to do the real work */ ++} ++ ++/* ++ * _resume -- Tell the remote machine to resume. ++ */ ++static void ++bdm_resume (ptid_t pid, int step, enum target_signal sig) ++{ ++ if (bdm_debug_level) ++ printf_filtered ("bdm resume called\n"); ++ if (step) ++ bdm_step_chip (); ++ else ++ bdm_go (); ++ bdm_ptid = pid_to_ptid (42000); ++} ++ ++/* ++ * We have fallen into an exception supported by the runtime system. ++ * by executing a `breakpoint' instruction. ++ */ ++static void ++analyze_exception (struct target_waitstatus *status) ++{ ++ unsigned long pc, sp; ++ unsigned short vec; ++ char opcode[20]; /* `big enough' */ ++ ++ if (cpu_type == BDM_CPU32) { ++ if (bdmReadSystemRegister (BDM_REG_PCC, &pc) < 0) ++ bdm_report_error (); ++ } ++ else { ++ if (bdmReadSystemRegister (BDM_REG_RPC, &pc) < 0) ++ bdm_report_error (); ++ if (pc) ++ pc -= 2; ++ } ++ status->kind = TARGET_WAITKIND_STOPPED; ++ ++ /* ++ * See if it was a `breakpoint' instruction ++ */ ++ if (bdmReadMemory (pc, opcode, breakpointSize) < 0) ++ bdm_report_error (); ++ if (memcmp (breakpointCode, opcode, breakpointSize) == 0) { ++ if (bdmWriteSystemRegister (BDM_REG_RPC, pc) < 0) ++ bdm_report_error (); ++ status->value.sig = TARGET_SIGNAL_TRAP; ++ return; ++ } ++ /* ++ * FIXME: Why an illegal instruction signal ? ++ */ ++ status->value.sig = TARGET_SIGNAL_ILL; ++} ++ ++static int sigintFlag; ++static void ++bdm_signal_handler (int s) ++{ ++ sigintFlag++; ++} ++ ++/* ++ * 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) ++{ ++ unsigned long csr; ++ int bdm_stat; ++ int detach = 0; ++ int ui_count = 0; ++ void (*ofunc) (); ++ ++ hit_watchpoint = 0; ++ if (bdm_gdb_no_wait) { ++ status->kind = TARGET_WAITKIND_STOPPED; ++ status->value.sig = TARGET_SIGNAL_GRANT; ++ return bdm_ptid; ++ } ++ ++ status->kind = TARGET_WAITKIND_EXITED; ++ status->value.integer = 0; ++ ++ /* ++ * Catch SIGINT signals ++ */ ++ sigintFlag = 0; ++ ofunc = signal (SIGINT, bdm_signal_handler); ++ ++ /* ++ * A work around a problem with the 5206e processor. Not sure ++ * what the issue is. It could be the processor. ++ */ ++ if (cpu_type == BDM_COLDFIRE && cf_debug_ver == 0) ++ nap (10000); ++ ++ /* ++ * Wait here till the target requires service ++ */ ++ while ((bdm_stat = bdm_get_status ()) == 0) { ++ ui_count = 0; ++ while (ui_count++ < 6) { ++ nap (50000); ++ ++ /* N.B. The UI may destroy our world (for instance by calling ++ remote_stop,) in which case we want to get out of here as ++ quickly as possible. It is not safe to touch scb, since ++ someone else might have freed it. The ui_loop_hook signals that ++ we should exit by returning 1. */ ++ ++ if (ui_loop_hook) ++ detach = ui_loop_hook (0); ++ ++ if (detach || sigintFlag) ++ bdm_stop_chip (); ++ } ++ } ++ ++ signal (SIGINT, ofunc); ++ ++ /* ++ * Determine why the target stopped ++ */ ++ 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: ++ case BDM_TARGETHALT: ++ case BDM_TARGETSTOPPED | BDM_TARGETHALT: ++ if (sigintFlag) { ++ status->kind = TARGET_WAITKIND_STOPPED; ++ status->value.sig = TARGET_SIGNAL_TSTP; ++ } ++ else { ++ if (cpu_type == BDM_CPU32) { ++ if (!have_atemp ++ && (bdmReadSystemRegister (BDM_REG_ATEMP, &atemp) < 0)) ++ bdm_report_error (); ++ switch (atemp & 0xffff) { ++ case 0xffff: /* double bus fault */ ++ status->kind = TARGET_WAITKIND_STOPPED; ++ status->value.sig = TARGET_SIGNAL_BUS; ++ break; ++ case 0x0: /* HW bkpt */ ++ status->kind = TARGET_WAITKIND_STOPPED; ++ status->value.sig = TARGET_SIGNAL_TRAP; ++ break; ++ case 0x1: /* background mode */ ++ analyze_exception (status); ++ break; ++ default: ++ printf_filtered ("bdm_wait: Unknown atemp:%#lx\n", atemp); ++ status->kind = TARGET_WAITKIND_STOPPED; ++ status->value.sig = TARGET_SIGNAL_GRANT; ++ } ++ } ++ else { ++ if (bdmReadSystemRegister (BDM_REG_CSR, &csr) < 0) ++ bdm_report_error (); ++ if (csr & 0x08000000) { /* double bus fault */ ++ status->kind = TARGET_WAITKIND_STOPPED; ++ status->value.sig = TARGET_SIGNAL_BUS; ++ } ++ else { ++ if (csr & 0x04000000) { /* hardware trigger */ ++ hit_watchpoint = 1; ++ status->kind = TARGET_WAITKIND_STOPPED; ++ status->value.sig = TARGET_SIGNAL_TRAP; ++ } ++ else { ++ if (csr & 0x01000000) { /* -BKPT signal */ ++ status->kind = TARGET_WAITKIND_STOPPED; ++ status->value.sig = TARGET_SIGNAL_TRAP; ++ } ++ else { ++ if (csr & 0x02000000) { /* HALT/software bkpt */ ++ analyze_exception (status); ++ } ++ else { ++ printf_filtered ("bdm_wait: Unknown csr:%#lx", ++ csr); ++ status->kind = TARGET_WAITKIND_STOPPED; ++ status->value.sig = TARGET_SIGNAL_GRANT; ++ } ++ } ++ } ++ } ++ } ++ } ++ break; ++ default: ++ printf_filtered ("bdm_wait: Unknown BDM status: %#x", bdm_stat); ++ break; ++ } ++ have_atemp = 0; ++ return bdm_ptid; ++} ++ ++/* This is called not only when we first attach, but also when the ++ user types "run" after having attached. */ ++static void ++bdm_create_inferior (char *execfile, char *args, char **env) ++{ ++ CORE_ADDR addr = -1;; ++ ++ if (bdm_debug_level) ++ printf_filtered ("bdm create inferior called\n"); ++ ++ if (!bdmIsOpen ()) ++ error ("Not attached to the target. Use `target bdm ' command to attach.\n"); ++ ++ /* ++ * If we do not load an executable, reset and step the processor to get a ++ * valid PC. ++ */ ++ ++ if (bdm_no_load) ++ { ++ bdm_reset (); ++ bdm_step_chip (); ++ } ++ else ++ { ++ bdm_load (execfile, 0); ++ addr = bfd_get_start_address (exec_bfd); ++ } ++ ++ inferior_ptid = pid_to_ptid (42000); ++ ++ /* Clean up from the last time we were running. */ ++ clear_proceed_status (); ++ ++ /* Let the remote process run. The -1 will continue. */ ++ proceed (addr, TARGET_SIGNAL_DEFAULT, 0); ++} ++ ++static void ++bdm_mourn_inferior (void) ++{ ++ if (bdm_debug_level) ++ printf_filtered ("bdm mourn inferior called\n"); ++ unpush_target (&bdm_ops); ++ generic_mourn_inferior (); ++} ++ ++/* ++ * Load a file. ++ */ ++static void ++bdm_load (char *filename, int from_tty) ++{ ++ if (bdm_debug_level) ++ printf_filtered ("bdm load called\n"); ++ if ((bdm_get_status () & BDM_TARGETSTOPPED) == 0) ++ bdm_stop_chip (); ++ inferior_ptid = bdm_ptid = null_ptid; ++ init_wait_for_inferior (); ++ generic_load (filename, from_tty); ++ bdm_prog_loaded = savestring (filename, strlen (filename)); ++ ++} ++ ++/* ++ * Fetch register REGNO, or all user registers if REGNO is -1. ++ */ ++static void ++bdm_fetch_register (int regno) ++{ ++ unsigned long l; ++ char cbuf[4]; ++ int ret; ++ ++ if (regno < 0) { ++ for (regno = 0 ; regno < NUM_REGS ; regno++) ++ bdm_fetch_register (regno); ++ } ++ else { ++ /* ++ * When the target is running the ++ * cpu registers can not be accessed. ++ */ ++ if (bdm_gdb_no_wait && (bdm_get_status () == 0)) { ++ l = 0; ++ ret = 0; ++ } ++ else { ++ if (regno < 16) { ++ ret = bdmReadRegister (regno, &l); ++ } ++ else { ++ int cfreg = regno - 16; ++ if (bdm_debug_level) ++ printf_filtered ("bdm_fetch_register: special reg: %d\n", cfreg); ++ if (cfreg < (sizeof (reg_to_dev_num) / sizeof (int))) { ++ if (reg_to_dev_num[cfreg] < 0) ++ return; ++ if (bdm_debug_level) ++ printf_filtered ("bdm_fetch_register: reg_to_dev_num: %d\n", ++ reg_to_dev_num[cfreg]); ++ if (reg_to_dev_num[cfreg] < 0x100) ++ ret = bdmReadSystemRegister (reg_to_dev_num[cfreg], &l); ++ else ++ ret = bdmReadControlRegister (reg_to_dev_num[cfreg], &l); ++ } ++ else { ++ error ("Bad register number (%d)", regno); ++ return; ++ } ++ } ++ } ++ if (ret < 0) ++ bdm_report_error (); ++ cbuf[0] = l >> 24; ++ cbuf[1] = l >> 16; ++ cbuf[2] = l >> 8; ++ cbuf[3] = l; ++ supply_register (regno, cbuf); ++ } ++} ++ ++void ++bdm_prepare_to_store (void) ++{ ++ /* Do nothing, since we can store individual regs */ ++} ++ ++/* ++ * Store register REGNO, or all user registers if REGNO == -1. ++ */ ++void ++bdm_store_register (int regno) ++{ ++ unsigned long l; ++ int ret; ++ ++ if (bdm_gdb_no_wait && (bdm_get_status () == 0)) ++ return; ++ ++ if (regno == -1) { ++ for (regno = 0 ; regno < NUM_REGS ; regno++) ++ bdm_store_register (regno); ++ } ++ else { ++ l = read_register (regno); ++ if (regno < 16) { ++ ret = bdmWriteRegister (regno, l); ++ } ++ else { ++ int cfreg = regno - 16; ++ if (bdm_debug_level) ++ printf_filtered ("bdm_store_register: special reg: %d\n", cfreg); ++ if (cfreg < (sizeof (reg_to_dev_num) / sizeof (int))) { ++ if (reg_to_dev_num[cfreg] < 0) ++ return; ++ if (bdm_debug_level) ++ printf_filtered ("bdm_store_register: reg_to_dev_num: %d\n", ++ reg_to_dev_num[cfreg]); ++ if (reg_to_dev_num[cfreg] < 0x100) ++ ret = bdmWriteSystemRegister (reg_to_dev_num[cfreg], l); ++ else ++ ret = bdmWriteControlRegister (reg_to_dev_num[cfreg], l); ++ } ++ else { ++ error ("Bad register number (%d)", regno); ++ return; ++ } ++ } ++ if (ret < 0) ++ bdm_report_error (); ++ } ++} ++ ++/* ++ * Transfer memory contents between target and host ++ */ ++static int ++bdm_xfer_inferior_memory (CORE_ADDR memaddr, char *myaddr, ++ int len, int write, ++ struct mem_attrib *attrib, ++ struct target_ops *t) ++{ ++ int ret; ++ ++ if (write) ++ ret = bdmWriteMemory (memaddr, myaddr, len); ++ else ++ ret = bdmReadMemory (memaddr, myaddr, len); ++ if (ret < 0) ++ bdm_report_error (); ++ return len; ++} ++ ++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"); ++ } ++} ++ ++/* ++ * Toggle the no load variable. ++ */ ++static void ++bdm_toggle_no_load (char *args, int from_tty) ++{ ++ if (!bdm_no_load) { ++ bdm_no_load = 1; ++ printf_filtered ("Image not loaded on run\n"); ++ } ++ else { ++ bdm_no_load = 0; ++ printf_filtered ("Image loaded on run\n"); ++ } ++} ++ ++/* ++ * Select a CPU32 processor register set. ++ */ ++static void ++bdm_select_cpu32 (char *args, int from_tty) ++{ ++ bdm_reg_names = cpu32_reg_names; ++} ++ ++/* ++ * Get or set the use of the PST signals when using a Coldfire. ++ */ ++static void ++bdm_cf_pst (char *args, int from_tty) ++{ ++ int pst; ++ ++ if (!args) ++ { ++ if (bdmColdfireGetPST (&pst) < 0) ++ printf_filtered ("error getting the PST state: %d\n", errno); ++ else ++ printf_filtered ("PST signal use: %s\n", pst ? "ENABLED" : "DISABLED"); ++ } ++ else ++ { ++ pst = strtoul (args, 0, 0); ++ if (pst) ++ pst = 1; ++ if (bdmColdfireSetPST (pst) < 0) ++ printf_filtered ("error setting the PST state: %d\n", errno); ++ } ++} ++ ++/* ++ * Read or write control registers. ++ */ ++static void ++bdm_read_control_reg (char *exp, int from_tty) ++{ ++ static LONGEST reg = -1; ++ static char format = 'x'; ++ struct cleanup *old_chain = 0; ++ struct expression *expr; ++ struct value* val; ++ struct type type; ++ unsigned long l; ++ ++ if (!exp) { ++ if (reg < 0) ++ error ("you need to supply a 16bit register value, eg VBR = 0x801\n"); ++ } ++ else { ++ if (*exp == '/') { ++ exp++; ++ if (*exp == 'd' || *exp == 'x') ++ format = *exp; ++ else ++ error ("format specifiers are 'd' or 'x\n"); ++ exp++; ++ } ++ ++ expr = parse_expression (exp); ++ old_chain = make_cleanup (free_current_contents, &expr); ++ val = evaluate_expression (expr); ++ ++ if (VALUE_LVAL (val) == not_lval || VALUE_LVAL (val) == lval_internalvar) ++ reg = unpack_long (VALUE_TYPE (val), VALUE_CONTENTS (val)); ++ else { ++ reg = -1; ++ format = 'x'; ++ do_cleanups (old_chain); ++ error ("the register can be a literal or a gdb variable"); ++ } ++ ++ do_cleanups (old_chain); ++ } ++ ++ if (bdmReadControlRegister (reg, &l) < 0) ++ bdm_report_error (); ++ ++ if (format == 'x') ++ printf_filtered ("0x%08lx\n", l); ++ else ++ printf_filtered ("%ld\n", l); ++} ++ ++static void ++bdm_write_control_reg (char *exp, int from_tty) ++{ ++ static int reg = -1; ++ static int l = 0x0; ++ struct cleanup *old_chain = 0; ++ struct expression *expr; ++ struct value* val; ++ char* end; ++ ++ if (!exp && (reg < 0)) ++ error ("you need to supply a 16bit register value, eg VBR = 0x801\n"); ++ ++ /* ++ * Do a little token parsing to split the expression into 2 separate parts ++ * and then parse each one. There may be a better way but it will do. ++ */ ++ ++ end = strchr (exp, ' '); ++ ++ if (!end) { ++ end = strchr (exp, '\t'); ++ if (!end) ++ error ("write requires a register and a value to write\n"); ++ } ++ ++ *end = '\0'; ++ ++ expr = parse_expression (exp); ++ old_chain = make_cleanup (free_current_contents, &expr); ++ val = evaluate_expression (expr); ++ ++ if (VALUE_LVAL (val) == not_lval || VALUE_LVAL (val) == lval_internalvar) { ++ reg = unpack_long (VALUE_TYPE (val), VALUE_CONTENTS (val)); ++ } ++ else { ++ reg = -1; ++ l = 0; ++ do_cleanups (old_chain); ++ error ("the register can be a literal or a gdb variable"); ++ } ++ ++ do_cleanups (old_chain); ++ ++ old_chain = 0; ++ ++ exp = end + 1; ++ ++ expr = parse_expression (exp); ++ old_chain = make_cleanup (free_current_contents, &expr); ++ val = evaluate_expression (expr); ++ ++ if (VALUE_LVAL (val) == not_lval || VALUE_LVAL (val) == lval_internalvar) { ++ l = unpack_long (VALUE_TYPE (val), VALUE_CONTENTS (val)); ++ } ++ else { ++ reg = -1; ++ l = 0; ++ do_cleanups (old_chain); ++ error ("the data to write can be a literal or a gdb variable"); ++ } ++ ++ do_cleanups (old_chain); ++ ++ if (bdmWriteControlRegister (reg, l) < 0) ++ bdm_report_error (); ++} ++ ++struct target_ops bdm_ops; ++ ++static void ++init_bdm_ops(void) ++{ ++ bdm_ops.to_shortname = "bdm"; ++ bdm_ops.to_longname = ++ "CPU32 and Coldfire Background Debug Mode Interface" \ ++ " for downloading and remote debugging"; ++ bdm_ops.to_doc = "Uses the Public Domain Background Debug Mode Interface connected to the\n" \ ++ "BDM-port of the CPU32 or Coldfire based microcontroller and to a parallel port\n" ++ "of the PC.\n" \ ++ "Usage: target bdm \n" \ ++ "where is the BDM character special file (e.g. /dev/bdm0)."; ++ bdm_ops.to_open = bdm_open; ++ bdm_ops.to_close = bdm_close; ++ bdm_ops.to_attach = bdm_attach; ++ bdm_ops.to_detach = bdm_detach; ++ bdm_ops.to_resume = bdm_resume; ++ bdm_ops.to_wait = bdm_wait; ++ 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 = memory_insert_breakpoint; ++ bdm_ops.to_remove_breakpoint = memory_remove_breakpoint; ++ bdm_ops.to_kill = bdm_kill; ++ bdm_ops.to_load = bdm_load; ++ bdm_ops.to_stop = bdm_stop_chip; ++ bdm_ops.to_create_inferior = bdm_create_inferior; ++ bdm_ops.to_mourn_inferior = bdm_mourn_inferior; ++ bdm_ops.to_can_run = bdm_can_run; ++ bdm_ops.to_stratum = process_stratum; ++ 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; ++ bdm_ops.to_magic = OPS_MAGIC; ++}; ++ ++void ++_initialize_remote_bdmcf (void) ++{ ++ bdm_ptid = null_ptid; ++ init_bdm_ops (); ++ add_com ("bdm-reset", class_obscure, ++ (void (*)(char *, int))bdm_reset, ++ "Reset target and enter BDM mode."); ++ add_com ("bdm-release", class_obscure, ++ (void (*)(char *, int))bdm_release_chip, ++ "Reset target without BDM-mode."); ++ add_com ("bdm-status", class_obscure, ++ (void (*)(char *, int))bdm_get_status_interactive, ++ "Show status of bdm interface\n"); ++ add_com ("bdm-setdelay", class_obscure, ++ bdm_setdelay_interactive, ++ "set delay for download"); ++ add_com ("bdm-setdebug", class_obscure, ++ bdm_setdebug_interactive, ++ "enable/disable BDM diagnostic messages"); ++ add_com ("bdm-setdriverdebug", class_obscure, ++ bdm_setdriverdebug_interactive, ++ "enable/disable BDM driver diagnostic messages"); ++ add_com ("bdm-no-wait", class_obscure, ++ bdm_set_no_wait, ++ "Cause GDB to not wait for the target to stop when running."); ++ add_com ("bdm-wait", class_obscure, ++ bdm_set_wait, ++ "Cause GDB to wait for the target to stop when running."); ++ add_com ("bdm-stop", class_obscure, ++ bdm_issue_stop, ++ "Stop the target if running."); ++ add_com ("bdm-select-cpu32", class_obscure, ++ bdm_select_cpu32, ++ "Selects the CPU32 register set rather than the default CPU32+."); ++ add_com ("bdm-no-load", class_obscure, ++ bdm_toggle_no_load, ++ "Toggle the loading of the program to memory when asked to run."); ++ add_com ("bdm-cf-pst", class_obscure, ++ bdm_cf_pst, ++ "Get or set the use of the PST signals."); ++ add_com ("bdm-read-creg", class_obscure, ++ bdm_read_control_reg, ++ "Read a control register from the processor."); ++ add_com ("bdm-write-creg", class_obscure, ++ bdm_write_control_reg, ++ "Write a control register from the processor."); ++ ++ add_target (&bdm_ops); ++} diff --git a/gdb/patches/gdb-6.3-bdm-m68k.patch b/gdb/patches/gdb-6.3-bdm-m68k.patch new file mode 100644 index 0000000..21c256d --- /dev/null +++ b/gdb/patches/gdb-6.3-bdm-m68k.patch @@ -0,0 +1,2504 @@ +diff -Nru gdb-6.3.orig/gdb/config/m68k/bdm.mt gdb-6.3/gdb/config/m68k/bdm.mt +--- gdb-6.3.orig/gdb/config/m68k/bdm.mt 1970-01-01 10:00:00.000000000 +1000 ++++ gdb-6.3/gdb/config/m68k/bdm.mt 2005-10-22 14:19:56.000000000 +1000 +@@ -0,0 +1,5 @@ ++# Target: m68k bdm interface for the CPU32 and Coldfire processors. ++# ++TM_CLIBS= -L$(prefix)/lib -lBDM ++TDEPFILES= m68k-tdep.o remote-m68k-bdm.o ++DEPRECATED_TM_FILE= tm-bdm.h +diff -Nru gdb-6.3.orig/gdb/config/m68k/tm-bdm.h gdb-6.3/gdb/config/m68k/tm-bdm.h +--- gdb-6.3.orig/gdb/config/m68k/tm-bdm.h 1970-01-01 10:00:00.000000000 +1000 ++++ gdb-6.3/gdb/config/m68k/tm-bdm.h 2005-10-24 07:58:43.000000000 +1000 +@@ -0,0 +1,89 @@ ++/* ++ * Target machine description for Coldfire BDM (Moto 5200) ++ * Copyright (C) 1995 W. Eric Norum ++ * Copyright (C) 1998 Chris Johns (ccj@acm.org) ++ * ++ * Based on: ++ * 1. `A Background Debug Mode Driver Package for Motorola's ++ * 16- and 32-Bit Microcontrollers', Scott Howard, Motorola ++ * Canada, 1993. ++ * 2. `Linux device driver for public domain BDM Interface', ++ * M. Schraut, Technische Universitaet Muenchen, Lehrstuhl ++ * fuer Prozessrechner, 1995. ++ * 3. BDM support for gdb by W. Eric Norum ++ * Saskatchewan Accelerator Laboratory ++ * University of Saskatchewan ++ * 107 North Road ++ * Saskatoon, Saskatchewan, CANADA ++ * S7N 5C6 ++ * ++ * 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. ++ */ ++ ++#include "breakpoint.h" ++ ++/* ++ * Function prototypes ++ */ ++extern const unsigned char *m68k_bdm_breakpoint_from_pc (CORE_ADDR *pcptr, int *lenptr); ++extern CORE_ADDR m68k_bdm_saved_pc_after_call (struct frame_info *); ++extern int m68k_bdm_decr_pc_after_break(); ++extern int m68k_bdm_have_nonsteppable_watchpoint(); ++ ++ ++/* ++ * Coldfire does it for us if we use PCC to get the PC ++ */ ++#define DECR_PC_AFTER_BREAK m68k_bdm_decr_pc_after_break() ++ ++/* ++ * We have to control this directly as the CPU32 and Coldfire have different ++ * breakpoint opcodes. ++ */ ++#define BREAKPOINT_FROM_PC m68k_bdm_breakpoint_from_pc ++ ++/* ++ * Define the number of registers as a function. ++ */ ++#define NUM_REGS m68k_bdm_num_regs () ++ ++/* ++ * Override some of the generic definitions ++ */ ++ ++/* ++ * For uCLinux we need to detect we have a subroutine call ++ * which is really a trap #0. This should be caught by the ++ * the IN_SIGTRAMP handler defined above, but incase it is ++ * not we should try and catch it here. ++ */ ++ ++#undef SAVED_PC_AFTER_CALL ++#define SAVED_PC_AFTER_CALL(frame) \ ++ (m68k_bdm_saved_pc_after_call (frame)) ++ ++/* ++ * The other definitions and macros don't need to be changed: ++ * a) The Coldfire has no floating point registers ++ * b) The REGISTER_BYTES_OK macro isn't used ++ */ ++ ++#define TARGET_HAS_HARDWARE_WATCHPOINTS ++ ++/* We need to remove watchpoints when stepping, else we hit them again! */ ++ ++#define HAVE_NONSTEPPABLE_WATCHPOINT m68k_bdm_have_nonsteppable_watchpoint() +diff -Nru gdb-6.3.orig/gdb/configure.tgt gdb-6.3/gdb/configure.tgt +--- gdb-6.3.orig/gdb/configure.tgt 2004-10-01 17:29:34.000000000 +1000 ++++ gdb-6.3/gdb/configure.tgt 2005-10-22 14:19:56.000000000 +1000 +@@ -110,6 +110,7 @@ + m32r*-*-*) gdb_target=m32r ;; + + m68hc11*-*-*|m6811*-*-*) gdb_target=m68hc11 ;; ++m68*-bdm-*) gdb_target=bdm ;; + + m68*-cisco*-*) gdb_target=cisco ;; + m68*-netx-*) gdb_target=vxworks68 ;; +diff -Nru gdb-6.3.orig/gdb/doc/gdb.texinfo gdb-6.3/gdb/doc/gdb.texinfo +--- gdb-6.3.orig/gdb/doc/gdb.texinfo 2004-10-09 05:19:03.000000000 +1000 ++++ gdb-6.3/gdb/doc/gdb.texinfo 2005-10-22 14:19:56.000000000 +1000 +@@ -6975,7 +6975,7 @@ + This command takes no arguments. It ends the trace experiment, and + stops collecting data. + +-@strong{Note:} a trace experiment and data collection may stop ++Note that a trace experiment and data collection may stop + automatically if any tracepoint's passcount is reached + (@pxref{Tracepoint Passcounts}), or if the trace buffer becomes full. + +@@ -12371,6 +12371,7 @@ + * H8/500:: Renesas H8/500 + * M32R/D:: Renesas M32R/D + * M68K:: Motorola M68K ++* Motorola BDM:: Motorola M68K/Coldfire Background Debug Mode + * MIPS Embedded:: MIPS Embedded + * OpenRISC 1000:: OpenRisc 1000 + * PA:: HP PA Embedded +@@ -12649,6 +12650,10 @@ + @item target abug @var{dev} + ABug ROM monitor for M68K. + ++@kindex target bdm ++Background Debug Mode interface to Motorola 68k/Coldfire machine. ++@xref{Motorola BDM, ,@value{GDBN} and Motorola 68k/Coldfire BDM}. ++ + @kindex target cpu32bug + @item target cpu32bug @var{dev} + CPU32BUG monitor, running on a CPU32 (M68K) board. +@@ -12675,6 +12680,101 @@ + + @end table + ++ ++@node Motorola BDM ++@subsection @value{GDBN} and Motorola BDM ++ ++@cindex BDM ++@cindex CPU32 ++@cindex Coldfire ++Background Debug Mode (@dfn{BDM}) provides a full set of debug options ++including the ability to: ++@itemize @bullet ++@item Insert breakpoints ++@item Single-step ++@item Display register contents ++@item Display memory contents ++@item Modify register contents ++@item Modify memory contents ++@end itemize ++ ++A small interface circuit connects the BDM interface port on the ++target machine to a parallel printer port on the debugging host. ++A target system can be configured and a program downloaded and ++executed with no bootstrap memory on the target machine and no other ++connection between the debugging host and the target machine. ++ ++The @code{target} command tells @value{GDBN} ++to debug a program running on a target machine ++@xref{Target Commands, ,Commands for managing targets}. ++For example, the following command tells @value{GDBN} to use a BDM ++interface connected to a ColdFire processor and the @code{LPT0} parallel port: ++@example ++target bdm /dev/bdmcf0 ++@end example ++ ++Do not attempt to use the parallel port for any other purpose while ++@value{GDBN} is using it to control a BDM target. ++ ++Once the BDM target has been selected a few other commands become ++available: ++ ++@table @code ++@item bdm_reset ++@kindex bdm_reset ++Reset the target machine and enable BDM operation in the target. ++ ++@item bdm_restart ++@kindex bdm_restart ++Reset the target machine and disable BDM operation in the target. ++This command is useful only if the target machine has some kind of ++bootstrap memory installed. ++ ++@item bdm_status ++@kindex bdm_status ++Print the status of the target machine and the BDM interface. ++ ++@item bdm_setdelay @var{N} ++@kindex bdm_setdelay ++Some BDM interface circuits can not handle high-speed data transfer. ++This command lets you insert a delay between each BDM clock. ++The larger the value of @var{N}, the longer the delay. ++On most machines the default delay of @var{0} should work just fine. ++ ++@item bdm_setdebug @var{N} ++@kindex bdm_setdebug ++Setting the level (@var{N}) to a non-zero value turns on ++debugging messages in the BDM support library. ++ ++@item bdm_setdriverdebug @var{N} ++@kindex bdm_setdriverdebug ++Setting the level (@var{N}) to a non-zero value turns on ++debugging messages in the BDM device driver. ++ ++@end table ++ ++The registers which can be displayed and modified are: ++@itemize @bullet ++@item The data registers: @code{$d0}-@code{$d7} ++@item The address registers: @code{$a0}-@code{$a5}, @code{$fp}, @code{$sp} ++@item The program counter: @code{$pc} ++@item The status register: @code{$ps} ++@item The program counter at the beginning of the most recently executed ++instruction: @code{$pcc} ++@item The user stack pointer: @code{$usp} ++@item The supervisor stack pointer: @code{$ssp} ++@item The source function code register: @code{$sfc} ++@item The destinaton function code register: @code{$dfc} ++@item The vector base register: @code{$vbr} ++@item The fault address register: @code{$far} ++@item The BDM temporary register: @code{$atemp} ++@item The module base address register: @code{$mbar} ++@end itemize ++ ++Target processor interrupts are disabled during single-step (step, next, ++stepi, nexti) operations. ++ ++ + @node MIPS Embedded + @subsection MIPS Embedded + +diff -Nru gdb-6.3.orig/gdb/gdbserver/configure.srv gdb-6.3/gdb/gdbserver/configure.srv +--- gdb-6.3.orig/gdb/gdbserver/configure.srv 2003-08-08 10:47:28.000000000 +1000 ++++ gdb-6.3/gdb/gdbserver/configure.srv 2005-10-22 14:19:56.000000000 +1000 +@@ -37,6 +37,11 @@ + srv_tgtobj="linux-low.o linux-m68k-low.o" + srv_linux_usrregs=yes + ;; ++ m68*-*-elf*) srv_regobj=reg-m68k.o ++ srv_tgtobj="linux-low.o linux-m68k-low.o" ++ srv_linux_usrregs=yes ++ ;; ++ + mips*-*-linux*) srv_regobj=reg-mips.o + srv_tgtobj="linux-low.o linux-mips-low.o" + srv_linux_usrregs=yes +diff -Nru gdb-6.3.orig/gdb/infcmd.c gdb-6.3/gdb/infcmd.c +--- gdb-6.3.orig/gdb/infcmd.c 2004-09-14 04:26:28.000000000 +1000 ++++ gdb-6.3/gdb/infcmd.c 2005-10-22 14:19:56.000000000 +1000 +@@ -1288,8 +1288,10 @@ + "finish_command: function has no target type"); + + /* FIXME: Shouldn't we do the cleanups before returning? */ +- if (TYPE_CODE (value_type) == TYPE_CODE_VOID) ++ if (TYPE_CODE (value_type) == TYPE_CODE_VOID) { ++ do_cleanups (old_chain); + return; ++ } + + CHECK_TYPEDEF (value_type); + gcc_compiled = BLOCK_GCC_COMPILED (SYMBOL_BLOCK_VALUE (function)); +diff -Nru gdb-6.3.orig/gdb/Makefile.in gdb-6.3/gdb/Makefile.in +--- gdb-6.3.orig/gdb/Makefile.in 2004-11-04 13:18:49.000000000 +1100 ++++ gdb-6.3/gdb/Makefile.in 2005-10-22 14:19:56.000000000 +1000 +@@ -1403,7 +1403,7 @@ + ppcobsd-nat.c ppcobsd-tdep.c \ + procfs.c \ + remote-e7000.c \ +- remote-hms.c remote-m32r-sdi.c remote-mips.c \ ++ remote-hms.c remote-m32r-sdi.c remote-m68k-bdm.c remote-mips.c \ + remote-rdp.c remote-sim.c \ + remote-st.c remote-utils.c dcache.c \ + remote-vx.c \ +@@ -2381,6 +2381,8 @@ + $(serial_h) $(regcache_h) + remote-m32r-sdi.o: remote-m32r-sdi.c $(defs_h) $(gdbcmd_h) $(gdbcore_h) \ + $(inferior_h) $(target_h) $(regcache_h) $(gdb_string_h) $(serial_h) ++remote-m68k-bdm.o: remote-m68k-bdm.c $(defs_h) $(gdbcmd_h) $(gdbcore_h) \ ++ $(defs_h) $(inferior_h) $(target_h) $(wait_h) + remote-mips.o: remote-mips.c $(defs_h) $(inferior_h) $(bfd_h) $(symfile_h) \ + $(gdbcmd_h) $(gdbcore_h) $(serial_h) $(target_h) $(remote_utils_h) \ + $(gdb_string_h) $(gdb_stat_h) $(regcache_h) $(mips_tdep_h) +diff -Nru gdb-6.3.orig/gdb/remote-m68k-bdm.c gdb-6.3/gdb/remote-m68k-bdm.c +--- gdb-6.3.orig/gdb/remote-m68k-bdm.c 1970-01-01 10:00:00.000000000 +1000 ++++ gdb-6.3/gdb/remote-m68k-bdm.c 2005-10-24 09:46:29.000000000 +1000 +@@ -0,0 +1,2203 @@ ++/* ++ * Motorola Background Debug Mode Target ++ * Copyright (C) 1995 W. Eric Norum ++ * Copyright (C) 1998 Chris Johns (ccj@acm.org) ++ * Copyright (C) 2000 Bryan Feir (bryan@sgl.crestech.ca) ++ * ++ * Based on: ++ * 1. `A Background Debug Mode Driver Package for Motorola's ++ * 16- and 32-Bit Microcontrollers', Scott Howard, Motorola ++ * Canada, 1993. ++ * 2. `Linux device driver for public domain BDM Interface', ++ * M. Schraut, Technische Universitaet Muenchen, Lehrstuhl ++ * fuer Prozessrechner, 1995. ++ * 3. BDM support for gdb by W. Eric Norum ++ * Saskatchewan Accelerator Laboratory ++ * University of Saskatchewan ++ * 107 North Road ++ * Saskatoon, Saskatchewan, CANADA ++ * S7N 5C6 ++ * 4. Coldfire support added by C Johns. ++ * 5. Hardware breakpoint support added by B Feir. ++ * ++ * 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. ++ * ++ * W. Eric Norum ++ * Saskatchewan Accelerator Laboratory ++ * University of Saskatchewan ++ * 107 North Road ++ * Saskatoon, Saskatchewan, CANADA ++ * S7N 5C6 ++ * ++ * eric@skatter.usask.ca ++ * ++ * Coldfire support by: ++ * Chris Johns ++ * Objective Design Systems ++ * 35 Cairo Street ++ * Cammeray, Sydney, 2062, Australia ++ * ++ * ccj@acm.org ++ * ++ * Coldfire hardware breakpoint support by: ++ * Bryan Feir ++ * CRESTech (Centre for Research in Earth and Space Technology) ++ * 4850 Keele Street, 1st floor ++ * Toronto, Ontario, CANADA M6E 3E5 ++ * ++ * bryan@sgl.crestech.ca ++ */ ++ ++/* ++ * $Revision: 1.4 $ $Date: 2005/10/24 02:16:51 $ $Author: cjohns $ ++ */ ++ ++#include "defs.h" ++#include "gdbcore.h" ++#include "target.h" ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "command.h" ++#include "inferior.h" ++#include "gdbtypes.h" ++#include "value.h" ++#include "breakpoint.h" ++#include "regcache.h" ++#include "BDMlib.h" ++ ++/* ++ * Here for now, but this should go. It should not be needed. ++ */ ++#define IS_BDM (!strcmp(target_shortname, "bdm")) ++ ++extern struct target_ops bdm_ops; /* Forward declaration */ ++ ++/* ++ * The name of the BDM driver special file ++ */ ++static char* dev_name; ++static int cpu_family; ++static int cpu_type; ++ ++/* ++ * The type of CPU. ++ */ ++#define BDM_MARCH_CPU32 (0) ++#define BDM_MARCH_CPU32PLUS (1) ++#define BDM_MARCH_CF5200 (2) ++#define BDM_MARCH_CF5252 (3) ++#define BDM_MARCH_CF5282 (4) ++#define BDM_MARCH_CFV4E (5) ++ ++/* ++ * The different register names for the processors. ++ */ ++ ++/* ++ * Mark a register as a control register using this define. ++ */ ++#define BDM_REG_CONTROL_REG (1 << 31) ++#define BDM_REG_CONTROL_REG_MASK (~(1 << 31)) ++ ++/* ++ * Hold a mapping from a register number to a register type ++ * and device number type. The register number comes from the ++ * register name. ++ */ ++struct m68k_bdm_reg_mapping ++{ ++ const char* name; ++ struct type** type; ++ unsigned int code; ++}; ++ ++/* ++ * The standard CPU32 core. ++ */ ++ ++static struct m68k_bdm_reg_mapping cpu32_reg_map[] = { ++ { "d0", &builtin_type_int32, BDM_REG_D0 }, ++ { "d1", &builtin_type_int32, BDM_REG_D1 }, ++ { "d2", &builtin_type_int32, BDM_REG_D2 }, ++ { "d3", &builtin_type_int32, BDM_REG_D3 }, ++ { "d4", &builtin_type_int32, BDM_REG_D4 }, ++ { "d5", &builtin_type_int32, BDM_REG_D5 }, ++ { "d6", &builtin_type_int32, BDM_REG_D6 }, ++ { "d7", &builtin_type_int32, BDM_REG_D7 }, ++ { "a0", &builtin_type_void_data_ptr, BDM_REG_A0 }, ++ { "a1", &builtin_type_void_data_ptr, BDM_REG_A1 }, ++ { "a2", &builtin_type_void_data_ptr, BDM_REG_A2 }, ++ { "a3", &builtin_type_void_data_ptr, BDM_REG_A3 }, ++ { "a4", &builtin_type_void_data_ptr, BDM_REG_A4 }, ++ { "a5", &builtin_type_void_data_ptr, BDM_REG_A5 }, ++ { "fp", &builtin_type_void_data_ptr, BDM_REG_A6 }, ++ { "sp", &builtin_type_void_data_ptr, BDM_REG_A7 }, ++ { "ps", &builtin_type_int32, BDM_REG_SR }, ++ { "pc", &builtin_type_int32, BDM_REG_RPC }, ++ { "pcc", &builtin_type_int32, BDM_REG_PCC }, ++ { "usp", &builtin_type_void_data_ptr, BDM_REG_USP }, ++ { "ssp", &builtin_type_void_data_ptr, BDM_REG_SSP }, ++ { "sfc", &builtin_type_int32, BDM_REG_SFC }, ++ { "dfc", &builtin_type_int32, BDM_REG_DFC }, ++ { "vbr", &builtin_type_void_data_ptr, BDM_REG_VBR } ++}; ++ ++/* ++ * The CPU32+ core, ie 68360. ++ */ ++ ++static struct m68k_bdm_reg_mapping cpu32plus_reg_map[] = { ++ { "d0", &builtin_type_int32, BDM_REG_D0 }, ++ { "d1", &builtin_type_int32, BDM_REG_D1 }, ++ { "d2", &builtin_type_int32, BDM_REG_D2 }, ++ { "d3", &builtin_type_int32, BDM_REG_D3 }, ++ { "d4", &builtin_type_int32, BDM_REG_D4 }, ++ { "d5", &builtin_type_int32, BDM_REG_D5 }, ++ { "d6", &builtin_type_int32, BDM_REG_D6 }, ++ { "d7", &builtin_type_int32, BDM_REG_D7 }, ++ { "a0", &builtin_type_void_data_ptr, BDM_REG_A0 }, ++ { "a1", &builtin_type_void_data_ptr, BDM_REG_A1 }, ++ { "a2", &builtin_type_void_data_ptr, BDM_REG_A2 }, ++ { "a3", &builtin_type_void_data_ptr, BDM_REG_A3 }, ++ { "a4", &builtin_type_void_data_ptr, BDM_REG_A4 }, ++ { "a5", &builtin_type_void_data_ptr, BDM_REG_A5 }, ++ { "fp", &builtin_type_void_data_ptr, BDM_REG_A6 }, ++ { "sp", &builtin_type_void_data_ptr, BDM_REG_A7 }, ++ { "ps", &builtin_type_int32, BDM_REG_SR }, ++ { "pc", &builtin_type_int32, BDM_REG_RPC }, ++ { "pcc", &builtin_type_int32, BDM_REG_PCC }, ++ { "usp", &builtin_type_void_data_ptr, BDM_REG_USP }, ++ { "ssp", &builtin_type_void_data_ptr, BDM_REG_SSP }, ++ { "sfc", &builtin_type_int32, BDM_REG_SFC }, ++ { "dfc", &builtin_type_int32, BDM_REG_DFC }, ++ { "vbr", &builtin_type_void_data_ptr, BDM_REG_VBR }, ++ { "atemp", &builtin_type_void_data_ptr, BDM_REG_ATEMP }, ++ { "far", &builtin_type_void_data_ptr, BDM_REG_FAR }, ++ { "vbr", &builtin_type_void_data_ptr, BDM_REG_VBR }, ++ { "mbar", &builtin_type_int32, BDM_REG_MBAR } ++}; ++ ++/* ++ * Generic Coldfire Register set, m5200. ++ */ ++ ++static struct m68k_bdm_reg_mapping cf5200_reg_map[] = { ++ { "d0", &builtin_type_int32, BDM_REG_D0 }, ++ { "d1", &builtin_type_int32, BDM_REG_D1 }, ++ { "d2", &builtin_type_int32, BDM_REG_D2 }, ++ { "d3", &builtin_type_int32, BDM_REG_D3 }, ++ { "d4", &builtin_type_int32, BDM_REG_D4 }, ++ { "d5", &builtin_type_int32, BDM_REG_D5 }, ++ { "d6", &builtin_type_int32, BDM_REG_D6 }, ++ { "d7", &builtin_type_int32, BDM_REG_D7 }, ++ { "a0", &builtin_type_void_data_ptr, BDM_REG_A0 }, ++ { "a1", &builtin_type_void_data_ptr, BDM_REG_A1 }, ++ { "a2", &builtin_type_void_data_ptr, BDM_REG_A2 }, ++ { "a3", &builtin_type_void_data_ptr, BDM_REG_A3 }, ++ { "a4", &builtin_type_void_data_ptr, BDM_REG_A4 }, ++ { "a5", &builtin_type_void_data_ptr, BDM_REG_A5 }, ++ { "fp", &builtin_type_void_data_ptr, BDM_REG_A6 }, ++ { "sp", &builtin_type_void_data_ptr, BDM_REG_A7 }, ++ { "ps", &builtin_type_int32, BDM_REG_SR }, ++ { "pc", &builtin_type_int32, BDM_REG_RPC }, ++ { "vbr", &builtin_type_void_data_ptr, BDM_REG_CONTROL_REG | BDM_REG_VBR }, ++ { "cacr", &builtin_type_int32, BDM_REG_CONTROL_REG | BDM_REG_CACR }, ++ { "acr0", &builtin_type_int32, BDM_REG_CONTROL_REG | BDM_REG_ACR0 }, ++ { "acr1", &builtin_type_int32, BDM_REG_CONTROL_REG | BDM_REG_ACR1 }, ++ { "rambar", &builtin_type_int32, BDM_REG_CONTROL_REG | BDM_REG_RAMBAR }, ++ { "mbar", &builtin_type_int32, BDM_REG_CONTROL_REG | BDM_REG_MBAR }, ++ { "csr", &builtin_type_int32, BDM_REG_CONTROL_REG | BDM_REG_CSR }, ++ { "aatr", &builtin_type_int32, BDM_REG_CONTROL_REG | BDM_REG_AATR }, ++ { "tdr", &builtin_type_int32, BDM_REG_CONTROL_REG | BDM_REG_TDR }, ++ { "pbr", &builtin_type_int32, BDM_REG_CONTROL_REG | BDM_REG_PBR }, ++ { "pbmr", &builtin_type_int32, BDM_REG_CONTROL_REG | BDM_REG_PBMR }, ++ { "abhr", &builtin_type_int32, BDM_REG_CONTROL_REG | BDM_REG_ABHR }, ++ { "ablr", &builtin_type_int32, BDM_REG_CONTROL_REG | BDM_REG_ABLR }, ++ { "dbr", &builtin_type_int32, BDM_REG_CONTROL_REG | BDM_REG_DBR }, ++ { "dbmr", &builtin_type_int32, BDM_REG_CONTROL_REG | BDM_REG_DBMR } ++}; ++ ++/* ++ * 5272 Coldfire Register set. Has the EMAC. ++ */ ++ ++static struct m68k_bdm_reg_mapping cf5272_reg_map[] = { ++ { "d0", &builtin_type_int32, BDM_REG_D0 }, ++ { "d1", &builtin_type_int32, BDM_REG_D1 }, ++ { "d2", &builtin_type_int32, BDM_REG_D2 }, ++ { "d3", &builtin_type_int32, BDM_REG_D3 }, ++ { "d4", &builtin_type_int32, BDM_REG_D4 }, ++ { "d5", &builtin_type_int32, BDM_REG_D5 }, ++ { "d6", &builtin_type_int32, BDM_REG_D6 }, ++ { "d7", &builtin_type_int32, BDM_REG_D7 }, ++ { "a0", &builtin_type_void_data_ptr, BDM_REG_A0 }, ++ { "a1", &builtin_type_void_data_ptr, BDM_REG_A1 }, ++ { "a2", &builtin_type_void_data_ptr, BDM_REG_A2 }, ++ { "a3", &builtin_type_void_data_ptr, BDM_REG_A3 }, ++ { "a4", &builtin_type_void_data_ptr, BDM_REG_A4 }, ++ { "a5", &builtin_type_void_data_ptr, BDM_REG_A5 }, ++ { "fp", &builtin_type_void_data_ptr, BDM_REG_A6 }, ++ { "sp", &builtin_type_void_data_ptr, BDM_REG_A7 }, ++ { "ps", &builtin_type_int32, BDM_REG_SR }, ++ { "pc", &builtin_type_int32, BDM_REG_RPC }, ++ { "vbr", &builtin_type_void_data_ptr, BDM_REG_CONTROL_REG | BDM_REG_VBR }, ++ { "cacr", &builtin_type_int32, BDM_REG_CONTROL_REG | BDM_REG_CACR }, ++ { "acr0", &builtin_type_int32, BDM_REG_CONTROL_REG | BDM_REG_ACR0 }, ++ { "acr1", &builtin_type_int32, BDM_REG_CONTROL_REG | BDM_REG_ACR1 }, ++ { "rambar", &builtin_type_int32, BDM_REG_CONTROL_REG | BDM_REG_RAMBAR }, ++ { "mbar", &builtin_type_int32, BDM_REG_CONTROL_REG | BDM_REG_MBAR }, ++ { "csr", &builtin_type_int32, BDM_REG_CONTROL_REG | BDM_REG_CSR }, ++ { "aatr", &builtin_type_int32, BDM_REG_CONTROL_REG | BDM_REG_AATR }, ++ { "tdr", &builtin_type_int32, BDM_REG_CONTROL_REG | BDM_REG_TDR }, ++ { "pbr", &builtin_type_int32, BDM_REG_CONTROL_REG | BDM_REG_PBR }, ++ { "pbmr", &builtin_type_int32, BDM_REG_CONTROL_REG | BDM_REG_PBMR }, ++ { "abhr", &builtin_type_int32, BDM_REG_CONTROL_REG | BDM_REG_ABHR }, ++ { "ablr", &builtin_type_int32, BDM_REG_CONTROL_REG | BDM_REG_ABLR }, ++ { "dbr", &builtin_type_int32, BDM_REG_CONTROL_REG | BDM_REG_DBR }, ++ { "dbmr", &builtin_type_int32, BDM_REG_CONTROL_REG | BDM_REG_DBMR }, ++ { "macsr", &builtin_type_int32, BDM_REG_CONTROL_REG | 0x804 }, ++ { "mask", &builtin_type_int32, BDM_REG_CONTROL_REG | 0x805 }, ++ { "acc", &builtin_type_int32, BDM_REG_CONTROL_REG | 0x806 } ++}; ++ ++/* ++ * 5282 Coldfire Register set. Has the extended EMAC, no MBAR. ++ */ ++ ++static struct m68k_bdm_reg_mapping cf5282_reg_map[] = { ++ { "d0", &builtin_type_int32, BDM_REG_D0 }, ++ { "d1", &builtin_type_int32, BDM_REG_D1 }, ++ { "d2", &builtin_type_int32, BDM_REG_D2 }, ++ { "d3", &builtin_type_int32, BDM_REG_D3 }, ++ { "d4", &builtin_type_int32, BDM_REG_D4 }, ++ { "d5", &builtin_type_int32, BDM_REG_D5 }, ++ { "d6", &builtin_type_int32, BDM_REG_D6 }, ++ { "d7", &builtin_type_int32, BDM_REG_D7 }, ++ { "a0", &builtin_type_void_data_ptr, BDM_REG_A0 }, ++ { "a1", &builtin_type_void_data_ptr, BDM_REG_A1 }, ++ { "a2", &builtin_type_void_data_ptr, BDM_REG_A2 }, ++ { "a3", &builtin_type_void_data_ptr, BDM_REG_A3 }, ++ { "a4", &builtin_type_void_data_ptr, BDM_REG_A4 }, ++ { "a5", &builtin_type_void_data_ptr, BDM_REG_A5 }, ++ { "fp", &builtin_type_void_data_ptr, BDM_REG_A6 }, ++ { "sp", &builtin_type_void_data_ptr, BDM_REG_A7 }, ++ { "ps", &builtin_type_int32, BDM_REG_SR }, ++ { "pc", &builtin_type_int32, BDM_REG_RPC }, ++ { "vbr", &builtin_type_void_data_ptr, BDM_REG_CONTROL_REG | BDM_REG_VBR }, ++ { "cacr", &builtin_type_int32, BDM_REG_CONTROL_REG | BDM_REG_CACR }, ++ { "acr0", &builtin_type_int32, BDM_REG_CONTROL_REG | BDM_REG_ACR0 }, ++ { "acr1", &builtin_type_int32, BDM_REG_CONTROL_REG | BDM_REG_ACR1 }, ++ { "rambar", &builtin_type_int32, BDM_REG_CONTROL_REG | BDM_REG_RAMBAR }, ++ { "flashbar", &builtin_type_int32, BDM_REG_CONTROL_REG | BDM_REG_MBAR }, ++ { "csr", &builtin_type_int32, BDM_REG_CONTROL_REG | BDM_REG_CSR }, ++ { "aatr", &builtin_type_int32, BDM_REG_CONTROL_REG | BDM_REG_AATR }, ++ { "tdr", &builtin_type_int32, BDM_REG_CONTROL_REG | BDM_REG_TDR }, ++ { "pbr", &builtin_type_int32, BDM_REG_CONTROL_REG | BDM_REG_PBR }, ++ { "pbmr", &builtin_type_int32, BDM_REG_CONTROL_REG | BDM_REG_PBMR }, ++ { "abhr", &builtin_type_int32, BDM_REG_CONTROL_REG | BDM_REG_ABHR }, ++ { "ablr", &builtin_type_int32, BDM_REG_CONTROL_REG | BDM_REG_ABLR }, ++ { "dbr", &builtin_type_int32, BDM_REG_CONTROL_REG | BDM_REG_DBR }, ++ { "dbmr", &builtin_type_int32, BDM_REG_CONTROL_REG | BDM_REG_DBMR }, ++ { "macsr", &builtin_type_int32, BDM_REG_CONTROL_REG | 0x804 }, ++ { "mask", &builtin_type_int32, BDM_REG_CONTROL_REG | 0x805 }, ++ { "acc0", &builtin_type_int32, BDM_REG_CONTROL_REG | 0x806 }, ++ { "acc1", &builtin_type_int32, BDM_REG_CONTROL_REG | 0x809 }, ++ { "acc2", &builtin_type_int32, BDM_REG_CONTROL_REG | 0x80a }, ++ { "acc3", &builtin_type_int32, BDM_REG_CONTROL_REG | 0x80b }, ++ { "accext01", &builtin_type_int32, BDM_REG_CONTROL_REG | 0x807 }, ++ { "accext32", &builtin_type_int32, BDM_REG_CONTROL_REG | 0x808 } ++}; ++ ++/* ++ * 5282 Coldfire Register set. Has the extended EMAC, no MBAR. ++ */ ++ ++static struct m68k_bdm_reg_mapping cfv4e_reg_map[] = { ++ { "d0", &builtin_type_int32, BDM_REG_D0 }, ++ { "d1", &builtin_type_int32, BDM_REG_D1 }, ++ { "d2", &builtin_type_int32, BDM_REG_D2 }, ++ { "d3", &builtin_type_int32, BDM_REG_D3 }, ++ { "d4", &builtin_type_int32, BDM_REG_D4 }, ++ { "d5", &builtin_type_int32, BDM_REG_D5 }, ++ { "d6", &builtin_type_int32, BDM_REG_D6 }, ++ { "d7", &builtin_type_int32, BDM_REG_D7 }, ++ { "a0", &builtin_type_void_data_ptr, BDM_REG_A0 }, ++ { "a1", &builtin_type_void_data_ptr, BDM_REG_A1 }, ++ { "a2", &builtin_type_void_data_ptr, BDM_REG_A2 }, ++ { "a3", &builtin_type_void_data_ptr, BDM_REG_A3 }, ++ { "a4", &builtin_type_void_data_ptr, BDM_REG_A4 }, ++ { "a5", &builtin_type_void_data_ptr, BDM_REG_A5 }, ++ { "fp", &builtin_type_void_data_ptr, BDM_REG_A6 }, ++ { "sp", &builtin_type_void_data_ptr, BDM_REG_A7 }, ++ { "ps", &builtin_type_int32, BDM_REG_CONTROL_REG | 0x80e }, ++ { "pc", &builtin_type_int32, BDM_REG_CONTROL_REG | 0x80f }, ++ { "vbr", &builtin_type_void_data_ptr, BDM_REG_CONTROL_REG | 0x801 }, ++ { "cacr", &builtin_type_int32, BDM_REG_CONTROL_REG | 0x002 }, ++ { "asid", &builtin_type_int32, BDM_REG_CONTROL_REG | 0x003 }, ++ { "acr0", &builtin_type_int32, BDM_REG_CONTROL_REG | 0x004 }, ++ { "acr1", &builtin_type_int32, BDM_REG_CONTROL_REG | 0x005 }, ++ { "acr2", &builtin_type_int32, BDM_REG_CONTROL_REG | 0x006 }, ++ { "acr3", &builtin_type_int32, BDM_REG_CONTROL_REG | 0x007 }, ++ { "mmubar", &builtin_type_int32, BDM_REG_CONTROL_REG | 0x008 }, ++ { "mbar", &builtin_type_int32, BDM_REG_CONTROL_REG | 0xc0f }, ++ { "rambar0", &builtin_type_int32, BDM_REG_CONTROL_REG | 0xc04 }, ++ { "rambar1", &builtin_type_int32, BDM_REG_CONTROL_REG | 0xc05 }, ++ { "csr", &builtin_type_int32, BDM_REG_CONTROL_REG | BDM_REG_CSR }, ++ { "aatr", &builtin_type_int32, BDM_REG_CONTROL_REG | BDM_REG_AATR }, ++ { "tdr", &builtin_type_int32, BDM_REG_CONTROL_REG | BDM_REG_TDR }, ++ { "pbr", &builtin_type_int32, BDM_REG_CONTROL_REG | BDM_REG_PBR }, ++ { "pbmr", &builtin_type_int32, BDM_REG_CONTROL_REG | BDM_REG_PBMR }, ++ { "abhr", &builtin_type_int32, BDM_REG_CONTROL_REG | BDM_REG_ABHR }, ++ { "ablr", &builtin_type_int32, BDM_REG_CONTROL_REG | BDM_REG_ABLR }, ++ { "dbr", &builtin_type_int32, BDM_REG_CONTROL_REG | BDM_REG_DBR }, ++ { "dbmr", &builtin_type_int32, BDM_REG_CONTROL_REG | BDM_REG_DBMR }, ++ { "macsr", &builtin_type_int32, BDM_REG_CONTROL_REG | 0x804 }, ++ { "mask", &builtin_type_int32, BDM_REG_CONTROL_REG | 0x805 }, ++ { "acc0", &builtin_type_int32, BDM_REG_CONTROL_REG | 0x806 }, ++ { "acc1", &builtin_type_int32, BDM_REG_CONTROL_REG | 0x809 }, ++ { "acc2", &builtin_type_int32, BDM_REG_CONTROL_REG | 0x80a }, ++ { "acc3", &builtin_type_int32, BDM_REG_CONTROL_REG | 0x80b }, ++ { "accext01", &builtin_type_int32, BDM_REG_CONTROL_REG | 0x807 }, ++ { "accext32", &builtin_type_int32, BDM_REG_CONTROL_REG | 0x808 }, ++ { "fp0", &builtin_type_m68881_ext, BDM_REG_CONTROL_REG | 0x810 }, ++ { "fp1", &builtin_type_m68881_ext, BDM_REG_CONTROL_REG | 0x812 }, ++ { "fp2", &builtin_type_m68881_ext, BDM_REG_CONTROL_REG | 0x814 }, ++ { "fp3", &builtin_type_m68881_ext, BDM_REG_CONTROL_REG | 0x816 }, ++ { "fp4", &builtin_type_m68881_ext, BDM_REG_CONTROL_REG | 0x818 }, ++ { "fp5", &builtin_type_m68881_ext, BDM_REG_CONTROL_REG | 0x81a }, ++ { "fp7", &builtin_type_m68881_ext, BDM_REG_CONTROL_REG | 0x81c }, ++ { "fpiar", &builtin_type_int32, BDM_REG_CONTROL_REG | 0x821 }, ++ { "fpsr", &builtin_type_int32, BDM_REG_CONTROL_REG | 0x822 }, ++ { "fpcr", &builtin_type_int32, BDM_REG_CONTROL_REG | 0x824 } ++}; ++ ++/* ++ * The array of registers for each support processor. ++ */ ++struct m68k_bdm_registers { ++ struct m68k_bdm_reg_mapping* map; ++ int num_regs; ++ int sp_regnum; ++ int pc_regnum; ++ int sr_regnum; ++ int fp0_regnum; ++}; ++ ++/* ++ * The number of registers. ++ */ ++#define BDM_REG_NUM(_m) (sizeof (_m) / sizeof (struct m68k_bdm_reg_mapping)) ++ ++/* ++ * The number of registers. ++ */ ++#define NUM_REGS_BDM (bdm_reg_map[cpu_type].num_regs) ++ ++/* ++ * Get a BDM register. ++ */ ++#define BDM_REG_NAME(_r) (bdm_reg_map[cpu_type].map[_r].name) ++#define BDM_REG_TYPE(_r) (bdm_reg_map[cpu_type].map[_r].type) ++#define BDM_REG_CODE(_r) (bdm_reg_map[cpu_type].map[_r].code) ++ ++struct m68k_bdm_registers bdm_reg_map[] = { ++ { cpu32_reg_map, BDM_REG_NUM (cpu32_reg_map), 15, 17, 16, -1 }, ++ { cpu32plus_reg_map, BDM_REG_NUM (cpu32plus_reg_map), 15, 17, 16, -1 }, ++ { cf5200_reg_map, BDM_REG_NUM (cf5200_reg_map), 15, 17, 16, -1 }, ++ { cf5272_reg_map, BDM_REG_NUM (cf5272_reg_map), 15, 17, 16, -1 }, ++ { cf5282_reg_map, BDM_REG_NUM (cf5282_reg_map), 15, 17, 16, -1 }, ++ { cfv4e_reg_map, BDM_REG_NUM (cfv4e_reg_map), 15, 17, 16, 46 } ++}; ++ ++#define BDM_FREE_PROG_LOADED() \ ++do {xfree (bdm_prog_loaded); bdm_prog_loaded = NULL; } while (0) ++ ++/* ++ * The name of the most recently loaded program ++ */ ++static char *bdm_prog_loaded; ++ ++/* ++ * Do not load the program when creating the target if set to 1. ++ */ ++static int bdm_no_load; ++ ++/* ++ * Default delay for interface ++ */ ++#define BDM_DEFAULT_DELAY 0 ++static int bdm_delay = -1; ++ ++/* ++ * does gdb wait or not, only valid for a Coldfire processor ++ */ ++static int bdm_gdb_no_wait = 0; ++ ++/* ++ * Hold BDM ATEMP register (CPU32 only). ++ */ ++static unsigned long atemp; ++static int have_atemp; ++ ++/* ++ * Target hit a watchpoint. ++ */ ++static int hit_watchpoint; ++ ++/* ++ * CF BDM Debug hardware version number. ++ */ ++ ++static unsigned long cf_debug_ver; ++ ++/* ++ * Have we set a debug level. ++ */ ++static int bdm_debug_level; ++ ++/* ++ * give target time to come up after reset ++ * time in usec ++ */ ++#define TIME_TO_COME_UP 60000 ++ ++/* ++ * We are quitting, so do not call error and therefore ++ * jump back into the main event handler. ++ */ ++static int bdm_gdb_is_quitting; ++ ++static void bdm_close (int quitting); ++ ++/* ++ * The load processor. ++ */ ++static void bdm_load (char *filename, int from_tty); ++ ++/* ++ * Our pid. ++ */ ++ptid_t bdm_ptid; ++ ++/* ++ * The breakpoint codes for the different processors ++ */ ++static unsigned char cpu32_breakpoint[] = {0x4a, 0xfa}; ++static unsigned char cf_breakpoint[] = {0x4a, 0xc8}; ++static unsigned char* breakpointCode = (unsigned char*) "\x4e\x41"; ++static int breakpointSize = 2; ++ ++/* ++ * The number of registers. Use the biggest number. ++ */ ++int m68k_bdm_num_regs () ++{ ++ return bdm_reg_map[BDM_MARCH_CFV4E].num_regs; ++} ++ ++/* ++ * Return the register name. ++ */ ++static const char * ++m68k_bdm_register_name (int regnum) ++{ ++ if ((regnum < 0) || (regnum >= bdm_reg_map[cpu_type].num_regs)) ++ return NULL; ++ return bdm_reg_map[cpu_type].map[regnum].name; ++} ++ ++/* ++ * Return the register type. ++ */ ++static struct type * ++m68k_bdm_register_type (struct gdbarch *gdbarch, int regnum) ++{ ++ if ((regnum < 0) || (regnum >= bdm_reg_map[cpu_type].num_regs)) ++ return builtin_type_int32; ++ return *BDM_REG_TYPE (regnum); ++} ++ ++/* ++ * Return nonzero if a value of type TYPE stored in register REGNUM ++ * needs any special handling. ++ */ ++ ++static int ++m68k_convert_register_p (int regnum, struct type *type) ++{ ++ return (bdm_reg_map[cpu_type].fp0_regnum >= 0); ++} ++ ++/* ++ * Display error message and jump back to main input loop ++ */ ++static void ++bdm_report_error (void) ++{ ++ if (!bdm_gdb_is_quitting) ++ error ("BDM driver error: %s", bdmErrorString ()); ++} ++ ++/* ++ * Read a system or control registers. ++ */ ++static int ++bdm_read_sys_ctl_reg (const char* name, int cregno, unsigned long* l) ++{ ++ int ret; ++ if (bdm_debug_level) ++ printf_filtered ("bdm_read_sys_ctl_reg: %s (0x%03x)\n", ++ name, cregno & BDM_REG_CONTROL_REG_MASK); ++ if (cregno & BDM_REG_CONTROL_REG) ++ ret = bdmReadControlRegister (cregno & BDM_REG_CONTROL_REG_MASK, l); ++ else ++ ret = bdmReadSystemRegister (cregno, l); ++ return ret; ++} ++ ++/* ++ * Write a system or control registers. ++ */ ++static int ++bdm_write_sys_ctl_reg (const char* name, int cregno, unsigned long l) ++{ ++ int ret; ++ if (bdm_debug_level) ++ printf_filtered ("bdm_write_sys_ctl_reg: %s (0x%03x)\n", ++ name, cregno & BDM_REG_CONTROL_REG_MASK); ++ if (cregno & BDM_REG_CONTROL_REG) ++ ret = bdmWriteControlRegister (cregno & BDM_REG_CONTROL_REG_MASK, l); ++ else ++ ret = bdmWriteSystemRegister (cregno, l); ++ return ret; ++} ++ ++/* ++ * The following routines handle the Coldfire hardware breakpoints. Only one ++ * breakpoint supported so far, and it can be either a PC breakpoint or an ++ * address watchpoint. Unfortunately, the TARGET_CAN_USE_HARDWARE_WATCHPOINT ++ * macro only allows for bounds checking within one of the two types and not ++ * limits that cover the sum of both, so extra work is needed. ++ * ++ * (Actually, very few processors seem to have much support for that routine ++ * at all.) ++ * ++ * As a result, the way this is handled is that the can_use routine will allow ++ * the first breakpoint of either type to be added. Any further checking so ++ * that only one of the two can be used is done later when GDB actually tries ++ * to create the breakpoints, usually when the processor is restarted. ++ * ++ * We keep a local copy of the breakpoints list becasue the chain that GDB ++ * keeps isn't exported globally. ++ * ++ * While things could be simplified with only one breakpoint present, setting ++ * up more general routines allows for later expansion if newer versions of ++ * the ColdFire chip support more breakpoints at once. ++ * ++ * Also, the ColdFire supports things like multi-level triggers and triggers ++ * based on the data bus instead of just the address bus. The GDB commands ++ * don't allow for access to this, but much of it isn't necessary anyway, ++ * as GDB has its own method of handling 'breakpoint conditions' that is ++ * sufficient for most tasks. ++ */ ++ ++#define TDR_TRC_DDATA 0x00000000 ++#define TDR_TRC_HALT 0x40000000 ++#define TDR_TRC_DINT 0x80000000 ++#define TDR_L2_EBL 0x20000000 ++#define TDR_L2_ALL 0x1FFF0000 ++#define TDR_L2_EDLW 0x10000000 ++#define TDR_L2_EDWL 0x08000000 ++#define TDR_L2_EDWU 0x04000000 ++#define TDR_L2_EDLL 0x02000000 ++#define TDR_L2_EDLM 0x01000000 ++#define TDR_L2_EDUM 0x00800000 ++#define TDR_L2_EDUU 0x00400000 ++#define TDR_L2_DI 0x00200000 ++#define TDR_L2_EAI 0x00100000 ++#define TDR_L2_EAR 0x00080000 ++#define TDR_L2_EAL 0x00040000 ++#define TDR_L2_EPC 0x00020000 ++#define TDR_L2_PCI 0x00010000 ++#define TDR_L1_EBL 0x00002000 ++#define TDR_L1_ALL 0x00001FFF ++#define TDR_L1_EDLW 0x00001000 ++#define TDR_L1_EDWL 0x00000800 ++#define TDR_L1_EDWU 0x00000400 ++#define TDR_L1_EDLL 0x00000200 ++#define TDR_L1_EDLM 0x00000100 ++#define TDR_L1_EDUM 0x00000080 ++#define TDR_L1_EDUU 0x00000040 ++#define TDR_L1_DI 0x00000020 ++#define TDR_L1_EAI 0x00000010 ++#define TDR_L1_EAR 0x00000008 ++#define TDR_L1_EAL 0x00000004 ++#define TDR_L1_EPC 0x00000002 ++#define TDR_L1_PCI 0x00000001 ++ ++struct cf_break { ++ enum target_hw_bp_type type; ++ CORE_ADDR addr; ++ int len; ++}; ++ ++#define CF_BREAKPOINT_MAX 1 ++ ++static struct cf_break cf_breakpoints[CF_BREAKPOINT_MAX]; ++static int cf_breakpoint_count; ++ ++static int ++cf_init_watchpoints(void) ++{ ++ if (cpu_family != BDM_COLDFIRE) { ++ return(-1); ++ } ++ cf_breakpoint_count = 0; ++ if (bdmWriteSystemRegister (BDM_REG_TDR, TDR_TRC_HALT) < 0) ++ bdm_report_error (); ++ return(0); ++} ++ ++int ++cf_stopped_by_watchpoint(void) ++{ ++ return hit_watchpoint; ++} ++ ++int ++cf_can_use_watchpoint(enum target_hw_bp_type type, int cnt, int ot) ++{ ++ unsigned long tdr; ++ ++ if (cpu_family != BDM_COLDFIRE) { ++ return(0); ++ } ++ ++ if (type == bp_hardware_breakpoint || type == bp_read_watchpoint || ++ type == bp_hardware_watchpoint || type == bp_access_watchpoint) { ++ if (cnt <= 1) { ++ return(1); ++ } ++ } ++ ++ return(-1); ++} ++ ++int ++cf_insert_hw_breakpoint(CORE_ADDR addr, char *shadow) ++{ ++ unsigned long tdr; ++ ++ if (cpu_family != BDM_COLDFIRE) { ++ return(-1); ++ } ++ ++ if (cf_breakpoint_count < CF_BREAKPOINT_MAX) { ++ cf_breakpoints[cf_breakpoint_count].type = hw_execute; ++ cf_breakpoints[cf_breakpoint_count].addr = addr; ++ cf_breakpoints[cf_breakpoint_count++].len = 2; ++ ++ if (bdmReadSystemRegister (BDM_REG_TDR, &tdr) < 0) ++ bdm_report_error (); ++ tdr = ((tdr & ~TDR_L1_ALL) | (TDR_L1_EBL|TDR_L1_EPC)); ++ if (bdmWriteSystemRegister (BDM_REG_PBR, addr) < 0) ++ bdm_report_error (); ++ if (bdmWriteSystemRegister (BDM_REG_PBMR, 0) < 0) ++ bdm_report_error (); ++ if (bdmWriteSystemRegister (BDM_REG_TDR, tdr) < 0) ++ bdm_report_error (); ++ if (bdm_debug_level) ++ printf_filtered ("Insert PC Breakpoint @0x%08lx\n", addr); ++ } ++ else { ++ return(-1); ++ } ++ return(0); ++} ++ ++static int ++cf_check_breakpoint(type, addr, len) ++ enum target_hw_bp_type type; ++ CORE_ADDR addr; ++ int len; ++{ ++ int i; ++ ++ for (i = 0; i < cf_breakpoint_count; i++) { ++ if (cf_breakpoints[i].type == type && ++ cf_breakpoints[i].addr == addr && ++ cf_breakpoints[i].len == len) { ++ for (; i < CF_BREAKPOINT_MAX-1; i++) { ++ cf_breakpoints[i] = cf_breakpoints[i+1]; ++ } ++ cf_breakpoint_count--; ++ return(1); ++ } ++ } ++ return(0); ++} ++ ++int ++cf_remove_hw_breakpoint(CORE_ADDR addr, char *shadow) ++{ ++ unsigned long tdr; ++ unsigned long csr; ++ ++ if (cpu_family != BDM_COLDFIRE) { ++ return(-1); ++ } ++ ++ if (cf_check_breakpoint(hw_execute, addr, 2)) { ++ if (bdmReadSystemRegister (BDM_REG_TDR, &tdr) < 0) ++ bdm_report_error (); ++ tdr &= ~TDR_L1_EPC; ++ if ((tdr & TDR_L1_ALL) == 0) { ++ tdr &= ~TDR_L1_EBL; ++ } ++ if (bdmWriteSystemRegister (BDM_REG_TDR, tdr) < 0) ++ bdm_report_error (); ++ if (bdm_debug_level) ++ printf_filtered ("Remove PC Breakpoint @0x%08lx\n", addr); ++ } ++ else { ++ return(-1); ++ } ++ return(0); ++} ++ ++#define AATR_READONLY 0x7F85 ++#define AATR_WRITEONLY 0x7F05 ++#define AATR_READWRITE 0xFF05 ++ ++int ++cf_insert_watchpoint(CORE_ADDR addr, int len, enum target_hw_bp_type type) ++{ ++ unsigned long tdr; ++ ++ if (cpu_family != BDM_COLDFIRE) { ++ return(-1); ++ } ++ ++ if (cf_breakpoint_count < CF_BREAKPOINT_MAX) { ++ cf_breakpoints[cf_breakpoint_count].type = type; ++ cf_breakpoints[cf_breakpoint_count].addr = addr; ++ cf_breakpoints[cf_breakpoint_count++].len = len; ++ ++ if (bdmReadSystemRegister (BDM_REG_TDR, &tdr) < 0) ++ bdm_report_error (); ++ tdr = ((tdr & ~TDR_L1_ALL) | (TDR_L1_EBL|TDR_L1_EAR)); ++ if (bdmWriteSystemRegister (BDM_REG_ABLR, addr) < 0) ++ bdm_report_error (); ++ if (bdmWriteSystemRegister (BDM_REG_ABHR, addr+len-1) < 0) ++ bdm_report_error (); ++ if (type == hw_read) { ++ if (bdmWriteSystemRegister (BDM_REG_AATR, AATR_READONLY) < 0) ++ bdm_report_error (); ++ if (bdm_debug_level) ++ printf_filtered ("Insert read Watchpoint @0x%08lx-0x%08lx\n", ++ addr, addr+len-1); ++ } ++ else if (type == hw_write) { ++ if (bdmWriteSystemRegister (BDM_REG_AATR, AATR_WRITEONLY) < 0) ++ bdm_report_error (); ++ if (bdm_debug_level) ++ printf_filtered ("Insert write Watchpoint @0x%08lx-0x%08lx\n", ++ (long unsigned int)addr, addr+len-1); ++ } ++ else { ++ if (bdmWriteSystemRegister (BDM_REG_AATR, AATR_READWRITE) < 0) ++ bdm_report_error (); ++ if (bdm_debug_level) ++ printf_filtered ("Insert access Watchpoint @0x%08lx-0x%08lx\n", ++ addr, addr+len-1); ++ } ++ if (bdmWriteSystemRegister (BDM_REG_TDR, tdr) < 0) ++ bdm_report_error (); ++ } ++ else { ++ return(-1); ++ } ++ return(0); ++} ++ ++int ++cf_remove_watchpoint(CORE_ADDR addr, int len, enum target_hw_bp_type type) ++{ ++ unsigned long tdr; ++ unsigned long csr; ++ ++ if (cpu_family != BDM_COLDFIRE) { ++ return(-1); ++ } ++ ++ if (cf_check_breakpoint(type, addr, len)) { ++ if (bdmReadSystemRegister (BDM_REG_TDR, &tdr) < 0) ++ bdm_report_error (); ++ tdr &= ~TDR_L1_EAR; ++ if ((tdr & TDR_L1_ALL) == 0) { ++ tdr &= ~TDR_L1_EBL; ++ } ++ if (bdmWriteSystemRegister (BDM_REG_TDR, tdr) < 0) ++ bdm_report_error (); ++ if (bdm_debug_level) ++ printf_filtered ("Remove %s Watchpoint @0x%08lx-0x%08lx\n", ++ (type == hw_read) ? "read" : ++ ((type == hw_write) ? "write" : "access"), ++ addr, addr+len-1); ++ } ++ else { ++ return(-1); ++ } ++ return(0); ++} ++ ++int ++cf_stopped_data_address(struct target_ops *target, CORE_ADDR *addr) ++{ ++ unsigned long tdr; ++ unsigned long ablr; ++ ++ if (cpu_family != BDM_COLDFIRE) { ++ return(-1); ++ } ++ ++ if (bdmReadSystemRegister (BDM_REG_TDR, &tdr) < 0) ++ bdm_report_error (); ++ if (bdmReadSystemRegister (BDM_REG_ABLR, &ablr) < 0) ++ bdm_report_error (); ++ ++ if (tdr & TDR_L1_EAR) { ++ *addr = ablr; ++ return 1; ++ } ++ return(0); ++} ++ ++#ifdef SYSCALL_TRAP ++/* Immediately after a function call, return the saved pc before the frame ++ is setup. For uCLinux which uses a TRAP #0 for a system call we need to ++ read the first long word of the stack to see if the stack frame format is ++ type 4 and the vector is 32 (0x4080), and the opcode at the PC is ++ "move.w #0x2700,sr". If it is then get the second long from the stack. */ ++ ++CORE_ADDR ++m68k_bdm_saved_pc_after_call (struct frame_info *frame) ++{ ++ unsigned int op; ++ unsigned int eframe; ++ int sp; ++ ++ if(!IS_BDM) ++ return gdbarch_saved_pc_after_call (current_gdbarch, frame); ++ ++ sp = read_register (SP_REGNUM); ++ eframe = read_memory_integer (sp, 2); ++ op = read_memory_integer (frame->pc, 4); ++ ++ /* ++ * This test could break if some changes the syste call. ++ */ ++ ++ if (eframe == 0x4080 && op == 0x46fc2700) ++ return read_memory_integer (sp + 4, 4); ++ else ++ return read_memory_integer (sp, 4); ++} ++#endif /* SYSCALL_TRAP */ ++ ++int ++m68k_bdm_decr_pc_after_break() ++{ ++ return IS_BDM ? 0 : gdbarch_decr_pc_after_break(current_gdbarch); ++} ++ ++extern int ++m68k_bdm_have_nonsteppable_watchpoint() ++{ ++ return IS_BDM ? 1 : gdbarch_have_nonsteppable_watchpoint(current_gdbarch); ++} ++ ++const unsigned char * ++m68k_bdm_breakpoint_from_pc (CORE_ADDR *pcptr, int *lenptr) ++{ ++ if(IS_BDM) ++ { ++ *lenptr = breakpointSize; ++ return breakpointCode; ++ } ++ else ++ return gdbarch_breakpoint_from_pc(current_gdbarch, pcptr, lenptr); ++} ++ ++/* ++ * Short pause ++ */ ++static void ++nap (int microseconds) ++{ ++#if defined (__MINGW32__) ++ Sleep (microseconds / 1000); ++#else ++ struct timeval tv; ++ ++ tv.tv_sec = microseconds / 1000000; ++ tv.tv_usec = microseconds % 1000000; ++ select (0, NULL, NULL, NULL, &tv); ++#endif ++} ++ ++/* ++ * Return interface status ++ */ ++static int ++bdm_get_status (void) ++{ ++ int status; ++ ++ if ((status = bdmStatus ()) < 0) ++ bdm_report_error (); ++ return status; ++} ++ ++static void ++bdm_get_status_interactive (int pid, char *arg) ++{ ++ printf_filtered ("BDM status: 0x%x\n", bdm_get_status ()); ++} ++ ++/* ++ * release chip: reset and disable bdm mode ++ */ ++static void ++bdm_release_chip (void) ++{ ++ have_atemp = 0; ++ registers_changed (); ++ inferior_ptid = bdm_ptid = null_ptid; ++ if (bdmRelease () < 0) ++ bdm_report_error (); ++} ++ ++/* ++ * stop chip ++ */ ++static void ++bdm_stop_chip (void) ++{ ++ if (bdm_debug_level) ++ printf_filtered ("bdm stop chip called\n"); ++ if (bdmStop () < 0) ++ bdm_report_error (); ++} ++ ++/* ++ * Allow chip to resume execution ++ */ ++static void ++bdm_go (void) ++{ ++ have_atemp = 0; ++ if (bdmGo () < 0) ++ bdm_report_error (); ++} ++ ++/* ++ * Reset chip, enter BDM mode ++ */ ++static void ++bdm_reset (void) ++{ ++ have_atemp = 0; ++ registers_changed (); ++ inferior_ptid = bdm_ptid = null_ptid; ++ if (bdmReset () < 0) ++ bdm_report_error (); ++ nap (TIME_TO_COME_UP); ++} ++ ++/* ++ * step cpu32 chip: execute a single instruction ++ * This is complicated by the presence of interrupts. ++ * Consider the following sequence of events: ++ * - User attempts to `continue' from a breakpoint. ++ * - Gdb calls bdm_step_chip to single-step the instruction that ++ * had been replaced by the BGND instruction. ++ * - The target processor executes the instruction and stops. ++ * - GDB replaces the instruction with a BGND instruction to ++ * force a breakpoint the next time the instruction is hit. ++ * - GDB calls bdm_go and the target resumes execution. ++ * This all seems fine, but now consider what happens when a interrupt ++ * is pending: ++ * - User attempts to `continue' from a breakpoint. ++ * - Gdb calls bdm_step_chip to single-step the instruction that ++ * had been replaced by the BGND instruction. ++ * - The target processor does not execute the replaced instruction, ++ * but rather executes the first instruction of the interrupt ++ * service routine, then stops. ++ * - GDB replaces the instruction with a BGND instruction to ++ * force a breakpoint the next time the instruction is hit. ++ * - GDB calls bdm_go and the target resumes execution. ++ * - The target finishes off the interrupt, and upon returing from ++ * the interrupt generates another breakpoint! ++ * The solution is simple -- disable interrupts when single stepping. ++ * The problem then becomes the handling of instructions which involve ++ * the program status word! ++ */ ++static void ++bdm_step_cpu32_chip (void) ++{ ++ unsigned long pc; ++ unsigned short instruction; ++ unsigned short immediate; ++ unsigned long d7; ++ unsigned long sr; ++ unsigned long nsr; ++ enum { ++ op_other, ++ op_ANDIsr, ++ op_EORIsr, ++ op_ORIsr, ++ op_TOsr, ++ op_FROMsr, ++ op_FROMsrTOd7 ++ } op; ++ ++ /* ++ * Get the existing status register ++ */ ++ if (bdmReadSystemRegister (BDM_REG_SR, &sr) < 0) ++ bdm_report_error (); ++ ++ /* ++ * Read the instuction about to be executed ++ */ ++ if ((bdmReadSystemRegister (BDM_REG_RPC, &pc) < 0) ++ || (bdmReadWord (pc, &instruction) < 0)) ++ bdm_report_error (); ++ ++ /* ++ * See what operation is to be performed ++ */ ++ if (instruction == 0x027C) ++ op = op_ANDIsr; ++ else if (instruction == 0x0A7C) ++ op = op_EORIsr; ++ else if (instruction == 0x007C) ++ op = op_ORIsr; ++ else if (instruction == 0x40C7) ++ op = op_FROMsrTOd7; ++ else if ((instruction & 0xFFC0) == 0x40C0) ++ op = op_FROMsr; ++ else if ((instruction & 0xFFC0) == 0x46C0) ++ op = op_TOsr; ++ else ++ op = op_other; ++ ++ /* ++ * Set things up for the single-step operation ++ */ ++ switch (op) { ++ case op_FROMsr: ++ /* ++ * It's storing the SR somewhere. ++ * Store the SR in D7 and change the instruction ++ * to save D7. This fails if the addressing mode ++ * is one of the esoteric modes that uses D7 as ++ * and index register, but we'll just have to hope ++ * that doesn't happen too often. ++ */ ++ if ((bdmReadRegister (7, &d7) < 0) ++ || (bdmWriteRegister (7, sr) < 0) ++ || (bdmWriteWord (pc, 0x3007 | ++ ((instruction & 0x38) << 3) | ++ ((instruction & 0x07) << 9)) < 0)) ++ bdm_report_error (); ++ break; ++ ++ case op_ANDIsr: ++ case op_EORIsr: ++ case op_ORIsr: ++ /* ++ * It's an immediate operation to the SR -- pick up the value ++ */ ++ if (bdmReadWord (pc+2, &immediate) < 0) ++ bdm_report_error (); ++ break; ++ ++ case op_TOsr: ++ case op_other: ++ break; ++ } ++ ++ /* ++ * Ensure the step is done with interrupts disabled ++ */ ++ if (bdmWriteSystemRegister (BDM_REG_SR, sr | 0x0700) < 0) ++ bdm_report_error (); ++ ++ /* ++ * Do the single-step ++ */ ++ if (bdmStep () < 0) ++ bdm_report_error (); ++ ++ /* ++ * Get the ATEMP register since the following operations may ++ * modify it. ++ */ ++ if (bdmReadSystemRegister (BDM_REG_ATEMP, &atemp) < 0) ++ bdm_report_error (); ++ have_atemp = 1; ++ ++ /* ++ * Clean things up ++ */ ++ switch (op) { ++ case op_FROMsr: ++ if ((bdmWriteRegister (7, d7) < 0) ++ || (bdmWriteWord (pc, instruction) < 0) ++ || (bdmWriteSystemRegister (BDM_REG_SR, sr) < 0)) ++ bdm_report_error (); ++ break; ++ ++ case op_FROMsrTOd7: ++ if ((bdmReadRegister (7, &d7) < 0) ++ || (bdmWriteRegister (7, (d7 & ~0xFFFF) | (sr & 0xFFFF)) < 0) ++ || (bdmWriteSystemRegister (BDM_REG_SR, sr) < 0)) ++ bdm_report_error (); ++ break; ++ ++ case op_ANDIsr: ++ if (bdmWriteSystemRegister (BDM_REG_SR, sr & immediate) < 0) ++ bdm_report_error (); ++ break; ++ ++ case op_EORIsr: ++ if (bdmWriteSystemRegister (BDM_REG_SR, sr ^ immediate) < 0) ++ bdm_report_error (); ++ break; ++ ++ case op_ORIsr: ++ if (bdmWriteSystemRegister (BDM_REG_SR, sr | immediate) < 0) ++ bdm_report_error (); ++ break; ++ ++ case op_TOsr: ++ break; ++ ++ case op_other: ++ if ((bdmReadSystemRegister (BDM_REG_SR, &nsr) < 0) ++ || (bdmWriteSystemRegister (BDM_REG_SR, (nsr & ~0x0700) | (sr & 0x0700)) < 0)) ++ bdm_report_error (); ++ break; ++ } ++} ++ ++static void ++bdm_step_chip (void) ++{ ++ /* ++ * The cpu32 is harder to step than the Coldfire. ++ */ ++ if (cpu_family == BDM_CPU32) { ++ bdm_step_cpu32_chip(); ++ return; ++ } ++ ++ /* ++ * Do the single-step ++ */ ++ if (bdmStep () < 0) ++ bdm_report_error (); ++} ++ ++/* ++ * true if runnable ++ */ ++static int ++bdm_can_run (void) ++{ ++ if (bdm_debug_level) ++ printf_filtered ("bdm can run called\n"); ++ return 1; ++} ++ ++static void ++bdm_setdelay(int delay) ++{ ++ if (bdmSetDelay (delay) < 0) ++ bdm_report_error (); ++} ++ ++static void ++bdm_setdelay_interactive (char *arg, int from_tty) ++{ ++ char *dummy; ++ ++ if (!arg) { ++ if (bdm_delay >= 0) ++ printf_filtered("bdm_delay is %d", bdm_delay); ++ else ++ printf_filtered("using default delay %d", BDM_DEFAULT_DELAY); ++ } ++ else { ++ bdm_delay = strtoul(arg, &dummy, 0); ++ bdm_setdelay (bdm_delay); ++ } ++} ++ ++static void ++bdm_setdebug_interactive (char *arg, int from_tty) ++{ ++ char *dummy; ++ if (arg) { ++ bdm_debug_level = strtoul(arg, &dummy, 0); ++ bdmSetDebugFlag (bdm_debug_level); ++ } ++ else ++ error ("Argument missing"); ++} ++ ++static void ++bdm_setdriverdebug_interactive (char *arg, int from_tty) ++{ ++ char *dummy; ++ if (arg) ++ bdmSetDriverDebugFlag (strtoul(arg, &dummy, 0)); ++ else ++ error ("Argument missing"); ++} ++ ++static void ++bdm_set_no_wait (char *arg, int from_tty) ++{ ++ bdm_gdb_no_wait = 1; ++} ++ ++static void ++bdm_set_wait (char *arg, int from_tty) ++{ ++ if (cpu_family == BDM_CPU32) { ++ error ("No wait mode is not supported on a CPU32"); ++ return; ++ } ++ if (bdm_get_status ()) ++ bdm_gdb_no_wait = 0; ++ else ++ error ("The target is running, please stop first"); ++} ++ ++static void ++bdm_issue_stop (char *arg, int from_tty) ++{ ++ bdm_stop_chip (); ++} ++ ++/* ++ * Open a connection the target via bdm ++ * name is the devicename of bdm and the filename to be used ++ * used for communication. ++ */ ++static void ++bdm_open (char *name, int from_tty) ++{ ++ char *p; ++ unsigned int version; ++ unsigned long csr; ++ struct gdbarch_info info; ++ struct gdbarch *arch; ++ ++ if (bdm_debug_level) ++ printf_filtered ("bdm open called\n"); ++ ++ if (bdmIsOpen ()) ++ bdm_close (0); ++ if (name == NULL) ++ error ("Use `target bdm ' to use the bdm target"); ++ ++ bdm_ptid = null_ptid; ++ ++ /* ++ * 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 the bdm port device."); ++ dev_name = savestring (name, p - name); ++ ++ target_preopen (from_tty); ++ unpush_target (&bdm_ops); ++ ++ if (bdmOpen (dev_name) < 0) ++ bdm_report_error (); ++ if (bdmStatus () & (BDM_TARGETPOWER | BDM_TARGETNC)) { ++ bdmClose (); ++ error ("Target or cable problem"); ++ } ++ ++ /* ++ * Ask the driver for it's version. ++ * We are only interested in the major number when checking the ++ * driver version number. ++ */ ++ if (bdmGetDrvVersion (&version) < 0) ++ bdm_report_error (); ++ if ((version & 0xff00) != (BDM_DRV_VERSION & 0xff00)) { ++ printf_filtered ("Incorrect driver version, looking for %i.%i"\ ++ " and found %i.%i\n", ++ BDM_DRV_VERSION >> 8, BDM_DRV_VERSION & 0xff, ++ version >> 8, version & 0xff); ++ bdmClose (); ++ error ("Can't run with incorrect BDM driver version"); ++ } ++ ++ /* ++ * Get the processor type. ++ */ ++ if (bdmGetProcessor (&cpu_family) < 0) ++ bdm_report_error (); ++ ++ switch (cpu_family) { ++ case BDM_CPU32: ++ breakpointCode = cpu32_breakpoint; ++ breakpointSize = sizeof cpu32_breakpoint; ++ cpu_type = BDM_MARCH_CPU32; ++ break; ++ ++ case BDM_COLDFIRE: ++ breakpointCode = cf_breakpoint; ++ breakpointSize = sizeof cf_breakpoint; ++ ++ cf_init_watchpoints(); ++ ++ /* ++ * Read the CSR register to determine the debug module ++ * version. ++ */ ++ if (bdmReadSystemRegister (BDM_REG_CSR, &csr) < 0) ++ bdm_report_error (); ++ cf_debug_ver = (csr >> 20) & 0x0f; ++ ++ /* ++ * If the processor is a version 0 read the PC and VBR ++ * an if they can be read read the mbar. If that fails ++ * we have a 5282. ++ */ ++ if (cf_debug_ver == 0) { ++ unsigned long junk; ++ cpu_type = BDM_MARCH_CF5200; ++ if ((bdmReadSystemRegister (BDM_REG_RPC, &junk) == 0) && ++ (bdmReadSystemRegister (BDM_REG_VBR, &junk) == 0)) { ++ if (bdmReadSystemRegister (BDM_REG_MBAR, &junk) < 0) { ++ cpu_type = BDM_MARCH_CF5282; ++ printf_filtered ("Detected MCF5282\n"); ++ } ++ else { ++ cpu_type = BDM_MARCH_CF5252; ++ printf_filtered ("Detected V2 core\n"); ++ } ++ } ++ } else if (cf_debug_ver == 3) { ++ cpu_type = BDM_MARCH_CFV4E; ++ printf_filtered ("Detected V4e core\n"); ++ } ++ break; ++ ++ default: ++ bdmClose (); ++ error ("Unknown processor type returned from the driver."); ++ } ++ ++ push_target (&bdm_ops); ++ ++ if (bdm_delay >= 0) ++ bdm_setdelay (bdm_delay); ++ else ++ bdm_setdelay (BDM_DEFAULT_DELAY); ++ if (from_tty) ++ printf_filtered ("GDB target %s connected to %s\n", ++ target_shortname, dev_name); ++ if (cpu_family == BDM_COLDFIRE) ++ { ++ char* cf_type = "5206(e)/5272/5282"; ++ if (cf_debug_ver == 1) ++ cf_type = "5307/5407(e)"; ++ else ++ cf_type = "V4e (547x/548x)"; ++ printf_filtered (" Coldfire debug module version is %ld (%s)\n", ++ cf_debug_ver, cf_type); ++ } ++ ++ /* ++ * Register the arch handlers for the processor we detected. ++ */ ++ ++ set_gdbarch_num_regs (current_gdbarch, bdm_reg_map[cpu_type].num_regs); ++ set_gdbarch_sp_regnum (current_gdbarch, bdm_reg_map[cpu_type].sp_regnum); ++ set_gdbarch_pc_regnum (current_gdbarch, bdm_reg_map[cpu_type].pc_regnum); ++ if (bdm_reg_map[cpu_type].fp0_regnum >= 0) ++ set_gdbarch_ps_regnum (current_gdbarch, bdm_reg_map[cpu_type].fp0_regnum); ++ set_gdbarch_register_type (current_gdbarch, m68k_bdm_register_type); ++ set_gdbarch_register_name (current_gdbarch, m68k_bdm_register_name); ++} ++ ++/* ++ * Terminate current application and return to system prompt. ++ * On a target, just let the program keep on running ++ */ ++static void ++bdm_kill (void) ++{ ++ if (bdm_debug_level) ++ printf_filtered ("bdm kill called\n"); ++#ifdef BDM_GDB_RELEASE_CPU_ON_EXIT ++ if (bdm_get_status () & BDM_TARGETSTOPPED) ++ bdm_go (); ++#else ++ bdm_stop_chip (); ++ bdm_reset (); ++#endif ++ BDM_FREE_PROG_LOADED (); ++} ++ ++static void ++bdm_close (int quitting) ++{ ++ if (bdm_debug_level) ++ printf_filtered ("bdm close called\n"); ++ bdm_gdb_is_quitting = quitting; ++ have_atemp = 0; ++ if (quitting) ++ bdm_kill (); ++ bdmClose (); ++ BDM_FREE_PROG_LOADED (); ++ inferior_ptid = bdm_ptid = null_ptid; ++} ++ ++static void ++bdm_attach (char *args, int from_tty) ++{ ++ if (bdm_debug_level) ++ printf_filtered ("bdm attach called\n"); ++ bdm_open (args, from_tty); ++ if (!use_windows) ++ bdm_ptid = pid_to_ptid (42000); ++} ++ ++/* ++ * _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) ++{ ++ if (bdm_debug_level) ++ printf_filtered ("bdm detach called\n"); ++ BDM_FREE_PROG_LOADED (); ++ inferior_ptid = bdm_ptid = null_ptid; ++ pop_target (); /* calls bdm_close to do the real work */ ++} ++ ++/* ++ * _resume -- Tell the remote machine to resume. ++ */ ++static void ++bdm_resume (ptid_t pid, int step, enum target_signal sig) ++{ ++ if (bdm_debug_level) ++ printf_filtered ("bdm resume called\n"); ++ if (step) ++ bdm_step_chip (); ++ else ++ bdm_go (); ++ if (use_windows) ++ bdm_ptid = pid_to_ptid (42000); ++} ++ ++/* ++ * We have fallen into an exception supported by the runtime system. ++ * by executing a `breakpoint' instruction. ++ */ ++static void ++analyze_exception (struct target_waitstatus *status) ++{ ++ unsigned long pc, sp; ++ unsigned short vec; ++ unsigned char opcode[20]; /* `big enough' */ ++ ++ if (cpu_family == BDM_CPU32) { ++ if (bdmReadSystemRegister (BDM_REG_PCC, &pc) < 0) ++ bdm_report_error (); ++ } ++ else { ++ if (bdmReadSystemRegister (BDM_REG_RPC, &pc) < 0) ++ bdm_report_error (); ++ if (pc) ++ pc -= 2; ++ } ++ status->kind = TARGET_WAITKIND_STOPPED; ++ ++ /* ++ * See if it was a `breakpoint' instruction ++ */ ++ if (bdmReadMemory (pc, opcode, breakpointSize) < 0) ++ bdm_report_error (); ++ if (memcmp (breakpointCode, opcode, breakpointSize) == 0) { ++ if (bdmWriteSystemRegister (BDM_REG_RPC, pc) < 0) ++ bdm_report_error (); ++ status->value.sig = TARGET_SIGNAL_TRAP; ++ return; ++ } ++ /* ++ * FIXME: Why an illegal instruction signal ? ++ */ ++ status->value.sig = TARGET_SIGNAL_ILL; ++} ++ ++static int sigintFlag; ++static void ++bdm_signal_handler (int s) ++{ ++ sigintFlag++; ++} ++ ++/* ++ * 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) ++{ ++ unsigned long csr; ++ int bdm_stat; ++ int detach = 0; ++ int ui_count = 0; ++ void (*ofunc) (); ++ ++ hit_watchpoint = 0; ++ if (bdm_gdb_no_wait) { ++ status->kind = TARGET_WAITKIND_STOPPED; ++ status->value.sig = TARGET_SIGNAL_GRANT; ++ return bdm_ptid; ++ } ++ ++ status->kind = TARGET_WAITKIND_EXITED; ++ status->value.integer = 0; ++ ++ /* ++ * Catch SIGINT signals ++ */ ++ sigintFlag = 0; ++ ofunc = signal (SIGINT, bdm_signal_handler); ++ ++ /* ++ * A work around a problem with the 5206e processor. Not sure ++ * what the issue is. It could be the processor. ++ */ ++ if (cpu_family == BDM_COLDFIRE && cf_debug_ver == 0) ++ nap (10000); ++ ++ /* ++ * Wait here till the target requires service ++ */ ++ while ((bdm_stat = bdm_get_status ()) == 0) { ++ ui_count = 0; ++ while (ui_count++ < 6) { ++ nap (50000); ++ ++ /* N.B. The UI may destroy our world (for instance by calling ++ remote_stop,) in which case we want to get out of here as ++ quickly as possible. It is not safe to touch scb, since ++ someone else might have freed it. The deprecated_ui_loop_hook signals that ++ we should exit by returning 1. */ ++ ++ if (deprecated_ui_loop_hook) ++ detach = deprecated_ui_loop_hook (0); ++ ++ if (detach || sigintFlag) ++ bdm_stop_chip (); ++ } ++ } ++ ++ signal (SIGINT, ofunc); ++ ++ /* ++ * Determine why the target stopped ++ */ ++ 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: ++ case BDM_TARGETHALT: ++ case BDM_TARGETSTOPPED | BDM_TARGETHALT: ++ if (sigintFlag) { ++ status->kind = TARGET_WAITKIND_STOPPED; ++ status->value.sig = TARGET_SIGNAL_TSTP; ++ } ++ else { ++ if (cpu_family == BDM_CPU32) { ++ if (!have_atemp ++ && (bdmReadSystemRegister (BDM_REG_ATEMP, &atemp) < 0)) ++ bdm_report_error (); ++ switch (atemp & 0xffff) { ++ case 0xffff: /* double bus fault */ ++ status->kind = TARGET_WAITKIND_STOPPED; ++ status->value.sig = TARGET_SIGNAL_BUS; ++ break; ++ case 0x0: /* HW bkpt */ ++ status->kind = TARGET_WAITKIND_STOPPED; ++ status->value.sig = TARGET_SIGNAL_TRAP; ++ break; ++ case 0x1: /* background mode */ ++ analyze_exception (status); ++ break; ++ default: ++ printf_filtered ("bdm_wait: Unknown atemp:%#lx\n", atemp); ++ status->kind = TARGET_WAITKIND_STOPPED; ++ status->value.sig = TARGET_SIGNAL_GRANT; ++ } ++ } ++ else { ++ if (bdmReadSystemRegister (BDM_REG_CSR, &csr) < 0) ++ bdm_report_error (); ++ if (csr & 0x08000000) { /* double bus fault */ ++ status->kind = TARGET_WAITKIND_STOPPED; ++ status->value.sig = TARGET_SIGNAL_BUS; ++ } ++ else { ++ if (csr & 0x04000000) { /* hardware trigger */ ++ hit_watchpoint = 1; ++ status->kind = TARGET_WAITKIND_STOPPED; ++ status->value.sig = TARGET_SIGNAL_TRAP; ++ } ++ else { ++ if (csr & 0x01000000) { /* -BKPT signal */ ++ status->kind = TARGET_WAITKIND_STOPPED; ++ status->value.sig = TARGET_SIGNAL_TRAP; ++ } ++ else { ++ if (csr & 0x02000000) { /* HALT/software bkpt */ ++ analyze_exception (status); ++ } ++ else { ++ printf_filtered ("bdm_wait: Unknown csr:%#lx", ++ csr); ++ status->kind = TARGET_WAITKIND_STOPPED; ++ status->value.sig = TARGET_SIGNAL_GRANT; ++ } ++ } ++ } ++ } ++ } ++ } ++ break; ++ default: ++ printf_filtered ("bdm_wait: Unknown BDM status: %#x", bdm_stat); ++ break; ++ } ++ have_atemp = 0; ++ return bdm_ptid; ++} ++ ++/* This is called not only when we first attach, but also when the ++ user types "run" after having attached. */ ++static void ++bdm_create_inferior (char *execfile, char *args, char **env, int from_tty) ++{ ++ CORE_ADDR addr = -1;; ++ ++ if (bdm_debug_level) ++ printf_filtered ("bdm create inferior called\n"); ++ ++ if (!bdmIsOpen ()) ++ error ("Not attached to the target. Use `target bdm ' command to attach.\n"); ++ ++ /* ++ * If we do not load an executable, reset and step the processor to get a ++ * valid PC. ++ */ ++ ++ if (bdm_no_load) ++ { ++ bdm_reset (); ++ bdm_step_chip (); ++ } ++ else ++ { ++ bdm_load (execfile, 0); ++ addr = bfd_get_start_address (exec_bfd); ++ } ++ ++ inferior_ptid = pid_to_ptid (42000); ++ ++ /* Clean up from the last time we were running. */ ++ clear_proceed_status (); ++ ++ /* Let the remote process run. The -1 will continue. */ ++ proceed (addr, TARGET_SIGNAL_DEFAULT, 0); ++} ++ ++static void ++bdm_mourn_inferior (void) ++{ ++ if (bdm_debug_level) ++ printf_filtered ("bdm mourn inferior called\n"); ++ unpush_target (&bdm_ops); ++ generic_mourn_inferior (); ++} ++ ++/* ++ * Load a file. ++ */ ++static void ++bdm_load (char *filename, int from_tty) ++{ ++ if (bdm_debug_level) ++ printf_filtered ("bdm load called\n"); ++ if ((bdm_get_status () & BDM_TARGETSTOPPED) == 0) ++ bdm_stop_chip (); ++ inferior_ptid = bdm_ptid = null_ptid; ++ init_wait_for_inferior (); ++ generic_load (filename, from_tty); ++ bdm_prog_loaded = savestring (filename, strlen (filename)); ++ ++} ++ ++/* ++ * Fetch register REGNO, or all user registers if REGNO is -1. ++ */ ++static void ++bdm_fetch_register (int regno) ++{ ++ unsigned long lu = 0; ++ unsigned long ll = 0; ++ char cbuf[8]; ++ int ret; ++ ++ if (regno < 0) { ++ for (regno = 0 ; regno < NUM_REGS_BDM ; regno++) ++ bdm_fetch_register (regno); ++ } ++ else { ++ /* ++ * When the target is running the ++ * cpu registers can not be accessed. ++ */ ++ if (bdm_gdb_no_wait && (bdm_get_status () == 0)) { ++ ret = 0; ++ } ++ else { ++ if (regno < 16) { ++ ret = bdmReadRegister (regno, &lu); ++ } ++ else { ++ if (regno < NUM_REGS_BDM) { ++ ret = bdm_read_sys_ctl_reg (BDM_REG_NAME (regno), ++ BDM_REG_CODE (regno), ++ &lu); ++ if (*BDM_REG_TYPE (regno) == builtin_type_m68881_ext) ++ ret = bdm_read_sys_ctl_reg (BDM_REG_NAME (regno), ++ BDM_REG_CODE (regno) + 1, ++ &ll); ++ } ++ else { ++ error ("Bad register number (%d)", regno); ++ return; ++ } ++ } ++ } ++ if (ret < 0) ++ bdm_report_error (); ++ cbuf[0] = lu >> 24; ++ cbuf[1] = lu >> 16; ++ cbuf[2] = lu >> 8; ++ cbuf[3] = lu; ++ cbuf[4] = ll >> 24; ++ cbuf[5] = ll >> 16; ++ cbuf[6] = ll >> 8; ++ cbuf[7] = ll; ++ regcache_raw_supply (current_regcache, regno, cbuf); ++ } ++} ++ ++void ++bdm_prepare_to_store (void) ++{ ++ /* Do nothing, since we can store individual regs */ ++} ++ ++/* ++ * Store register REGNO, or all user registers if REGNO == -1. ++ */ ++void ++bdm_store_register (int regno) ++{ ++ unsigned long l; ++ int ret; ++ ++ if (bdm_gdb_no_wait && (bdm_get_status () == 0)) ++ return; ++ ++ if (regno == -1) { ++ for (regno = 0 ; regno < NUM_REGS_BDM ; regno++) ++ bdm_store_register (regno); ++ } ++ else { ++ l = read_register (regno); ++ if (regno < 16) { ++ ret = bdmWriteRegister (regno, l); ++ } ++ else { ++ if (regno < NUM_REGS_BDM) { ++ ret = bdm_write_sys_ctl_reg (BDM_REG_NAME (regno), ++ BDM_REG_CODE (regno), ++ l); ++ } ++ else { ++ error ("Bad register number (%d)", regno); ++ return; ++ } ++ } ++ if (ret < 0) ++ bdm_report_error (); ++ } ++} ++ ++/* ++ * Transfer memory contents between target and host ++ */ ++static int ++bdm_xfer_inferior_memory (CORE_ADDR memaddr, char *myaddr, ++ int len, int write, ++ struct mem_attrib *attrib, ++ struct target_ops *t) ++{ ++ int ret; ++ ++ if (write) ++ ret = bdmWriteMemory (memaddr, (unsigned char*) myaddr, len); ++ else ++ ret = bdmReadMemory (memaddr, (unsigned char*) myaddr, len); ++ if (ret < 0) ++ bdm_report_error (); ++ return len; ++} ++ ++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"); ++ } ++} ++ ++/* ++ * Toggle the no load variable. ++ */ ++static void ++bdm_toggle_no_load (char *args, int from_tty) ++{ ++ if (!bdm_no_load) { ++ bdm_no_load = 1; ++ printf_filtered ("Image not loaded on run\n"); ++ } ++ else { ++ bdm_no_load = 0; ++ printf_filtered ("Image loaded on run\n"); ++ } ++} ++ ++/* ++ * Select a CPU32 processor register set. ++ */ ++static void ++bdm_select_cpu32 (char *args, int from_tty) ++{ ++ cpu_type = BDM_MARCH_CPU32PLUS; ++} ++ ++/* ++ * Get or set the use of the PST signals when using a Coldfire. ++ */ ++static void ++bdm_cf_pst (char *args, int from_tty) ++{ ++ int pst; ++ ++ if (!args) ++ { ++ if (bdmColdfireGetPST (&pst) < 0) ++ printf_filtered ("error getting the PST state: %d\n", errno); ++ else ++ printf_filtered ("PST signal use: %s\n", pst ? "ENABLED" : "DISABLED"); ++ } ++ else ++ { ++ pst = strtoul (args, 0, 0); ++ if (pst) ++ pst = 1; ++ if (bdmColdfireSetPST (pst) < 0) ++ printf_filtered ("error setting the PST state: %d\n", errno); ++ } ++} ++ ++/* ++ * Read or write control registers. ++ */ ++static void ++bdm_read_control_reg (char *exp, int from_tty) ++{ ++ static LONGEST reg = -1; ++ static char format = 'x'; ++ struct cleanup *old_chain = 0; ++ struct expression *expr; ++ struct value* val; ++ struct type type; ++ unsigned long l; ++ ++ if (!exp) { ++ if (reg < 0) ++ error ("you need to supply a 16bit register value, eg VBR = 0x801\n"); ++ } ++ else { ++ if (*exp == '/') { ++ exp++; ++ if (*exp == 'd' || *exp == 'x') ++ format = *exp; ++ else ++ error ("format specifiers are 'd' or 'x\n"); ++ exp++; ++ } ++ ++ expr = parse_expression (exp); ++ old_chain = make_cleanup (free_current_contents, &expr); ++ val = evaluate_expression (expr); ++ ++ if (VALUE_LVAL (val) == not_lval || VALUE_LVAL (val) == lval_internalvar) ++ reg = unpack_long (VALUE_TYPE (val), VALUE_CONTENTS (val)); ++ else { ++ reg = -1; ++ format = 'x'; ++ do_cleanups (old_chain); ++ error ("the register can be a literal or a gdb variable"); ++ } ++ ++ do_cleanups (old_chain); ++ } ++ ++ if (bdmReadControlRegister (reg, &l) < 0) ++ bdm_report_error (); ++ ++ if (format == 'x') ++ printf_filtered ("0x%08lx\n", l); ++ else ++ printf_filtered ("%ld\n", l); ++} ++ ++static void ++bdm_write_control_reg (char *exp, int from_tty) ++{ ++ static int reg = -1; ++ static int l = 0x0; ++ struct cleanup *old_chain = 0; ++ struct expression *expr; ++ struct value* val; ++ char* end; ++ ++ if (!exp && (reg < 0)) ++ error ("you need to supply a 16bit register value, eg VBR = 0x801\n"); ++ ++ /* ++ * Do a little token parsing to split the expression into 2 separate parts ++ * and then parse each one. There may be a better way but it will do. ++ */ ++ ++ end = strchr (exp, ' '); ++ ++ if (!end) { ++ end = strchr (exp, '\t'); ++ if (!end) ++ error ("write requires a register and a value to write\n"); ++ } ++ ++ *end = '\0'; ++ ++ expr = parse_expression (exp); ++ old_chain = make_cleanup (free_current_contents, &expr); ++ val = evaluate_expression (expr); ++ ++ if (VALUE_LVAL (val) == not_lval || VALUE_LVAL (val) == lval_internalvar) { ++ reg = unpack_long (VALUE_TYPE (val), VALUE_CONTENTS (val)); ++ } ++ else { ++ reg = -1; ++ l = 0; ++ do_cleanups (old_chain); ++ error ("the register can be a literal or a gdb variable"); ++ } ++ ++ do_cleanups (old_chain); ++ ++ old_chain = 0; ++ ++ exp = end + 1; ++ ++ expr = parse_expression (exp); ++ old_chain = make_cleanup (free_current_contents, &expr); ++ val = evaluate_expression (expr); ++ ++ if (VALUE_LVAL (val) == not_lval || VALUE_LVAL (val) == lval_internalvar) { ++ l = unpack_long (VALUE_TYPE (val), VALUE_CONTENTS (val)); ++ } ++ else { ++ reg = -1; ++ l = 0; ++ do_cleanups (old_chain); ++ error ("the data to write can be a literal or a gdb variable"); ++ } ++ ++ do_cleanups (old_chain); ++ ++ if (bdmWriteControlRegister (reg, l) < 0) ++ bdm_report_error (); ++} ++ ++struct target_ops bdm_ops; ++ ++static void ++init_bdm_ops(void) ++{ ++ bdm_ops.to_shortname = "bdm"; ++ bdm_ops.to_longname = ++ "CPU32 and Coldfire Background Debug Mode Interface" \ ++ " for downloading and remote debugging"; ++ bdm_ops.to_doc = "Uses the Public Domain Background Debug Mode Interface connected to the\n" \ ++ "BDM-port of the CPU32 or Coldfire based microcontroller and to a parallel port\n" ++ "of the PC.\n" \ ++ "Usage: target bdm \n" \ ++ "where is the BDM character special file (e.g. /dev/bdmcf0)."; ++ bdm_ops.to_open = bdm_open; ++ bdm_ops.to_close = bdm_close; ++ bdm_ops.to_attach = bdm_attach; ++ bdm_ops.to_detach = bdm_detach; ++ bdm_ops.to_resume = bdm_resume; ++ bdm_ops.to_wait = bdm_wait; ++ 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.deprecated_xfer_memory = bdm_xfer_inferior_memory; ++ bdm_ops.to_files_info = bdm_files_info; ++ bdm_ops.to_insert_breakpoint = memory_insert_breakpoint; ++ bdm_ops.to_remove_breakpoint = memory_remove_breakpoint; ++ bdm_ops.to_kill = bdm_kill; ++ bdm_ops.to_load = bdm_load; ++ bdm_ops.to_stop = bdm_stop_chip; ++ bdm_ops.to_create_inferior = bdm_create_inferior; ++ bdm_ops.to_mourn_inferior = bdm_mourn_inferior; ++ bdm_ops.to_can_run = bdm_can_run; ++ bdm_ops.to_stratum = process_stratum; ++ 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; ++ bdm_ops.to_magic = OPS_MAGIC; ++ bdm_ops.to_stopped_by_watchpoint = cf_stopped_by_watchpoint; ++ bdm_ops.to_can_use_hw_breakpoint = cf_can_use_watchpoint; ++ bdm_ops.to_stopped_data_address = cf_stopped_data_address; ++ bdm_ops.to_insert_hw_breakpoint = cf_insert_hw_breakpoint; ++ bdm_ops.to_remove_hw_breakpoint = cf_remove_hw_breakpoint; ++ bdm_ops.to_insert_watchpoint = cf_insert_watchpoint; ++ bdm_ops.to_remove_watchpoint = cf_remove_watchpoint; ++}; ++ ++void ++_initialize_remote_bdmcf (void) ++{ ++ bdm_ptid = null_ptid; ++ init_bdm_ops (); ++ add_com ("bdm-reset", class_obscure, ++ (void (*)(char *, int))bdm_reset, ++ "Reset target and enter BDM mode."); ++ add_com ("bdm-release", class_obscure, ++ (void (*)(char *, int))bdm_release_chip, ++ "Reset target without BDM-mode."); ++ add_com ("bdm-status", class_obscure, ++ (void (*)(char *, int))bdm_get_status_interactive, ++ "Show status of bdm interface\n"); ++ add_com ("bdm-setdelay", class_obscure, ++ bdm_setdelay_interactive, ++ "set delay for download"); ++ add_com ("bdm-setdebug", class_obscure, ++ bdm_setdebug_interactive, ++ "enable/disable BDM diagnostic messages"); ++ add_com ("bdm-setdriverdebug", class_obscure, ++ bdm_setdriverdebug_interactive, ++ "enable/disable BDM driver diagnostic messages"); ++ add_com ("bdm-no-wait", class_obscure, ++ bdm_set_no_wait, ++ "Cause GDB to not wait for the target to stop when running."); ++ add_com ("bdm-wait", class_obscure, ++ bdm_set_wait, ++ "Cause GDB to wait for the target to stop when running."); ++ add_com ("bdm-stop", class_obscure, ++ bdm_issue_stop, ++ "Stop the target if running."); ++ add_com ("bdm-select-cpu32", class_obscure, ++ bdm_select_cpu32, ++ "Selects the CPU32 register set rather than the default CPU32+."); ++ add_com ("bdm-no-load", class_obscure, ++ bdm_toggle_no_load, ++ "Toggle the loading of the program to memory when asked to run."); ++ add_com ("bdm-cf-pst", class_obscure, ++ bdm_cf_pst, ++ "Get or set the use of the PST signals."); ++ add_com ("bdm-read-creg", class_obscure, ++ bdm_read_control_reg, ++ "Read a control register from the processor."); ++ add_com ("bdm-write-creg", class_obscure, ++ bdm_write_control_reg, ++ "Write a control register from the processor."); ++ ++ add_target (&bdm_ops); ++} diff --git a/gdb/patches/insight-5.0.patch b/gdb/patches/insight-5.0.patch new file mode 100644 index 0000000..d6f4441 --- /dev/null +++ b/gdb/patches/insight-5.0.patch @@ -0,0 +1,55 @@ +diff -urN insight-5.0.orig/gdb/gdbtk/library/targetselection.itb insight-5.0/gdb/gdbtk/library/targetselection.itb +--- insight-5.0.orig/gdb/gdbtk/library/targetselection.itb Fri Feb 2 17:34:20 2001 ++++ insight-5.0/gdb/gdbtk/library/targetselection.itb Fri Feb 2 23:07:22 2001 +@@ -104,6 +104,20 @@ + set gdb_target(remotetcp,runlist) {1 1 0 1} + set gdb_target(remotetcp,after_attaching) {} + ++ # BDM ++ set gdb_target(bdm,pretty-name) "BDM/Direct" ++ set gdb_target(bdm,defbaud) "DIRECT" ++ set gdb_target(bdm,baud-rates) {} ++ set gdb_target(bdm,cmd) "bdm /dev/bdmcf0" ++ set gdb_target(bdm,runlist) {1 1 0 1} ++ set gdb_target(bdm,after_attaching) { setup-and-load } ++ set gdb_target(bdmtcp,pretty-name) "BDM/TCP" ++ set gdb_target(bdmtcp,defbaud) "TCP" ++ set gdb_target(bdmtcp,baud-rates) {} ++ set gdb_target(bdmtcp,cmd) "BDM tcpX" ++ set gdb_target(bdmtcp,runlist) {1 1 0 1} ++ set gdb_target(bdmtcp,after_attaching) { setup-and-load } ++ + # ARM Angel + set gdb_target(rdi,pretty-name) "ARM Angel/Serial" + set gdb_target(rdi,defbaud) "9600" +@@ -627,7 +641,20 @@ + pref define gdb/load/$t-verbose [pref get gdb/load/verbose] + $f.fr.verb config -variable [pref varname gdb/load/$t-verbose] + # Map the correct entries and comboboxes onto the screen +- if {$gdb_target($t,defbaud) == "TCP"} { ++ if {$gdb_target($t,defbaud) == "DIRECT"} { ++ # we have a direct device target ++ # map device ++ if {$mapped1 != "$fr.host"} { ++ grid forget $mapped1 ++ set mapped1 $fr.host ++ grid $mapped1 -row 1 -column 1 -sticky w -padx 5 -pady 5 ++ } ++ $fr.cbl configure -text "Device:" ++ $fr.host config -textvariable [pref varname gdb/load/$t-device] ++ ++ $mapped1 configure -state normal ++# $mapped2 configure -state normal ++ } elseif {$gdb_target($t,defbaud) == "TCP"} { + # we have a tcp target + # map host and porte + if {$mapped1 != "$fr.host"} { +@@ -769,7 +796,7 @@ + # ------------------------------------------------------------------ + body TargetSelection::change_baud {w {baud ""}} { + if {$baud != ""} { +- if {[string compare $baud "TCP"] != 0} { ++ if {[string compare $baud "TCP"] != 0 && [string compare $baud "DIRECT"] != 0} { + gdb_cmd "set remotebaud $baud" + if {[catch {gdb_cmd "show remotebaud"} res]} { + set newbaud 0 diff --git a/gdb/patches/insight-5.2.1.patch b/gdb/patches/insight-5.2.1.patch new file mode 100644 index 0000000..26893fb --- /dev/null +++ b/gdb/patches/insight-5.2.1.patch @@ -0,0 +1,56 @@ +diff -urN insight-5.2.1.orig/gdb/gdbtk/library/targetselection.itb insight-5.2.1/gdb/gdbtk/library/targetselection.itb +--- insight-5.2.1.orig/gdb/gdbtk/library/targetselection.itb 2002-02-12 21:05:14.000000000 +0100 ++++ insight-5.2.1/gdb/gdbtk/library/targetselection.itb 2003-06-14 00:48:01.000000000 +0200 +@@ -104,6 +104,20 @@ + set gdb_target(remotetcp,runlist) {1 1 0 1} + set gdb_target(remotetcp,after_attaching) {} + ++ # BDM ++ set gdb_target(bdm,pretty-name) "BDM/Direct" ++ set gdb_target(bdm,defbaud) "DIRECT" ++ set gdb_target(bdm,baud-rates) {} ++ set gdb_target(bdm,cmd) "bdm /dev/bdmcf0" ++ set gdb_target(bdm,runlist) {1 1 0 1} ++ set gdb_target(bdm,after_attaching) { setup-and-load } ++ set gdb_target(bdmtcp,pretty-name) "BDM/TCP" ++ set gdb_target(bdmtcp,defbaud) "TCP" ++ set gdb_target(bdmtcp,baud-rates) {} ++ set gdb_target(bdmtcp,cmd) "BDM tcpX" ++ set gdb_target(bdmtcp,runlist) {1 1 0 1} ++ set gdb_target(bdmtcp,after_attaching) { setup-and-load } ++ + # ARM Angel + set gdb_target(rdi,pretty-name) "ARM Angel/Serial" + set gdb_target(rdi,defbaud) "9600" +@@ -681,7 +695,20 @@ + pref define gdb/load/$t-verbose [pref get gdb/load/verbose] + $f.fr.verb config -variable [pref varname gdb/load/$t-verbose] + # Map the correct entries and comboboxes onto the screen +- if {$gdb_target($t,defbaud) == "TCP"} { ++ if {$gdb_target($t,defbaud) == "DIRECT"} { ++ # we have a direct device target ++ # map device ++ if {$mapped1 != "$fr.host"} { ++ grid forget $mapped1 ++ set mapped1 $fr.host ++ grid $mapped1 -row 1 -column 1 -sticky w -padx 5 -pady 5 ++ } ++ $fr.cbl configure -text "Device:" ++ $fr.host config -textvariable [pref varname gdb/load/$t-device] ++ ++ $mapped1 configure -state normal ++# $mapped2 configure -state normal ++ } elseif {$gdb_target($t,defbaud) == "TCP"} { + # we have a tcp target + # map host and porte + if {$mapped1 != "$fr.host"} { +@@ -833,7 +860,8 @@ + body TargetSelection::change_baud {w {baud ""}} { + if {$baud != ""} { + if {([string compare $baud "TCP"] != 0) +- && ([string compare $baud "ETH"] != 0)} { ++ && ([string compare $baud "ETH"] != 0) ++ && ([string compare $baud "DIRECT"] != 0)} { + gdb_cmd "set remotebaud $baud" + if {[catch {gdb_cmd "show remotebaud"} res]} { + set newbaud 0 diff --git a/gdb/patches/insight-5.3.patch b/gdb/patches/insight-5.3.patch new file mode 100644 index 0000000..9eb7da0 --- /dev/null +++ b/gdb/patches/insight-5.3.patch @@ -0,0 +1,79 @@ +diff -urN insight-5.3.orig/gdb/gdbtk/library/targetselection.itb insight-5.3/gdb/gdbtk/library/targetselection.itb +--- insight-5.3.orig/gdb/gdbtk/library/targetselection.itb 2002-02-12 21:05:14.000000000 +0100 ++++ insight-5.3/gdb/gdbtk/library/targetselection.itb 2003-06-14 00:48:01.000000000 +0200 +@@ -104,6 +104,20 @@ + set gdb_target(remotetcp,runlist) {1 1 0 1} + set gdb_target(remotetcp,after_attaching) {} + ++ # BDM ++ set gdb_target(bdm,pretty-name) "BDM/Direct" ++ set gdb_target(bdm,defbaud) "DIRECT" ++ set gdb_target(bdm,baud-rates) {} ++ set gdb_target(bdm,cmd) "bdm /dev/bdmcf0" ++ set gdb_target(bdm,runlist) {1 1 0 1} ++ set gdb_target(bdm,after_attaching) { setup-and-load } ++ set gdb_target(bdmtcp,pretty-name) "BDM/TCP" ++ set gdb_target(bdmtcp,defbaud) "TCP" ++ set gdb_target(bdmtcp,baud-rates) {} ++ set gdb_target(bdmtcp,cmd) "BDM tcpX" ++ set gdb_target(bdmtcp,runlist) {1 1 0 1} ++ set gdb_target(bdmtcp,after_attaching) { setup-and-load } ++ + # ARM Angel + set gdb_target(rdi,pretty-name) "ARM Angel/Serial" + set gdb_target(rdi,defbaud) "9600" +@@ -681,7 +695,20 @@ + pref define gdb/load/$t-verbose [pref get gdb/load/verbose] + $f.fr.verb config -variable [pref varname gdb/load/$t-verbose] + # Map the correct entries and comboboxes onto the screen +- if {$gdb_target($t,defbaud) == "TCP"} { ++ if {$gdb_target($t,defbaud) == "DIRECT"} { ++ # we have a direct device target ++ # map device ++ if {$mapped1 != "$fr.host"} { ++ grid forget $mapped1 ++ set mapped1 $fr.host ++ grid $mapped1 -row 1 -column 1 -sticky w -padx 5 -pady 5 ++ } ++ $fr.cbl configure -text "Device:" ++ $fr.host config -textvariable [pref varname gdb/load/$t-device] ++ ++ $mapped1 configure -state normal ++# $mapped2 configure -state normal ++ } elseif {$gdb_target($t,defbaud) == "TCP"} { + # we have a tcp target + # map host and porte + if {$mapped1 != "$fr.host"} { +@@ -833,7 +860,8 @@ + body TargetSelection::change_baud {w {baud ""}} { + if {$baud != ""} { + if {([string compare $baud "TCP"] != 0) +- && ([string compare $baud "ETH"] != 0)} { ++ && ([string compare $baud "ETH"] != 0) ++ && ([string compare $baud "DIRECT"] != 0)} { + gdb_cmd "set remotebaud $baud" + if {[catch {gdb_cmd "show remotebaud"} res]} { + set newbaud 0 +diff -Nur insight-5.3.orig/gdb/gdbtk/generic/gdbtk-hooks.c insight-5.3/gdb/gdbtk/generic/gdbtk-hooks.c +--- insight-5.3.orig/gdb/gdbtk/generic/gdbtk-hooks.c 2002-07-03 19:38:22.000000000 +0200 ++++ insight-5.3/gdb/gdbtk/generic/gdbtk-hooks.c 2003-09-05 14:02:42.000000000 +0200 +@@ -518,6 +518,10 @@ + gdbtk_call_command (struct cmd_list_element *cmdblk, + char *arg, int from_tty) + { ++ struct cleanup *old_chain; ++ ++ old_chain = make_cleanup (null_cleanup, 0); ++ + running_now = 0; + if (cmdblk->class == class_run || cmdblk->class == class_trace) + { +@@ -532,6 +536,8 @@ + } + else + cmd_func (cmdblk, arg, from_tty); ++ ++ do_cleanups (old_chain); + } + + /* Called after a `set' command succeeds. Runs the Tcl hook diff --git a/gdb/patches/insight-6.0.patch b/gdb/patches/insight-6.0.patch new file mode 100644 index 0000000..2418b07 --- /dev/null +++ b/gdb/patches/insight-6.0.patch @@ -0,0 +1,56 @@ +diff -Nru insight-5.3.92.orig/gdb/gdbtk/library/targetselection.itb insight-5.3.92/gdb/gdbtk/library/targetselection.itb +--- insight-5.3.92.orig/gdb/gdbtk/library/targetselection.itb 2003-02-04 09:03:09.000000000 +0100 ++++ insight-5.3.92/gdb/gdbtk/library/targetselection.itb 2003-09-21 13:12:41.000000000 +0200 +@@ -104,6 +104,20 @@ + set gdb_target(remotetcp,runlist) {1 1 0 1} + set gdb_target(remotetcp,after_attaching) {} + ++ # BDM ++ set gdb_target(bdm,pretty-name) "BDM/Direct" ++ set gdb_target(bdm,defbaud) "DIRECT" ++ set gdb_target(bdm,baud-rates) {} ++ set gdb_target(bdm,cmd) "bdm /dev/bdmcf0" ++ set gdb_target(bdm,runlist) {1 1 0 1} ++ set gdb_target(bdm,after_attaching) { setup-and-load } ++ set gdb_target(bdmtcp,pretty-name) "BDM/TCP" ++ set gdb_target(bdmtcp,defbaud) "TCP" ++ set gdb_target(bdmtcp,baud-rates) {} ++ set gdb_target(bdmtcp,cmd) "BDM tcpX" ++ set gdb_target(bdmtcp,runlist) {1 1 0 1} ++ set gdb_target(bdmtcp,after_attaching) { setup-and-load } ++ + # ARM Angel + set gdb_target(rdi,pretty-name) "ARM Angel/Serial" + set gdb_target(rdi,defbaud) "9600" +@@ -694,7 +708,20 @@ + pref define gdb/load/$t-verbose [pref get gdb/load/verbose] + $f.fr.verb config -variable [pref varname gdb/load/$t-verbose] + # Map the correct entries and comboboxes onto the screen +- if {$gdb_target($t,defbaud) == "TCP"} { ++ if {$gdb_target($t,defbaud) == "DIRECT"} { ++ # we have a direct device target ++ # map device ++ if {$mapped1 != "$fr.host"} { ++ grid forget $mapped1 ++ set mapped1 $fr.host ++ grid $mapped1 -row 1 -column 1 -sticky w -padx 5 -pady 5 ++ } ++ $fr.cbl configure -text "Device:" ++ $fr.host config -textvariable [pref varname gdb/load/$t-device] ++ ++ $mapped1 configure -state normal ++# $mapped2 configure -state normal ++ } elseif {$gdb_target($t,defbaud) == "TCP"} { + # we have a tcp target + # map host and porte + if {$mapped1 != "$fr.host"} { +@@ -846,7 +873,8 @@ + itcl::body TargetSelection::change_baud {w {baud ""}} { + if {$baud != ""} { + if {([string compare $baud "TCP"] != 0) +- && ([string compare $baud "ETH"] != 0)} { ++ && ([string compare $baud "ETH"] != 0) ++ && ([string compare $baud "DIRECT"] != 0)} { + gdb_cmd "set remotebaud $baud" + if {[catch {gdb_cmd "show remotebaud"} res]} { + set newbaud 0 diff --git a/gdb/scripts/5206.gdb b/gdb/scripts/5206.gdb new file mode 100644 index 0000000..93fec37 --- /dev/null +++ b/gdb/scripts/5206.gdb @@ -0,0 +1,127 @@ +# +# GDB Init script for the Coldfire 5206 processor. +# +# The main purpose of this script is to configure the +# DRAM controller so code can be loaded. +# +# + +define addresses + +set $mbar = 0x10000001 +set $simr = $mbar - 1 + 0x003 +set $icr1 = $mbar - 1 + 0x014 +set $icr2 = $mbar - 1 + 0x015 +set $icr3 = $mbar - 1 + 0x016 +set $icr4 = $mbar - 1 + 0x017 +set $icr5 = $mbar - 1 + 0x018 +set $icr6 = $mbar - 1 + 0x019 +set $icr7 = $mbar - 1 + 0x01A +set $icr8 = $mbar - 1 + 0x01B +set $icr9 = $mbar - 1 + 0x01C +set $icr10 = $mbar - 1 + 0x01D +set $icr11 = $mbar - 1 + 0x01E +set $icr12 = $mbar - 1 + 0x01F +set $icr13 = $mbar - 1 + 0x020 +set $imr = $mbar - 1 + 0x036 +set $ipr = $mbar - 1 + 0x03A +set $rsr = $mbar - 1 + 0x040 +set $sypcr = $mbar - 1 + 0x041 +set $swivr = $mbar - 1 + 0x042 +set $swsr = $mbar - 1 + 0x043 +set $dcrr = $mbar - 1 + 0x046 +set $dctr = $mbar - 1 + 0x04A +set $dcar0 = $mbar - 1 + 0x04C +set $dcmr0 = $mbar - 1 + 0x050 +set $dccr0 = $mbar - 1 + 0x057 +set $dcar1 = $mbar - 1 + 0x058 +set $dcmr1 = $mbar - 1 + 0x05C +set $dccr1 = $mbar - 1 + 0x063 +set $csar0 = $mbar - 1 + 0x064 +set $csmr0 = $mbar - 1 + 0x068 +set $cscr0 = $mbar - 1 + 0x06E +set $csar1 = $mbar - 1 + 0x070 +set $csmr1 = $mbar - 1 + 0x074 +set $cscr1 = $mbar - 1 + 0x07A +set $csar2 = $mbar - 1 + 0x07C +set $csmr2 = $mbar - 1 + 0x080 +set $cscr2 = $mbar - 1 + 0x086 +set $csar3 = $mbar - 1 + 0x088 +set $csmr3 = $mbar - 1 + 0x08C +set $cscr3 = $mbar - 1 + 0x092 +set $csar4 = $mbar - 1 + 0x094 +set $csmr4 = $mbar - 1 + 0x098 +set $cscr4 = $mbar - 1 + 0x09E +set $csar5 = $mbar - 1 + 0x0A0 +set $csmr5 = $mbar - 1 + 0x0A4 +set $cscr5 = $mbar - 1 + 0x0AA +set $csar6 = $mbar - 1 + 0x0AC +set $csmr6 = $mbar - 1 + 0x0B0 +set $cscr6 = $mbar - 1 + 0x0B6 +set $csar7 = $mbar - 1 + 0x0B8 +set $csmr7 = $mbar - 1 + 0x0BC +set $cscr7 = $mbar - 1 + 0x0C2 +set $dmcr = $mbar - 1 + 0x0C6 +set $par = $mbar - 1 + 0x0CA +set $tmr1 = $mbar - 1 + 0x100 +set $trr1 = $mbar - 1 + 0x104 +set $tcr1 = $mbar - 1 + 0x108 +set $tcn1 = $mbar - 1 + 0x10C +set $ter1 = $mbar - 1 + 0x111 +set $tmr2 = $mbar - 1 + 0x120 +set $trr2 = $mbar - 1 + 0x124 +set $tcr2 = $mbar - 1 + 0x128 +set $tcn2 = $mbar - 1 + 0x12C +set $ter2 = $mbar - 1 + 0x131 + +end + +# +# Setup CSAR0 for the FLASH ROM. +# + +define setup-cs + +set *((short*) $csar0) = 0xffe0 +set *((short*) $csmr0) = 0x00030000 +set *((short*) $cscr0) = 0x0d83 +set *((short*) $csar1) = 0xffff +set *((short*) $csmr1) = 0x0000001e +set *((short*) $cscr1) = 0x0043 +set *((short*) $csar2) = 0x3000 +set *((short*) $csmr2) = 0x00000014 +set *((short*) $cscr2) = 0x0043 +set *((short*) $csar3) = 0x4000 +set *((short*) $csmr3) = 0x000f0000 +set *((short*) $cscr3) = 0x0083 + +end + +# +# Setup the DRAM controller. +# + +define setup-dram + +set *((short*) $dcrr) = 24 +set *((short*) $dctr) = 0x0000 +set *((short*) $dcar0) = 0x0000 +set *((long*) $dcmr0) = 0x000e0000 +set *((char*) $dccr0) = 0x07 +set *((short*) $dcar1) = 0x0000 +set *((long*) $dcmr1) = 0x00000000 +set *((char*) $dccr1) = 0x00 + +end + +# +# Wake up the board +# + +defined initBoard + +addresses +setup-cs +setup-dram + +end \ No newline at end of file diff --git a/gdb/scripts/Makefile b/gdb/scripts/Makefile new file mode 100644 index 0000000..e0097e8 --- /dev/null +++ b/gdb/scripts/Makefile @@ -0,0 +1,15 @@ +prefix = /usr/local/RTEMS + +SCRIPTDIR = $(prefix)/lib/gdbScripts +BINDIR = $(prefix)/bin + +all: + +install: + -mkdir -p $(SCRIPTDIR) + for i in *.gdb ; do sed -e "/===PREFIX===/s@@$(prefix)"@ $$i >$(SCRIPTDIR)/$$i ; done + -mkdir -p $(BINDIR) + sed -e "/===PREFIX===/s@@$(prefix)"@ m68k-rtems-gdb >$(BINDIR)/m68k-rtems-gdb + chmod 755 $(BINDIR)/m68k-rtems-gdb + +clean: diff --git a/gdb/scripts/RTEMS360.gdb b/gdb/scripts/RTEMS360.gdb new file mode 100644 index 0000000..7d2f3b9 --- /dev/null +++ b/gdb/scripts/RTEMS360.gdb @@ -0,0 +1,43 @@ +# +# Prepare to download and run an RTEMS executable image +# + +# +# Load BDM/CPU32 support +# +source ===PREFIX===/lib/gdbScripts/SAL68360.gdb +source ===PREFIX===/lib/gdbScripts/showCPU32Exception.gdb + +# +# Connect to the BDM interface +# +target bdm /dev/bdmcpu320 +bdm_setdelay 0 + +# +# Catch exceptions and display the exception stack +# +break _uhoh +commands +displayExceptionStack +end + +# +# Regain control on fatal errors +# +break rtems_panic +break _Internal_error_Occurred +break rtems_fatal_error_occurred + +# +# Quit when the RTEMS executable finishes +# +break _mainDone +commands +quit +end + +# +# Get the hardware to a known state +# +initBoard diff --git a/gdb/scripts/RTEMS5206.gdb b/gdb/scripts/RTEMS5206.gdb new file mode 100644 index 0000000..ed29a44 --- /dev/null +++ b/gdb/scripts/RTEMS5206.gdb @@ -0,0 +1,43 @@ +# +# Prepare to download and run an RTEMS executable image +# + +# +# Load BDM/CF support +# +source ===PREFIX===/lib/gdbScripts/5206.gdb +source ===PREFIX===/lib/gdbScripts/showCPU32Exception.gdb + +# +# Connect to the BDM interface +# +target bdm /dev/bdmcf0 +bdm_setdelay 0 + +# +# Catch exceptions and display the exception stack +# +break _uhoh +commands +displayExceptionStack +end + +# +# Regain control on fatal errors +# +break rtems_panic +break _Internal_error_Occurred +break rtems_fatal_error_occurred + +# +# Quit when the RTEMS executable finishes +# +break _mainDone +commands +quit +end + +# +# Get the hardware to a known state +# +initBoard diff --git a/gdb/scripts/SAL68360.gdb b/gdb/scripts/SAL68360.gdb new file mode 100644 index 0000000..03a5546 --- /dev/null +++ b/gdb/scripts/SAL68360.gdb @@ -0,0 +1,78 @@ +##################################################################### +# Board setup for SAL Communications Controller card # +##################################################################### + +define initBoard + +bdm_reset + +# +# Step 4: Set up module base address register +# +set $dpram = 0x0e000000 +set $mbar = $dpram|0x101 +set $regb = $dpram+0x1000 + +# +# I/O is to supervisor program space +# +set $dfc=5 +set $sfc=5 + +# +# Step 7: Deal with clock synthesizer +# +set {unsigned char}($regb+0x000c) = 0x8f +set {unsigned char}($regb+0x0010) = 0xd000 +set {unsigned short}($regb+0x0014) = 0x8000 + +# +# Step 8: Initialize system protection +# +set {unsigned char}($regb+0x0022) = 0x7f + +# +# Step 9: Clear parameter RAM and reset communication processor module +# Ignore this for now, since all we want to use is the memory controller +# + +# +# Step 10: Write PEPAR +# +set {unsigned short}($regb+0x0016) = 0x0180 + +# +# Step 11: Remap Chip Select 0 (CS0} +# +set {unsigned long}($regb+0x0040) = 0x17940120 +set {unsigned long}($regb+0x0054) = 0x4ff80004 +set {unsigned long}($regb+0x0050) = 0x0f000003 + +# +# Step 12: Initialize the system RAM +# +set {unsigned long}($regb+0x0064) = 0x0f000001 +set {unsigned long}($regb+0x0060) = 0x00000001 +set $ramjnk={unsigned long}0@8 + +# +# Determine RAM size +# +set {char}0 = 0 +if ({char}0x00801000 == 0) + set {char}0 = 1 + if ({char}0x000801000 == 1) + set {unsigned long}($regb+0x0040) = 0x178C0120 + end +end + +# +# Step 15: Set module configuration register +# +set {unsigned long}($regb+0x0000) = 0x00004c7f + +end + +define hook-run +initBoard +end diff --git a/gdb/scripts/m68k-rtems-gdb b/gdb/scripts/m68k-rtems-gdb new file mode 100644 index 0000000..d853ba7 --- /dev/null +++ b/gdb/scripts/m68k-rtems-gdb @@ -0,0 +1,3 @@ +#!/bin/sh + +exec m68k-bdm-elf-gdb -x "===PREFIX===/lib/gdbScripts/RTEMS360.gdb" "$@" diff --git a/gdb/scripts/showCPU32Exception.gdb b/gdb/scripts/showCPU32Exception.gdb new file mode 100644 index 0000000..fca6952 --- /dev/null +++ b/gdb/scripts/showCPU32Exception.gdb @@ -0,0 +1,22 @@ +# +# Display an exception stack +# +define displayExceptionStack +set $frsr = *(unsigned short *)$sp +set $frpc = *(unsigned long *)((unsigned long)$sp + 2) +set $frfvo = *(unsigned short *)((unsigned long)$sp + 6) +set $frcode = $frfvo >> 12 +set $frvect = ($frfvo & 0xFFF) >> 2 +printf "EXCEPTION -- SR:0x%X PC:0x%X FRAME:0x%x VECTOR:%d\n", $frsr, $frpc, $frcode, $frvect +if $frcode==0x2 + set $fripc = *(unsigned long *)((unsigned long)$sp + 0x8) + set $frssw = *(unsigned short *)((unsigned long)$sp + 0x16) + printf " INSTRUCTION PC:0x%X\n", $fripc, +end +if $frcode==0xC + set $frfault = *(unsigned long *)((unsigned long)$sp + 0x8) + set $fripc = *(unsigned long *)((unsigned long)$sp + 0x10) + set $frssw = *(unsigned short *)((unsigned long)$sp + 0x16) + printf " ADDRESS:0x%X INSTRUCTION PC:0x%X SSW:0x%X\n", $frfault, $fripc, $frssw +end +end diff --git a/m683xx/README b/m683xx/README new file mode 100644 index 0000000..72644b6 --- /dev/null +++ b/m683xx/README @@ -0,0 +1,28 @@ +This directory contains M683xx specific BDM +driver version and GDB utilities from the +development branch with following history + + * Scott Howard, original author of Motorola + BDM library and utilities, Feb 93 + * M. Schraut, original author of BDM driver + * Gunter Magin magin AT skil.camelot.de + maintainer of BDM and GDB till 98 + * Pavel Pisa pisa AT cmp.felk.cvut.cz + enhancements and maintaining this branch from May 98 + +The full documentation of this branch +is at this moment at next URLs: + + http://cmp.felk.cvut.cz/~pisa + http://cmp.felk.cvut.cz/~pisa/m683xx/bdm_driver.html + +This driver uses different API than Chris's tool-chain. +Code is there to: + + * provide support for people using this branch + * archival purposes + * as source for integration of same features + (DEVFS, PARPORT) into Chris's driver. + +Pavel Pisa pisa@cmp.felk.cvut.cz 2003 + diff --git a/m683xx/README-5.3-bdm-683xx b/m683xx/README-5.3-bdm-683xx new file mode 100644 index 0000000..a53e4ff --- /dev/null +++ b/m683xx/README-5.3-bdm-683xx @@ -0,0 +1,43 @@ +Plain gdb and insight (that is the GUI extended gdb) can be built with +just one build: download insight-5.3 instead of gdb-5.3. Then apply both, +gdb-5.3-bdm-683xx-patch and insight-5.3-bdm-683xx-patch. This builds +m68k-bdm-coff-gdb (this is plain gdb) and m68k-bdm-coff-insight (this is +GUI-enabled gdb) + +To get insight running I needed to put the following into my .gdbinit68 file: + + set prompt (gdb-bdm) + set hash 1 + bdm_log off + bdm_setdelay 0 + bdm_autoreset on + bdm_timetocomeup 0 + bdm_load_use_lma 1 + #target bdm /dev/pd_bdm0 + target bdm /dev/icd_bdm0 + bdm_debug_driver 0 + + # this macro is called by insight directly after attaching to target but + # just before the processor is let to run. + # + define reset + bdm_reset + bdm_entry gdb_entry + set $pc = gdb_entry + set $vbr = __s_text + set $sp = ((unsigned long *)$vbr)[0] + # + # insert breakpoints on positions that indicate big trouble. + # + delete + break excpt_handl + break halt_system + break uninit_irq + end + +There is still a problem with insight: On start up insight sometimes get +into an endless loop trying to read a cycle of stack frames. I don't know +what triggers this loop, but when it happens once it is perfectly +reproducable. Deleting ~/.gdbtkinit helps in this case, but I have no idea +why it helps. + diff --git a/m683xx/bdm-driver/MAKEDEV b/m683xx/bdm-driver/MAKEDEV new file mode 100644 index 0000000..551f637 --- /dev/null +++ b/m683xx/bdm-driver/MAKEDEV @@ -0,0 +1,7 @@ +cd /dev +mknod -m666 pd_bdm0 c 53 0 +mknod -m666 pd_bdm1 c 53 1 +mknod -m666 pd_bdm2 c 53 2 +mknod -m666 icd_bdm0 c 53 4 +mknod -m666 icd_bdm1 c 53 5 +mknod -m666 icd_bdm2 c 53 6 diff --git a/m683xx/bdm-driver/Makefile b/m683xx/bdm-driver/Makefile new file mode 100644 index 0000000..426a615 --- /dev/null +++ b/m683xx/bdm-driver/Makefile @@ -0,0 +1,121 @@ +#******************************************************************* +# Motorola 683xx BDM Driver for Linux Kernel and GNU Debugger +# +# Makefile-mod - Makefile for regular compilation +# through Linux kernel rules +# +# This file must be renamed or linked to Makefile +# +# (C) Copyright 1999 by Pavel Pisa +# +# The BDM driver is distributed under the Gnu General Public Licence. +# See file COPYING for details. +#*******************************************************************/ + +# Use "make MODULE_NAME=foobar" if you want to give the driver module +# a different name. This might be usefull if you want to install both, +# Chris's and Pavel's drivers at the same machine. +MODULE_NAME=m683xx-bdm + +# currently running kernel +CURRENT=$(shell uname -r) +KERNEL_NEW=$(shell if [ -d /lib/modules/$(CURRENT)/build ] ; \ + then echo yes ; else echo no ; fi ) + +# Where to look for kernel +#KERNEL_LOCATION=/usr/src/linux +#KERNEL_LOCATION=/usr/src/kernel/$(CURRENT) +#KERNEL_LOCATION=/lib/modules/$(CURRENT)/build +#KERNEL_LOCATION=/usr/src/linux-2.2.19 +#KERNEL_LOCATION=/usr/src/linux-2.5.60 + +ifndef KERNEL_LOCATION +ifeq ($(KERNEL_NEW),yes) +KERNEL_LOCATION=/lib/modules/$(CURRENT)/build +MODULE_CHAR_LOC=/lib/modules/$(CURRENT)/kernel/drivers/char +else +KERNEL_LOCATION=/usr/src/linux +MODULE_CHAR_LOC=/lib/modules/$(CURRENT)/misc +endif +endif + +# Test for latest 2.5.xx and future 2.6.xx kernels +KERNEL_VERSION := $(shell awk -F\" '/REL/ {print $$2}' \ + $(KERNEL_LOCATION)/include/linux/version.h | awk -F\- '{print $$1}') + +ifeq ($(KERNEL_VERSION),) +KERNEL_VERSION=$(shell grep UTS_RELEASE ${KERNEL_LOCATION}/include/linux/utsrelease.h | \ + sed 's/[^"]*"\(.*\)\{1\}"/\1/') +endif + +KERNEL_MODULE_V26 := $(shell echo $(KERNEL_VERSION) \ + | sed -n 's/^.*2\.[5-9]\..*$$/yes/p') + +# Target object file if any +O_TARGET := +# Regular object files +O_OBJS = $(MODULE_NAME).o +# Objects with exported symbols (-DEXPORT_SYMTAB) +OX_OBJS = +# Module objects +M_OBJS = $(O_OBJS) +# Module only objects with exported symbols (-DEXPORT_SYMTAB) +MX_OBJS = +# Kernel only objects +L_OBJS = +# Kernel only objects with exported symbols (-DEXPORT_SYMTAB) +LX_OBJS = +# Additional CFLAGS +EXTRA_CFLAGS = + +# Linux 2.4.2 build system needs next +obj-m += $(O_OBJS) + +ifndef KERNEL_MODULE_V26 +FINAL_MODULE_OBJS=$(obj-m) +else +FINAL_MODULE_OBJS=$(obj-m:%.o=%.ko) +endif + +all : make_this_module + +install : install_this_module + +$(MODULE_NAME).c: bdm.c bdm.h + cp $< $@ + +make_this_module: $(MODULE_NAME).c + DIR=`pwd`; (cd $(KERNEL_LOCATION); make SUBDIRS=$$DIR modules) + +install_this_module: make_this_module + su -c "mkdir -v -p $(MODULE_CHAR_LOC) && cp -v $(FINAL_MODULE_OBJS) $(MODULE_CHAR_LOC)" + +clean: + rm -f $(M_OBJS) $(MX_OBJS) *.ko .*.o.flags .*.o.cmd .*.ko.cmd .depend *~ + +# which interface do you want to use +# now you can select both without problems +INTERFACE+= -D PD_INTERFACE +INTERFACE+= -D ICD_INTERFACE + +# if you want to use ispGAL programming +INTERFACE+= -DEFIICDISP + +# last possible way to make system work when you have problems +# with single step or stop +# it tries to find 17 bit protocol boundary +# after single step or stop +BDM_DEFS += -D BDM_TRY_RESYNCHRO + +# if you want a PARPORT compatible device, then +# uncomment the following line +BDM_DEFS += -DWITH_PARPORT_SUPPORT + + +EXTRA_CFLAGS= $(INTERFACE) $(BDM_DEFS) + + +ifndef KERNEL_MODULE_V26 +include $(KERNEL_LOCATION)/Rules.make +endif + diff --git a/m683xx/bdm-driver/README b/m683xx/bdm-driver/README new file mode 100644 index 0000000..0909ba0 --- /dev/null +++ b/m683xx/bdm-driver/README @@ -0,0 +1,91 @@ +This version of BDM driver is updated to be compatible with +the most of existing kernel versions. Main focus has been oriented +to 2.2.x and 2.4.x, but most of other unstable and stable kernels +back to 1.3.x stone age should be supported. + +Driver needs to find kernel sources to compile. +You may need to edit "Makefile-mod" for some strange kernel +sources locations. There is automatic location selection depending +on current kernel version and "/lib/modules" structure. +It select next kernel souces directory for older kernels + + KERNEL_LOCATION=/usr/src/linux + +it uses more reliable way of build process for +new modules hierarchy + + KERNEL_LOCATION=/lib/modules/$(CURRENT)/build + +*** BDM driver autoloading *** + +No longer su to root, insmod the module of choice, and then start the +debugger as user-joe, but just start the debugger, and the necessary +modules get loaded automatically. + +What do you have to do? + * You need to copy the device driver code to + /lib/modules//misc + for 2.4.0 kernels use + /lib/modules//kernel/drivers/char + * edit /etc/conf.modules + (see my local /etc/conf.modules as an example) + * do a "depmod -a". + * Start "kerneld" at an early boot stage + or enable "kmod" in kernel configuration in section + "Loadable module support". + +For more details on dynamic kernel module support, see the READMEs +in the latest modules utilities. The current release is modutils-2.4.22. + +*** IMPORTANT *** + +The bdm driver checks if the required resources (here only the io-port +addresses) are in use, e.g. by the lp device driver or a parallel port +ethernet device. When everything is free, it reserves these resources, and +releases them when closing the device. So no double access should be possible. + +If BDM driver is compiled without PARPORT support, there could be problem +with "parport", "parport_pc" and "lp" module stack resource reservation, +which could compete with "m683xx-bdm" driver. Compile "lp" and "parport" +as modules in such case and unload them before "m683xx-bdm". +Opposite is true in the case of BDM driver with PARPORT support. +You need "parport_pc" compiled into kernel or as module. + +Possibilities reworded + +A) You need to rmmod parport, if you have compiled BDM driver WITHOUT parport + support. It can be done by next line added to "/etc/modules.conf" + + pre-install bdm /sbin/modprobe -r lp parport_pc + +B) If BDM driver is compiled WITH parport support, the "parport_pc" module + have to be loaded before "bdm" one. It is loaded by boot process in the + most cases but next line in "/etc/modules.conf" doe not hurt + + below bdm parport_pc + +** DEVFS support *** + +Driver supports new "devfs" virtual device filesystem found in +2.4.0 kernels. There are compiled-in next device names for those +kenels "/dev/m683xx-bdm/pd0" and "/dev/m683xx-bdm/icd0" etc. + +You can add next line to "/etc/devfs.conf" + + LOOKUP m683xx-bdm MODLOAD + +Next line helps to connect simple "/dev/bdm" name for right configuration + + LOOKUP m683xx-bdm EXECUTE /bin/ln -s ${mntpnt}/m683xx-bdm/icd0 ${mntpnt}/m683xx-bdm + +There are lines for "/dev/modules.conf" with aliases for different kernels + + # m68k BDM + alias /dev/bdm m683xx-bdm + alias /dev/m683xx-bdm m683xx-bdm + alias char-major-53 m683xx-bdm + # the next line is required/usable for BDM driver compiled without + # parport support. You might want to remove this line if you get errors + # about unresolved symbols when the driver is loaded. + pre-install m683xx-bdm /sbin/modprobe -r lp parport_pc + diff --git a/m683xx/bdm-driver/bdm.c b/m683xx/bdm-driver/bdm.c new file mode 100644 index 0000000..d3df62e --- /dev/null +++ b/m683xx/bdm-driver/bdm.c @@ -0,0 +1,1967 @@ +/* + * $Id: bdm.c,v 1.8 2006/12/28 13:04:58 ppisa Exp $ + * + * Linux Device Driver BDM Interface + * based on the PD driver package by Scott Howard, Feb 93 + * PD version ported to Linux by M.Schraut, Feb 95 + * enhancements from W. Eric Norum (eric@skatter.usask.ca), who did + * a Next-Step-Port in Jun 95 + * tested for kernel version 1.3.57 + * (C) 1995, 1996 Technische Universitaet Muenchen, L. f. Prozessrechner + * (C) 1997 Gunter Magin, Muenchen + * + * Modified by Pavel Pisa pisa@cmp.felk.cvut.cz 1997 - 2003 + * tested for kernel version 2.2.x and 2.4.x with ICD and PD cables + * new k_compat.h for kernels up to 2.4.0 + * + * 2003/04/27 modified by Juergen Eder : + * Compatible with parport driver + * define in makefile: -DWITH_PARPORT_SUPPORT + * + +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. + + */ + +#undef REALLY_SLOW_IO + +#include +#include +#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,17) +#include +#endif +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,60) +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17) +#include +#endif +#else /* 2.5.60 */ +#ifdef MODVERSIONS +#include +#endif /* MODVERSIONS */ +#endif /* 2.5.60 */ +#include +#include +#include +#include +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) // fixme ? + #include /* instead of malloc.h */ +#else + #include +#endif +#include +#include +#include +#include +#ifdef WITH_PARPORT_SUPPORT +#include +#endif +#include +#include +#include +#include "bdm.h" +#include "k_compat.h" + +#if (LINUX_VERSION_CODE >= VERSION(2,4,0)) + #define BDM_WITH_DEVFS + #include + kc_devfs_handle_t bdm_devfs_handle=NULL; +#endif + +#define BDM_DEVFS_DIR_NAME "m683xx-bdm" + +MODULE_SUPPORTED_DEVICE("m683xx-bdm"); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Motorola m683xx BDM debugging interface"); + +#define BDM_DRIVER_VERSION 4 + +#if !defined PD_INTERFACE && !defined ICD_INTERFACE +#error You have to decide for the PD interface or the ICD interface +#error Check the Makefile and uncomment the right line +#endif + +#if !defined ICD_INTERFACE && defined EFIICDISP +#error It makes no sense to enable ISP programming support in a driver not +#error for ICD compatible devices +#error Check the Makefile and either disable EFIICDISP or enable ICD_INTERFACE +#endif + +#define BYTECOUNT_FOR_BEING_NICE 64 + /* no of bytes to transfer before giving + * other tasks opportunity being scheduled */ +#define BDM_WAITCNT 0xffff /* no of loops to wait for response */ +#define BITS 15 /* shift 16bit into 32 bit by 15 */ + /* -.1.Bit always 0 (Statusbit) */ + +/* declaration of local variables */ +#define BDM_DLY_DEFAULT 30 + +#define BDM_LONG_DLY(d) (2*d/3 == 0) ? 1 : (2*d/3) +#define BDM_HALF_DLY(d) (d/2 == 0) ? 1 : (d/2) +#define BDM_SHORT_DLY(d) (d/3 == 0) ? 1 : (d/3) +#define BDM_MIN_DLY(d) (d/30 == 0) ? 1 : (d/30) +static int bdm_norm_dly = BDM_DLY_DEFAULT; +static int bdm_long_dly = BDM_LONG_DLY(BDM_DLY_DEFAULT); +static int bdm_half_dly = BDM_HALF_DLY(BDM_DLY_DEFAULT); +static int bdm_short_dly = BDM_SHORT_DLY(BDM_DLY_DEFAULT); +static int bdm_min_dly = BDM_MIN_DLY(BDM_DLY_DEFAULT); +static int bdm_reset_dly = 0; +static int bdm_no_ser_dly_mode = 0; /* mode for maximal speed */ +#define SER_CLK_DSO_WAIT 0x100 /* in fast mode, delay only before */ + /* explicit serial transfers */ + +static unsigned int bdm_debug_level = BDM_DEBUG_NONE; +static int bdm_version = BDM_DRIVER_VERSION; +static int bdm_sense = 1; /* do sense power & connected */ + +typedef unsigned int status_bitset; + +#define BDM_DESCR_MAGIC 0x42444daa + +typedef struct _bdm_descr_t bdm_descr_t; +struct _bdm_descr_t { + unsigned int magic; + #ifndef WITH_PARPORT_SUPPORT + unsigned int port_adr; + #else /* WITH_PARPORT_SUPPORT */ + unsigned int parport_nr; + #endif /* WITH_PARPORT_SUPPORT */ + unsigned int minor; + status_bitset (*init) (bdm_descr_t *); + int (*deinit) (bdm_descr_t *); + status_bitset (*getstatus) (bdm_descr_t *); + int (*restart_chip) (bdm_descr_t *); + int (*release_chip) (bdm_descr_t *); + int (*stop_chip) (bdm_descr_t *); + int (*step_chip) (bdm_descr_t *); + int (*reset_chip) (bdm_descr_t *); + int (*ser_clk) (bdm_descr_t *, short, int); + int (*set_led) (bdm_descr_t *, int); + status_bitset (*resynchro) (bdm_descr_t *); + char *name; + unsigned int old_ctl; /* save old control port settings */ + unsigned int shadow_ctl; /* shadow reg. of control port for read */ +}; + +/* generic helper functions */ + +#ifndef WITH_PARPORT_SUPPORT + +#define PORT_ADDRESSE_LP1 0x378 /* LPT1 */ +#define PORT_ADDRESSE_LP2 0x278 /* LPT2 */ +#define PORT_ADDRESSE_LP3 0x3bc /* LPT3 */ + +#define BDM_DATA(d) (d->port_adr) +#define BDM_STAT(d) (d->port_adr + 1) +#define BDM_CTRL(d) (d->port_adr + 2) + +static unsigned char +bdm_in_ctl(bdm_descr_t * descr) +{ + return inb(BDM_CTRL(descr)); +} + +static void +bdm_out_ctl(int data, bdm_descr_t * descr) +{ + outb(data,BDM_CTRL(descr)); + descr->shadow_ctl=data; +} + +static unsigned char +bdm_in_st(bdm_descr_t * descr) +{ + return inb(BDM_STAT(descr)); +} + +static void +bdm_out_data(int data, bdm_descr_t * descr) +{ + outb(data,BDM_DATA(descr)); +} + +static unsigned char +bdm_in_data(bdm_descr_t * descr) +{ + return inb(BDM_DATA(descr)); +} + +#else /* WITH_PARPORT_SUPPORT */ + +#define PORT_ADDRESSE_LP1 0 +#define PORT_ADDRESSE_LP2 1 +#define PORT_ADDRESSE_LP3 2 + +#define MAX_BDM_PORTS 3 +static struct pardevice *bdm_parports[MAX_BDM_PORTS]; + +static struct pardevice * +bdm_get_parport(bdm_descr_t * descr) +{ + if((unsigned)descr->parport_nr>=MAX_BDM_PORTS) + return NULL; + return bdm_parports[descr->parport_nr]; +} + +/*static int +bdm_get_parport_num(bdm_descr_t * descr) +{ + return descr->parport_nr; +}*/ + +static void +bdm_out_ctl(int data, bdm_descr_t * descr) +{ + struct pardevice *p; + p = bdm_get_parport(descr); + if(!p) + return; + #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) + parport_write_control(p->port,data & ~0x20); + if(data & 0x20) + parport_data_reverse(p->port); + else + parport_data_forward(p->port); + #else + parport_write_control(p->port,data); + #endif + descr->shadow_ctl=data; +} + +static unsigned char +bdm_in_ctl(bdm_descr_t * descr) +{ + struct pardevice *p; + p = bdm_get_parport(descr); + if(!p) + return 0; + #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) + /* There is no 'parport_read_control()' function -> use my own variable */ + return descr->shadow_ctl; + #else + return parport_read_control(p->port); + #endif +} + +static unsigned char +bdm_in_st(bdm_descr_t * descr) +{ + struct pardevice *p; + p = bdm_get_parport(descr); + if(!p) + return 0; + return parport_read_status(p->port); +} + +static void +bdm_out_data(int data, bdm_descr_t * descr) +{ + struct pardevice *p; + p = bdm_get_parport(descr); + if(!p) + return; + parport_write_data(p->port,data); +} + +static unsigned char +bdm_in_data(bdm_descr_t * descr) +{ + struct pardevice *p; + p = bdm_get_parport(descr); + if(!p) + return 0; + return parport_read_data(p->port); +} + +#endif /* WITH_PARPORT_SUPPORT */ + +/* slow down host for not overrunning target */ +static void +bdm_delay(int counter) +{ + + if (counter < (1000000/HZ)) { + while (counter > 1000) { + udelay(1000); counter -= 1000; + } + udelay(counter); + } else { + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(counter/(1000000/HZ)); + } +#if NEVER + while (counter--) { + asm volatile ("nop"); + } +#endif /* NEVER */ +} + + +static void +bdm_error(int bdm_type) +{ + if (bdm_debug_level >= BDM_DEBUG_SOME) { + switch (bdm_type) { + case -BDM_FAULT_UNKNOWN: + printk("Unknown Error - check speed\n"); + break; + case -BDM_FAULT_POWER: + printk("Power failed on Target MCU\n"); + break; + case -BDM_FAULT_CABLE: + printk("Cable disconnected on Target MCU\n"); + break; + case -BDM_FAULT_RESPONSE: + printk("No response from Target MCU\n"); + break; + case -BDM_FAULT_RESET: + printk("Can t clock Target MCU while on Reset\n"); + break; + case -BDM_FAULT_PORT: + printk("Wrong Port\n"); + break; + case -BDM_FAULT_BERR: + printk("Buserror\n"); + break; + } + } +} + +#define do_case(x) case x: ret = #x; break; + +static char * +bdm_get_ioctl_name(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); + do_case(BDM_RESPW); +#ifdef EFIICDISP + do_case(BDM_ISPSET); + do_case(BDM_ISPGET); +#endif + default: + ret = "Unknown ioctl"; + } + return ret; +} + + +#ifdef PD_INTERFACE + +/* + * Parallel port bit assignments for the PD interface (minor-numbers 0-2) + * + * Status register (bits 0-2 not used): + * +---+---+---+---+---+---+---+---+ + * | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | + * +---+---+---+---+---+---+---+---+ + * | | | | | + * | | | | +--- Target FREEZE line + * | | | | 1 - Target is in background mode + * | | | | 0 - Target is not background mode + * | | | | + * | | | +------- Not used + * | | | + * | | +----------- Serial data from target + * | | 1 - `0' from target + * | | 0 - `1' from target + * | | + * | +--------------- Target power + * | 1 - Target power is ON + * | 0 - Target power is OFF + * | + * +------------------- Target connected + * 1 - Target is connected + * 0 - Target is not connected + * + * Control register (bits 4-7 not used): + * +---+---+---+---+ + * | 3 | 2 | 1 | 0 | + * +---+---+---+---+ + * | | | | + * | | | +--- Target BKPT* /DSCLK line + * | | | Write 1 - Drive BKPT* /DSCLK line LOW + * | | | Write 0 - Drive BKPT* /DSCLK line HIGH + * | | | + * | | +------- Target RESET* line + * | | Write 1 - Force RESET* LOW + * | | Write 0 - Allow monitoring of RESET* + * | | Read 1 - RESET* is LOW + * | | Read 0 - RESET* is HIGH + * | | + * | +----------- Serial data to target + * | Write 0 - Send `0' to target + * | Write 1 - Send `1' to target + * | + * +--------------- Control single-step flip-flop + * Write 1 - Clear flip-flop + * BKPT* /DSCLK is controlled by bit 0. + * Write 0 - Allow flip-flop operation + * Falling edge of IFETCH* /DSI clocks a `1' + * into the flip-flop and drive BKPT* /DSCLK + * LOW, causing a breakpoint. + */ + +#define BDMPD_DSCLK 1 /* data shift clock / breakpoint pin */ +#define BDMPD_RST_OUT 2 /* set high to force reset on MCU */ +#define BDMPD_DSI 4 /* data shift input Host->MCU */ +#define BDMPD_STEP_OUT 8 /* set low to gate IFETCH onto BKPT */ + +#define BDMPD_FREEZE 8 /* FREEZE asserted when MCU stopped */ +#define BDMPD_DSO 0x20 /* data shift output MCU-.Host */ +#define BDMPD_PWR_DWN 0x40 /* power down - low when Vcc failed */ +#define BDMPD_NC 0x80 /* not connected - low when unplugged */ + + +static status_bitset +bdm_pd_init(bdm_descr_t *descr) +{ + status_bitset status; + bdm_out_ctl(BDMPD_STEP_OUT | BDMPD_DSCLK, descr); + /* force breakpoint */ + bdm_delay(bdm_min_dly); + status = descr->getstatus(descr); /* eg connected, power etc. */ + if (bdm_debug_level >= BDM_DEBUG_SOME) { + printk("bdm_pd_init minor %d status %d\n", + descr->minor, status); + } + return status; +} + +static int +bdm_pd_deinit(bdm_descr_t * descr) +{ +#if LP_PORT_RESTORE + if (bdm_debug_level >= BDM_DEBUG_SOME) { + printk("bdm_deinit: restoring %#x\n", descr->old_ctl); + } + bdm_out_ctl(descr->old_ctl, descr); + /* restore old control port settings */ +#endif /* LP_PORT_RESTORE */ + return BDM_FAULT_NOERROR; +} + +/* read status byte from statusport and translate into bitset */ +static status_bitset +bdm_pd_getstatus(bdm_descr_t *descr) +{ + unsigned char temp = bdm_in_st(descr); + + if (bdm_debug_level >= BDM_DEBUG_ALL) { + printk("bdm_pd_getstatus minor=%d res=%#x\n", descr->minor, temp); + } + if (bdm_sense) { + if (!(temp & BDMPD_NC)) + return BDM_TARGETNC; + if (!(temp & BDMPD_PWR_DWN)) + return BDM_TARGETPOWER; + } + return (temp & BDMPD_FREEZE ? BDM_TARGETSTOPPED : 0) | + (bdm_in_ctl(descr) & BDMPD_RST_OUT ? BDM_TARGETRESET : 0); +} + +/* this routine is last resort one, it is able resyncronize with MCU, + when some spike on DSCLK has disturbed MCU */ +static status_bitset +bdm_pd_resynchro(bdm_descr_t *descr) +{ + int i; + descr->ser_clk(descr, BDM_NOP_CMD, 0); /* send NOP command */ + descr->ser_clk(descr, BDM_NOP_CMD, 0); /* send NOP command */ + descr->ser_clk(descr, BDM_NOP_CMD, 0); /* send NOP command */ + i=17; /* maximal number disturb in bit shift */ + while(i--) + { + if((bdm_in_st(descr) & BDMPD_DSO)) + return BDM_FAULT_NOERROR; /* DSO becomes 0 => OK */ + bdm_out_ctl( BDMPD_STEP_OUT | BDMPD_DSCLK, descr); /* DSCLK=0 */ + bdm_delay(bdm_norm_dly); + bdm_out_ctl( BDMPD_STEP_OUT , descr); /* DSCLK=1 */ + bdm_delay(bdm_norm_dly); + } + return -BDM_FAULT_UNKNOWN; +} + +/* restart chip and stop on first execution fetch */ +static int +bdm_pd_restart_chip(bdm_descr_t * descr) +{ + unsigned bdm_Loop_Count = 0; + + if (bdm_debug_level >= BDM_DEBUG_SOME) { + printk("bdm_pd_restart_chip minor=%d\n", descr->minor); + } + + bdm_out_ctl(BDMPD_DSCLK, descr); + bdm_out_ctl(BDMPD_RST_OUT | BDMPD_DSCLK, descr); + bdm_delay(bdm_norm_dly+bdm_reset_dly); + bdm_out_ctl(BDMPD_DSCLK, descr); + bdm_delay(bdm_norm_dly); + bdm_out_ctl(BDMPD_STEP_OUT | BDMPD_DSCLK, descr); + for (bdm_Loop_Count = 0xffff; bdm_Loop_Count; bdm_Loop_Count--) + if (bdm_in_st(descr) & BDMPD_FREEZE) + break; + if (!bdm_Loop_Count) { + bdm_error(-BDM_FAULT_RESPONSE); + return -BDM_FAULT_RESPONSE; + } else { + return BDM_FAULT_NOERROR; + } + +} + + +/* stop running target */ +static int +bdm_pd_stop_chip(bdm_descr_t * descr) +{ + unsigned int bdm_ctr; + int return_value; + + if (bdm_debug_level >= BDM_DEBUG_SOME) { + printk("bdm_pd_stop_chip minor=%d\n", descr->minor); + } + + if (bdm_in_st(descr) & BDMPD_FREEZE) { + if (bdm_debug_level >= BDM_DEBUG_SOME) { + printk("bdm_pd_stop_chip: already frozen..\n"); + }; + /* ensures no spike on BKPT/DSCLK in bdm_ser_clk */ + bdm_out_ctl(BDMPD_DSCLK, descr); + bdm_delay(bdm_short_dly); + bdm_out_ctl(BDMPD_DSCLK | BDMPD_STEP_OUT, descr); + return BDM_FAULT_NOERROR; /* target was already halted */ + } + + if (bdm_debug_level >= BDM_DEBUG_SOME) { + printk("bdm_pd_stop_chip: was not frozen..\n"); + } + return_value = -BDM_FAULT_UNKNOWN; + + /* bdm_out_ctl(BDMPD_DSCLK | BDMPD_STEP_OUT, descr); */ + bdm_out_ctl(BDMPD_DSCLK*0, descr); + + if (bdm_debug_level >= BDM_DEBUG_SOME) { + printk("bdm_pd_stop_chip: armed stop\n"); + } + for (bdm_ctr = BDM_WAITCNT; bdm_ctr; bdm_ctr--) { + if ((bdm_in_st(descr)) & BDMPD_FREEZE) { + return_value = BDM_FAULT_NOERROR; /* target is now halted */ + break; + } + bdm_delay(bdm_min_dly); + } + + if (bdm_debug_level >= BDM_DEBUG_SOME) { + printk("bdm_pd_stop_chip: after wait-for-freeze: cntr = %d\n", + BDM_WAITCNT-bdm_ctr); + } + bdm_out_ctl(BDMPD_DSCLK, descr); + bdm_delay(bdm_norm_dly); + bdm_out_ctl(BDMPD_DSCLK | BDMPD_STEP_OUT, descr); + + if (!bdm_ctr) { + bdm_error(-BDM_FAULT_RESPONSE); + return -BDM_FAULT_RESPONSE; + } + #ifdef BDM_TRY_RESYNCHRO + descr->resynchro(descr); /* tries to find correct 17 bit boundary */ + #endif /* BDM_TRY_RESYNCHRO */ + return return_value; +} + + + +/* single stepping target mcu */ +static int +bdm_pd_step_chip(bdm_descr_t * descr) +{ + int tester; + unsigned short DataOut = (BDM_GO_CMD & 1 ? BDMPD_DSI : 0); + + status_bitset bdm_stat = descr->getstatus(descr); + + if (bdm_debug_level >= BDM_DEBUG_SOME) { + printk("bdm_pd_step_chip minor=%d\n", descr->minor); + } + + if (bdm_stat & BDM_TARGETRESET) { + bdm_error(-BDM_FAULT_RESET); + return -BDM_FAULT_RESET; + } + if (bdm_stat & BDM_TARGETNC) { + bdm_error(-BDM_FAULT_CABLE); + return -BDM_FAULT_CABLE; + } + if (bdm_stat & BDM_TARGETPOWER) { + bdm_error(-BDM_FAULT_POWER); + return -BDM_FAULT_POWER; + } + tester = descr->ser_clk(descr, BDM_GO_CMD, 1); + switch (tester) { + case -BDM_FAULT_RESET: + case -BDM_FAULT_CABLE: + case -BDM_FAULT_POWER: + return tester; + } + if (bdm_debug_level >= BDM_DEBUG_ALL) { + printk("stepchip sent: %x got : %x\n", + BDM_GO_CMD, (unsigned int) tester); + printk("last answerbit : %x\n", !(bdm_in_st(descr) & BDMPD_DSO)); + } + /* + * this is the place the inb() should take place, but on step_chip, we + * don't care for the reply of CPU32, coming in when sending the cmd + */ + bdm_out_ctl(BDMPD_DSCLK | BDMPD_STEP_OUT | DataOut, descr); + bdm_delay(bdm_norm_dly); + bdm_out_ctl(BDMPD_DSCLK | DataOut, descr); + bdm_delay(bdm_long_dly); + /* leave more time to avoid a glitch on DSCLK*/ + bdm_out_ctl(DataOut, descr); + /* FREEZE goes low after */ + /* 10 CPU32 clock cycles, it is about 700ns @ 16 MHz */ + bdm_delay(bdm_long_dly); + #ifdef BDM_TRY_RESYNCHRO + descr->stop_chip(descr); + return descr->resynchro(descr); + #else /* BDM_TRY_RESYNCHRO */ + return descr->stop_chip(descr); + #endif /* BDM_TRY_RESYNCHRO */ +} + +/* reset target chip without asserting bkpt/!dsclk */ +static int +bdm_pd_release_chip(bdm_descr_t * descr) +{ + if (bdm_debug_level >= BDM_DEBUG_SOME) { + printk("bdm_pd_release_chip minor=%d\n", descr->minor); + } + + bdm_out_ctl(BDMPD_DSCLK | BDMPD_STEP_OUT, descr); + bdm_delay(bdm_short_dly); + bdm_out_ctl(BDMPD_DSCLK | BDMPD_RST_OUT | BDMPD_STEP_OUT, descr); + bdm_delay(bdm_norm_dly); + bdm_out_ctl(BDMPD_STEP_OUT, descr); + bdm_delay(bdm_short_dly); + + return BDM_FAULT_NOERROR; +} + +/* + * Restart chip, enable background debugging mode, halt on first fetch + * + * The software from the Motorola BBS tries to have the target + * chip begin execution, but that doesn't work very reliably. + * The RESETH* line rises rather slowly, so sometimes the BKPT* / DSCLK + * would be seen low, and sometimes it wouldn't. + */ +static int +bdm_pd_reset_chip(bdm_descr_t * descr) +{ + if (bdm_debug_level >= BDM_DEBUG_SOME) { + printk("bdm_pd_reset_chip minor=%d\n", descr->minor); + } + +#if NEVER + /* this is the original Howard code */ + bdm_out_ctl(BDMPD_RST_OUT | BDMPD_STEP_OUT, descr); + bdm_delay(bdm_norm_dly); + bdm_out_ctl(BDMPD_STEP_OUT, descr); +#endif /* NEVER */ + + + /* this is suggested by Eric Norum */ + bdm_out_ctl(BDMPD_DSCLK | BDMPD_RST_OUT, descr); + bdm_delay(bdm_norm_dly+bdm_reset_dly); + bdm_out_ctl(BDMPD_DSCLK, descr); + bdm_delay(bdm_norm_dly+bdm_reset_dly); + bdm_out_ctl(BDMPD_DSCLK | BDMPD_STEP_OUT, descr); + return BDM_FAULT_NOERROR; +} + + +/* serial software protokoll for bdm-pd-interface */ +static int +bdm_pd_ser_clk(bdm_descr_t * descr, short bdm_value, int delay_bits) +{ + unsigned int ShiftRegister; + unsigned char DataOut; + unsigned counter; + unsigned bdm_stat = descr->getstatus(descr); + + ShiftRegister = bdm_value; + ShiftRegister <<= BITS; + if (bdm_stat & BDM_TARGETRESET) { /*error checking */ + bdm_error(-BDM_FAULT_RESET); + return -BDM_FAULT_RESET; + } + if (bdm_stat & BDM_TARGETNC) { + bdm_error(-BDM_FAULT_CABLE); + return -BDM_FAULT_CABLE; + } + if (bdm_stat & BDM_TARGETPOWER) { + bdm_error(-BDM_FAULT_POWER); + return -BDM_FAULT_POWER; + } + if(!(bdm_stat & BDM_TARGETSTOPPED)) + { if (bdm_debug_level >= BDM_DEBUG_SOME) + printk("bdm_ser_clk stop target first minor=%d\n", descr->minor); + if(descr->stop_chip(descr)!=BDM_FAULT_NOERROR) + { printk("bdm_ser_clk can't stop it minor=%d\n", descr->minor); + return -BDM_FAULT_RESPONSE; + } + } + + /* + * We can get there with DSCLK high or low + * but next code is OK for both cases + * first ensures DSCLK low => it frozes transmit shift + * register against CPU32 updates until 17 bits are sent + * and then clocks transmit shift register by DSCLK high + */ + + if (bdm_debug_level >= BDM_DEBUG_ALL) { + printk("bdm_pd_ser_clk: writing %5x\n", bdm_value); + } + if(bdm_no_ser_dly_mode && (delay_bits&SER_CLK_DSO_WAIT)) + { /* Wait for DSO to become 0 to indicate ready + * according CPU32UM, DSO is updated as long as + * DSCLK is high + */ + int wait_cnt; + for(wait_cnt=0;wait_cnt<100;wait_cnt++) + { if (bdm_in_st(descr) & BDMPD_DSO) + break; /* DSO becomed zerro already */ + bdm_delay(bdm_min_dly); + } + if(wait_cnt && (bdm_debug_level >= BDM_DEBUG_SOME)) + printk("bdm_pd_ser_clk: ready after %d cycles\n", + wait_cnt); + } + + counter = 32 - BITS - (delay_bits&0xff); + while (counter--) { + DataOut = ((ShiftRegister & 0x80000000) ? BDMPD_DSI : 0); + /*if 1 then dsi=1*/ + ShiftRegister <<= 1; /*shift one bit left*/ + bdm_out_ctl(DataOut | BDMPD_STEP_OUT | BDMPD_DSCLK, descr); + if(!bdm_no_ser_dly_mode) + bdm_delay(bdm_half_dly); + if (!(bdm_in_st(descr) & BDMPD_DSO)) + ShiftRegister |= 1; /*put 1 on 0.bit */ + bdm_out_ctl(DataOut | BDMPD_STEP_OUT, descr); + if(!bdm_no_ser_dly_mode) + bdm_delay(bdm_norm_dly); + } + if (bdm_debug_level >= BDM_DEBUG_ALL) { + printk("bdm_pd_ser_clk: read %5x bits %d\n", + ShiftRegister, delay_bits); + } +#ifdef FIXME + if (!(delay_bits&0xff) && (ShiftRegister & 0x10000)) switch (ShiftRegister) { + case 0x1ffff: /* no valid command return */ + return -BDM_FAULT_NVC; + case 0x10001: + return -BDM_FAULT_BERR; + case 0x10000: + return BDM_NOTE_NOTREADY; + default: ; + } +#endif /* FIXME */ + return ShiftRegister; +} + +/* switch LED if available */ +static int +bdm_pd_setled(bdm_descr_t * descr, int switchstate) +{ + return 0; +} + +#endif + +#ifdef ICD_INTERFACE +/* + * Parallel port bit assignments for the ICD interface (minor-numbers 4-6) + * + * Status register + * +---+---+---+---+---+---+---+---+ + * | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | + * +---+---+---+---+---+---+---+---+ + * | | | | | + * | | | | +--- ICD detection + * | | | | must follow LED level + * | | | | + * | | | +------- Power Detection + * | | | 1 - Power available + * | | | 0 - no Power + * | | | + * | | +----------- Jumper State + * | | 1 - Jumper closed + * | | 0 - Jumper open + * | | + * | +--------------- Target FREEZE line + * | 1 - Target is in background mode + * | 0 - Target is not background mode + * | + * +------------------- Serial data from target + * 1 - `0' from target + * 0 - `1' from target + * + * Data register + * +---+---+---+---+---+---+---+---+ + * | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | + * +---+---+---+---+---+---+---+---+ + * | | | | | | | | + * | | | | | | | +--- Serial data to target + * | | | | | | | Write 1: Send 1 to target + * | | | | | | | Write 0: Send 0 to target + * | | | | | | | Signal gets to target, if OE is 1 + * | | | | | | | and target is in FREEZE mode + * | | | | | | | + * | | | | | | +------- Clock + * | | | | | | if target in freeze mode, then: + * | | | | | | Write 1: drive BKPT* /DSCLK 1 + * | | | | | | Write 0: drive BKPT* /DSCLK 0 + * | | | | | | + * | | | | | +----------- BREAK + * | | | | | if target not in freeze mode, then: + * | | | | | Write 0: drive BKPT* /DSCLK 0 + * | | | | | line determines single stepping + * | | | | | on leaving BGND mode: + * | | | | | Write 0: do single step + * | | | | | Write 1: continue normally + * | | | | | + * | | | | +--------------- RESET + * | | | | Write 0: pull reset low + * | | | | Write 1: release reset line + * | | | | + * | | | +--- OE + * | | | Write 0 - DSI is tristated + * | | | Write 1 - DSI pin is forced to level of serial data + * | | | + * | | +------- LED (not implemented everywhere..) + * | | Write 1 - turn on LED + * | | Write 0 - turn off LED + * | | + * | +----------- ERROR + * | Write 0 - BERR output is tristated + * | Write 1 - BERR is pulled low + * | + * +--------------- spare + */ + +/* data register bit definitions */ +#define BDMICD_DSI 0x01 /* data shift input Host->MCU */ +#define BDMICD_DSCLK 0x02 /* data shift clock / breakpoint pin */ +#define BDMICD_STEP_OUT 0x04 /* set low to force breakpoint */ +#define BDMICD_RST_OUT 0x08 /* set low to force reset on MCU */ +#define BDMICD_OE 0x10 /* set to a 1 to enable DSI */ +#define BDMICD_LED 0x20 /* set to 1 to turn on LED */ +#define BDMICD_FORCE_BERR 0x40 /* set to a 1 to force BERR on target */ + +/* status register bit definitions */ +#define BDMICD_DSO 0x80 /* serial data from target */ +#define BDMICD_FREEZE 0x40 /* 1 if target is frozen */ +#define BDMICD_JMPR 0x20 /* 1 if jumper is set */ +#define BDMICD_PWR 0x10 /* 1 if power available */ +#define BDMICD_ICDDETECT 0x08 /* must follow LED */ + +/* control register bit definitions */ +#define BDMICD_EFIDET 0x04 /* setting to 1 will pull LED feedback low */ +#define BDMICD_DCR_DIR 0x20 /* 0 -> drive data buffers, 1 -> data port tristate */ + +static int bdm_icd_led_status; + +/* + * Jumper seems to be responsible for SW generated breakpoints according to + * P&E's user manual + * + * we assume a Rev. A cable, so ignore jumper setting + * + * Power detection is instable: depends heavily on PP internal + * pull-ups/downs to get low level when there is no power + * + */ + + +static status_bitset +bdm_icd_init(bdm_descr_t * descr) +{ + status_bitset status; + unsigned char temp1, temp2; + + bdm_icd_led_status = BDMICD_LED; + + /* ensure data outputs are driven for BPP port configuration */ + bdm_out_ctl(BDMICD_DCR_DIR*0,descr); + + /* perform icd check */ + bdm_out_data(BDMICD_STEP_OUT | BDMICD_DSCLK | BDMICD_RST_OUT, descr); + bdm_delay(bdm_min_dly); + temp1 = bdm_in_st(descr); + bdm_out_data(BDMICD_STEP_OUT | BDMICD_DSCLK | BDMICD_RST_OUT | + bdm_icd_led_status, descr); + bdm_delay(bdm_min_dly); + temp2 = bdm_in_st(descr); + if ((temp1 ^ temp2) & BDMICD_ICDDETECT) { + printk("bdm_icd_init: detected ICD interface\n"); + } + + /* force breakpoint */ + bdm_delay(bdm_min_dly); + status = descr->getstatus(descr); + if (bdm_debug_level >= BDM_DEBUG_SOME) { + printk("bdm_icd_init minor %d status %d\n", + descr->minor, status); + } + return status; +} + +static int +bdm_icd_deinit(bdm_descr_t * descr) +{ +#if LP_PORT_RESTORE + if (bdm_debug_level >= BDM_DEBUG_SOME) { + printk("bdm_icd_deinit: restoring %#x\n", descr->bdm_old_ctl); + } + bdm_out_ctl(descr->bdm_old_ctl, descr); + /* restore old control port settings */ +#endif /* LP_PORT_RESTORE */ + return BDM_FAULT_NOERROR; +} + +/* read status byte from statusport and translate into bitset */ +static status_bitset +bdm_icd_getstatus(bdm_descr_t * descr) +{ + unsigned char temp = bdm_in_st(descr); + + if (bdm_debug_level > BDM_DEBUG_SOME) { + printk("bdm_icd_getstatus minor=%d res=%#x\n", descr->minor, temp); + } + if (bdm_sense) { + if (!(temp & BDMICD_PWR)) + return BDM_TARGETPOWER; + } + return (temp & BDMICD_FREEZE ? BDM_TARGETSTOPPED : 0); +} + +/* this routine is last resort one, it is able resyncronize with MCU, + when some spike on DSCLK has disturbed MCU */ +static status_bitset +bdm_icd_resynchro(bdm_descr_t *descr) +{ + int i; + descr->ser_clk(descr, BDM_NOP_CMD, 0); /* send NOP command */ + descr->ser_clk(descr, BDM_NOP_CMD, 0); /* send NOP command */ + descr->ser_clk(descr, BDM_NOP_CMD, 0); /* send NOP command */ + i=17; /* maximal number disturb in bit shift */ + while(i--) + { + if((bdm_in_st(descr) & BDMICD_DSO)) { + if (bdm_debug_level >= BDM_DEBUG_SOME) { + printk("bdm_icd_resynchro minor=%d shift=%d\n", + descr->minor,16-i); + } + return BDM_FAULT_NOERROR; /* DSO becomes 0 => OK */ + } + bdm_out_data(BDMICD_RST_OUT | BDMICD_OE | BDMICD_STEP_OUT, + descr); /* DSCLK=0 */ + bdm_delay(bdm_norm_dly); + bdm_out_data(BDMICD_RST_OUT | BDMICD_OE | BDMICD_STEP_OUT | + BDMICD_DSCLK, descr); /* DSCLK=1 */ + bdm_delay(bdm_norm_dly); + } + if (bdm_debug_level >= BDM_DEBUG_SOME) + printk("bdm_icd_resynchro failed\n"); + return -BDM_FAULT_UNKNOWN; +} + +/* restart chip and stop on first execution fetch */ +static int +bdm_icd_restart_chip(bdm_descr_t * descr) +{ + if (bdm_debug_level >= BDM_DEBUG_SOME) { + printk("bdm_icd_restart_chip minor=%d\n", descr->minor); + } + + bdm_out_data(BDMICD_DSCLK, descr); + bdm_delay(bdm_norm_dly+bdm_reset_dly); + return descr->stop_chip(descr); +} + + +/* stop running target */ +static int +bdm_icd_stop_chip(bdm_descr_t * descr) +{ + unsigned int bdm_ctr; + int return_value; + + if (bdm_debug_level >= BDM_DEBUG_SOME) { + printk("bdm_icd_stop_chip minor=%d\n", descr->minor); + } + + if ((bdm_in_st(descr)) & BDMICD_FREEZE) + { /* already frozen, ensure no spikes on BKPT/DSCLK in bdm_ser_clk */ + bdm_out_data(BDMICD_RST_OUT, descr); + bdm_delay(bdm_short_dly); + bdm_out_data(BDMICD_STEP_OUT | BDMICD_RST_OUT, descr); + return BDM_FAULT_NOERROR; + } + + return_value = -BDM_FAULT_UNKNOWN; + + bdm_delay(bdm_min_dly+100); +#if 1 /* stop imediately */ + bdm_out_data(BDMICD_RST_OUT, descr); +#else /* stop after this instruction */ + bdm_out_data(BDMICD_DSCLK | BDMICD_RST_OUT, descr); +#endif + bdm_delay(bdm_min_dly+300); + + + + for (bdm_ctr = BDM_WAITCNT; bdm_ctr; bdm_ctr--) { + if ((bdm_in_st(descr)) & BDMICD_FREEZE) { + return_value = BDM_FAULT_NOERROR; /* target is now halted */ + break; + } + bdm_delay(bdm_min_dly); + } + +#ifdef DEB_TIM +printk("bdm_icd_stop_chip: having waited for FREEZE %d loops\n", + BDM_WAITCNT-bdm_ctr); +#endif + + if (!bdm_ctr) { +#if 1 + bdm_out_data(BDMICD_RST_OUT | BDMICD_FORCE_BERR, descr); +#else + bdm_out_data(BDMICD_DSCLK | BDMICD_RST_OUT | BDMICD_FORCE_BERR, descr); +#endif + bdm_delay(bdm_min_dly); + for (bdm_ctr = BDM_WAITCNT; bdm_ctr; bdm_ctr--) { + if ((bdm_in_st(descr)) & BDMICD_FREEZE) { + return_value = BDM_FAULT_NOERROR; /* target is now halted */ + break; + } + bdm_delay(bdm_min_dly); + } +#ifdef DEB_TIM +printk("bdm_icd_stop_chip: berr has been forced; wait time was: %d\n", + BDM_WAITCNT-bdm_ctr); +#endif + } + +#if 1 + bdm_out_data(BDMICD_RST_OUT, descr); + bdm_delay(bdm_short_dly); + bdm_out_data(BDMICD_RST_OUT | BDMICD_STEP_OUT, descr); +#else + bdm_out_data(BDMICD_DSCLK | BDMICD_RST_OUT | BDMICD_STEP_OUT, descr); +#endif + +#ifdef DEB_TIM +printk("bdm_icd_stop_chip: forcing DSCLK RST STEP\n"); +#endif + + if (!bdm_ctr) { + bdm_error(-BDM_FAULT_RESPONSE); + return -BDM_FAULT_RESPONSE; + } +#ifdef BDM_TRY_RESYNCHRO + descr->resynchro(descr); /* tries to find correct 17 bit boundary */ +#endif /* BDM_TRY_RESYNCHRO */ + return return_value; +} + + + +/* single stepping target mcu */ +static int +bdm_icd_step_chip(bdm_descr_t * descr) +{ + int tester; + unsigned short DataOut = (BDM_GO_CMD & 1 ? BDMICD_DSI : 0); + + status_bitset bdm_stat = descr->getstatus(descr); + + if (bdm_debug_level >= BDM_DEBUG_SOME) { + printk("bdm_icd_step_chip minor=%d\n", descr->minor); + } + + /* first two conditions will not be detected on ICD... */ + if (bdm_stat & BDM_TARGETRESET) { + bdm_error(-BDM_FAULT_RESET); + return -BDM_FAULT_RESET; + } + if (bdm_stat & BDM_TARGETNC) { + bdm_error(-BDM_FAULT_CABLE); + return -BDM_FAULT_CABLE; + } + if (bdm_stat & BDM_TARGETPOWER) { + bdm_error(-BDM_FAULT_POWER); + return -BDM_FAULT_POWER; + } + tester = descr->ser_clk(descr, BDM_GO_CMD, 1); + switch (tester) { + case -BDM_FAULT_RESET: + case -BDM_FAULT_CABLE: + case -BDM_FAULT_POWER: + return tester; + } + if (bdm_debug_level >= BDM_DEBUG_ALL) { + printk("stepchip sent: %x got : %x\n", + BDM_GO_CMD, (unsigned int) tester); + printk("last answerbit : %x\n", !(bdm_in_st(descr) & BDMICD_DSO)); + } + bdm_out_data(BDMICD_OE | BDMICD_STEP_OUT | DataOut | BDMICD_RST_OUT, descr); + bdm_delay(bdm_norm_dly); + bdm_out_data(BDMICD_OE | DataOut | BDMICD_RST_OUT, descr); + bdm_delay(bdm_min_dly); + bdm_out_data(BDMICD_DSCLK | DataOut | BDMICD_RST_OUT, descr); + +#ifdef BDM_TRY_RESYNCHRO + descr->stop_chip(descr); + return descr->resynchro(descr); +#else /* BDM_TRY_RESYNCHRO */ + return descr->stop_chip(descr); +#endif /* BDM_TRY_RESYNCHRO */ +} + +/* reset target chip without asserting freeze */ +static int +bdm_icd_release_chip(bdm_descr_t * descr) +{ + if (bdm_debug_level >= BDM_DEBUG_SOME) { + printk("bdm_icd_release_chip minor=%d\n", descr->minor); + } + + bdm_out_data(BDMICD_DSCLK | BDMICD_STEP_OUT, descr); + bdm_delay(bdm_norm_dly); + bdm_out_data(BDMICD_DSCLK | BDMICD_RST_OUT | BDMICD_STEP_OUT, descr); + bdm_delay(bdm_short_dly); + + return BDM_FAULT_NOERROR; +} + +/* + * Restart chip, enable background debugging mode, halt on first fetch + * + * The software from the Motorola BBS tries to have the target + * chip begin execution, but that doesn't work very reliably. + * The RESETH* line rises rather slowly, so sometimes the BKPT* / DSCLK + * would be seen low, and sometimes it wouldn't. + */ +static int +bdm_icd_reset_chip(bdm_descr_t * descr) +{ + if (bdm_debug_level >= BDM_DEBUG_SOME) { + printk("bdm_icd_reset_chip minor=%d\n", descr->minor); + } + + /* this is according to Scott Howard */ + bdm_out_data(BDMICD_DSCLK | BDMICD_STEP_OUT, descr); + bdm_delay(bdm_norm_dly+bdm_reset_dly); + bdm_out_data(BDMICD_DSCLK | BDMICD_STEP_OUT | BDMICD_RST_OUT, descr); + bdm_delay(bdm_norm_dly+bdm_reset_dly); + + /* + *Tom Hoover's Error or Optimization? has to be checked + * FIXME... with scope; kick out if unnecessary. + */ + bdm_out_data(BDMICD_DSCLK, descr); + bdm_delay(bdm_norm_dly+1000); + /* + descr->stop_chip(descr); + */ + return BDM_FAULT_NOERROR; +} + +/* serial software protokoll for bdm-icd-interface */ +static int +bdm_icd_ser_clk(bdm_descr_t * descr, short bdm_value, int delay_bits) +{ + unsigned int ShiftRegister; + unsigned char DataOut; + unsigned counter; + unsigned bdm_stat = descr->getstatus(descr); + + if (bdm_debug_level >= BDM_DEBUG_ALL) { + printk("icd_ser_clk: in-val %x delay %d\n", + (unsigned short) bdm_value, delay_bits); + } + + ShiftRegister = bdm_value; + ShiftRegister <<= BITS; + /* first two conditions will not be detected on ICD... */ + if (bdm_stat & BDM_TARGETRESET) { /*error checking */ + bdm_error(-BDM_FAULT_RESET); + return -BDM_FAULT_RESET; + } + if (bdm_stat & BDM_TARGETNC) { + bdm_error(-BDM_FAULT_CABLE); + return -BDM_FAULT_CABLE; + } + if (bdm_stat & BDM_TARGETPOWER) { + bdm_error(-BDM_FAULT_POWER); + return -BDM_FAULT_POWER; + } + if(!(bdm_stat & BDM_TARGETSTOPPED)) + { if (bdm_debug_level >= BDM_DEBUG_SOME) + printk("bdm_ser_clk stop target first minor=%d\n", descr->minor); + if(descr->stop_chip(descr)==-BDM_FAULT_RESPONSE) + { printk("bdm_ser_clk can't stop it minor=%d\n", descr->minor); + return -BDM_FAULT_RESPONSE; + } + } + if(bdm_no_ser_dly_mode && (delay_bits&SER_CLK_DSO_WAIT)) + { /* Wait for DSO to become 0 to indicate ready + * according CPU32UM, DSO is updated as long as + * DSCLK is high + */ + int wait_cnt; + for(wait_cnt=0;wait_cnt<100;wait_cnt++) + { if (bdm_in_st(descr) & BDMICD_DSO) + break; /* DSO becomed zerro already */ + bdm_delay(bdm_min_dly); + } + if(wait_cnt && (bdm_debug_level >= BDM_DEBUG_SOME)) + printk("bdm_icd_ser_clk: ready after %d cycles\n", + wait_cnt); + } + + counter = 32 - BITS - (delay_bits&0xff); + if (bdm_debug_level >= BDM_DEBUG_ALL) { + printk("bdm_icd_ser_clk: writing %x\n", bdm_value); + } + while (counter--) { + DataOut = ((ShiftRegister & 0x80000000) ? BDMICD_DSI : 0); + /*if 1 then DSI=1*/ + bdm_out_data(DataOut | BDMICD_RST_OUT | BDMICD_OE | BDMICD_STEP_OUT | + BDMICD_LED, descr); /* DSCLK=0 */ + if(!bdm_no_ser_dly_mode) + bdm_delay(bdm_norm_dly); + + ShiftRegister <<= 1; /*shift one bit left*/ + if (!(bdm_in_st(descr) & BDMICD_DSO)) + ShiftRegister |= 1; /*put 1 on 0.bit */ + bdm_out_data(DataOut | BDMICD_RST_OUT | BDMICD_OE | BDMICD_STEP_OUT | + BDMICD_DSCLK | BDMICD_LED, descr); /* DSCLK=1 */ + if(!bdm_no_ser_dly_mode) + bdm_delay(bdm_half_dly); + } + if ((delay_bits&0xff) == 0) { + bdm_out_data(BDMICD_DSCLK | BDMICD_STEP_OUT | BDMICD_RST_OUT, + descr); + bdm_delay(bdm_min_dly); + } + if (bdm_debug_level >= BDM_DEBUG_ALL) { + printk("icd_ser_clk: out-val %x delay %d\n", + (unsigned short) ShiftRegister, delay_bits); + } + + +#ifdef FIXME + if (!(delay_bits&0xff) && (ShiftRegister & 0x10000)) switch (ShiftRegister) { + case 0x1ffff: /* no valid command return */ + return -BDM_FAULT_NVC; + case 0x10001: + return -BDM_FAULT_BERR; + case 0x10000: + return BDM_NOTE_NOTREADY; + default: ; + } +#endif /* FIXME */ + return ShiftRegister; +} + +/* switch LED if available */ +static int +bdm_icd_setled(bdm_descr_t * descr, int switchstate) +{ + bdm_icd_led_status = (switchstate ? BDMICD_LED : 0); + bdm_out_data(BDMICD_STEP_OUT | BDMICD_DSCLK | BDMICD_RST_OUT | + bdm_icd_led_status, descr); + return BDM_FAULT_NOERROR; +} + +#endif + +static int bdm_minor_index[] = { +#ifdef PD_INTERFACE + 0, 1, 2, +#else + -1, -1, -1, +#endif + -1, +#ifdef ICD_INTERFACE + 3, 4, 5, +#else + -1, -1, -1, +#endif + -1, +#ifdef AS_INTERFACE + -1, -1, -1, +#else + -1, -1, -1, +#endif + -1 +}; +const int bdm_minor_index_size = + sizeof(bdm_minor_index)/sizeof(*bdm_minor_index); + +#define PD_DESCRIPTOR(adr,minor,name) \ + BDM_DESCR_MAGIC, adr, minor, \ + bdm_pd_init, bdm_pd_deinit, bdm_pd_getstatus,\ + bdm_pd_restart_chip, bdm_pd_release_chip, bdm_pd_stop_chip,\ + bdm_pd_step_chip, bdm_pd_reset_chip, bdm_pd_ser_clk,\ + bdm_pd_setled, bdm_pd_resynchro , name + +#define ICD_DESCRIPTOR(adr,minor,name) \ + BDM_DESCR_MAGIC, adr, minor, \ + bdm_icd_init, bdm_icd_deinit, bdm_icd_getstatus,\ + bdm_icd_restart_chip, bdm_icd_release_chip, bdm_icd_stop_chip,\ + bdm_icd_step_chip, bdm_icd_reset_chip, bdm_icd_ser_clk,\ + bdm_icd_setled, bdm_icd_resynchro , name + +#define EMPTY_DESCRIPTOR(adr,minor) \ + 0, adr, minor, \ + NULL, NULL, NULL, \ + NULL, NULL, NULL, \ + NULL, NULL, NULL, \ + NULL, NULL, NULL + +static bdm_descr_t bdm_driver_descriptors[] = { +#ifdef PD_INTERFACE + { PD_DESCRIPTOR(PORT_ADDRESSE_LP1,0,"pd0") }, + { PD_DESCRIPTOR(PORT_ADDRESSE_LP2,1,"pd1") }, + { PD_DESCRIPTOR(PORT_ADDRESSE_LP3,2,"pd2") }, +#else + { EMPTY_DESCRIPTOR(0,0) }, + { EMPTY_DESCRIPTOR(0,1) }, + { EMPTY_DESCRIPTOR(0,2) }, +#endif +#ifdef ICD_INTERFACE + { ICD_DESCRIPTOR(PORT_ADDRESSE_LP1,4,"icd0") }, + { ICD_DESCRIPTOR(PORT_ADDRESSE_LP2,5,"icd1") }, + { ICD_DESCRIPTOR(PORT_ADDRESSE_LP3,6,"icd2") }, +#else + { EMPTY_DESCRIPTOR(0,4) }, + { EMPTY_DESCRIPTOR(0,5) }, + { EMPTY_DESCRIPTOR(0,6) }, +#endif + { EMPTY_DESCRIPTOR(0,8) }, + { EMPTY_DESCRIPTOR(0,9) }, + { EMPTY_DESCRIPTOR(0,10) } +}; + +/* preparation macros to get minor descriptor */ + +#define check_descriptor(rdev, descr) \ +{\ + unsigned int minor; int descr_indx;\ + if ((minor = kc_dev2minor(rdev)) > bdm_minor_index_size) {\ + return -ENODEV;\ + } \ + if ((descr_indx = bdm_minor_index[minor]) < 0) {\ + return -ENODEV;\ + }\ + descr = &bdm_driver_descriptors[descr_indx];\ + if (descr->minor != minor) {\ + printk("Inconsistency: descr->minor %d, minor %d\n", descr->minor,\ + minor);\ + return -ENODEV;\ + }\ +} + +#define minor2descriptor(minor) \ + (&bdm_driver_descriptors[bdm_minor_index[(minor)]]) + +static bdm_descr_t *bdm_file2descr(const struct file *file) +{ + bdm_descr_t *descr = (bdm_descr_t *)(file->private_data); + if(descr==NULL){ + printk(KERN_CRIT "BDM no descriptor!!!\n"); + return NULL; + } + if(descr->magic!=BDM_DESCR_MAGIC){ + printk(KERN_CRIT "BDM wrong MAGIC number!!!\n"); + return NULL; + } + return descr; +} + +static int +bdm_open(struct inode *inode, struct file *file) +{ + status_bitset bdm_okay; + bdm_descr_t *descr; + int val; + #ifdef WITH_PARPORT_SUPPORT + static struct pardevice *parport; + #endif /* WITH_PARPORT_SUPPORT */ + + + check_descriptor(inode->i_rdev, descr); + + #ifndef WITH_PARPORT_SUPPORT + if (check_region(BDM_DATA(descr), 3)) { + printk("bdm_open: address space in use (conflict with PARPORT ?)...\n"); + return -EBUSY; + request_region(BDM_DATA(descr), 3, "bdm"); + } + #else /* WITH_PARPORT_SUPPORT */ + parport=bdm_get_parport(descr); + if(!parport) + return -ENODEV; + if(parport_claim(parport)) { + printk("bdm_open: no access to PARPORT device"); + return -EBUSY; + } + #endif /* WITH_PARPORT_SUPPORT */ + /* stupid test if required port is really available */ + val=bdm_in_data(descr); + val&=~0x21; + bdm_out_data(val, descr); + if (bdm_in_data(descr) != val) { + printk("bdm_open: physical device not detected...\n"); + #ifdef WITH_PARPORT_SUPPORT + parport_release(bdm_get_parport(descr)); + #else + release_region(BDM_DATA(descr), 3); + #endif + return -ENODEV; + } + + kc_MOD_INC_USE_COUNT; + + file->private_data=descr; + + if (bdm_debug_level >= BDM_DEBUG_SOME) { + printk("bdm_open\n"); + } + + bdm_okay = descr->init(descr); + + if (bdm_debug_level >= BDM_DEBUG_SOME) { + if (!(bdm_okay & BDM_TARGETNC)) { + printk("BDM detected !!\n"); + } else { + printk("Target not connected ! Error %d \n", bdm_okay); + } + } + + if (bdm_debug_level >= BDM_DEBUG_SOME) { + printk("bdm_open successful\n"); + } + + return BDM_FAULT_NOERROR; +} + +static CLOSERET +bdm_release(struct inode *inode, struct file *file) +{ + bdm_descr_t *descr = bdm_file2descr(file); + if(!descr) return -ENODEV; + + descr->deinit(descr); + if (bdm_debug_level >= BDM_DEBUG_SOME) { + printk("bdm_release\n"); + } + + file->private_data=NULL; + kc_MOD_DEC_USE_COUNT; +#ifdef WITH_PARPORT_SUPPORT + parport_release(bdm_get_parport(descr)); +#else + release_region(BDM_DATA(descr), 3); +#endif + return (CLOSERET)0; +} + +static int +bdm_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) +{ + unsigned retval = BDM_FAULT_NOERROR; + status_bitset status; + bdm_descr_t *descr = bdm_file2descr(file); + if(!descr) return -ENODEV; + + if (bdm_debug_level >= BDM_DEBUG_SOME) { + printk("bdm_ioctl minor=%d cmd=%d (%s) arg=0x%lx\n", + descr->minor, cmd, bdm_get_ioctl_name(cmd), arg); + } + switch (cmd) { + case BDM_INIT: + status = descr->init(descr); + if (status & BDM_TARGETNC) + retval = -BDM_FAULT_CABLE; + else if (status & BDM_TARGETPOWER) + retval = -BDM_FAULT_POWER; + break; + case BDM_DEINIT: + retval = descr->deinit(descr); + break; + case BDM_RESET_CHIP: + retval = descr->reset_chip(descr); + /* hardware reset on MCU - running state */ + break; + case BDM_RESTART_CHIP: + /* reset target and stops execution on first instruction fetch */ + retval = descr->restart_chip(descr); + break; + case BDM_STOP_CHIP: + /* stop running target (FREEZE) */ + retval = descr->stop_chip(descr); + break; + case BDM_STEP_CHIP: + /* one step on target */ + descr->step_chip(descr); + retval = BDM_FAULT_NOERROR; + break; + case BDM_GET_STATUS: + retval = descr->getstatus(descr); + break; + case BDM_SPEED: + /* Change speed value */ + if ((int) arg <= 0) { + if(bdm_debug_level >= BDM_DEBUG_SOME) + printk("bdm_ioctl BDM_SPEED: no_ser_dly_mode=1\n"); + bdm_no_ser_dly_mode = 1; + bdm_norm_dly = 1; + } else { + bdm_no_ser_dly_mode = 0; + bdm_norm_dly = (int) arg; + } + bdm_long_dly = BDM_LONG_DLY(bdm_norm_dly); + bdm_half_dly = BDM_HALF_DLY(bdm_norm_dly); + bdm_short_dly = BDM_SHORT_DLY(bdm_norm_dly); + bdm_min_dly = BDM_MIN_DLY(bdm_norm_dly); + if (bdm_debug_level >= BDM_DEBUG_SOME) { + printk("bdm_ioctl SPEED: " + "norm %d long %d half %d short %d min %d\n", + bdm_norm_dly, bdm_long_dly, bdm_half_dly, bdm_short_dly, + bdm_min_dly); + } + break; + case BDM_RELEASE_CHIP: + /* reset without bdm, so quit bdm mode */ + retval = descr->release_chip(descr); + break; + case BDM_DEBUG_LEVEL: + /* change debug level 0,1,2 */ + if (arg < 3) { + bdm_debug_level = (unsigned int) arg; + } else { + retval = -EINVAL; + } + break; + case BDM_GET_VERSION: + /* read counter and return it to *arg */ + if(kc_put_user_long(bdm_version, arg)) + retval = -EINVAL; + break; + case BDM_SENSECABLE: + bdm_sense = arg; + if (bdm_debug_level >= BDM_DEBUG_SOME) { + printk("bdm_ioctl: setting bdm_sense to %d\n", bdm_sense); + } + break; + case BDM_RESPW: + /* reset additional delay */ + bdm_reset_dly = (unsigned int) arg; + if (bdm_debug_level >= BDM_DEBUG_SOME) { + printk("bdm_ioctl: setting reset_pw to %d\n", bdm_reset_dly); + } + break; + case BDM_SETLED: + retval = descr->set_led(descr,arg); + break; +#ifdef EFIICDISP + +#define BDMICD_ispSCLK 1 /* ctrl-Register; clock data to isp */ +#define BDMICD_ispSDI 8 /* ctrl-Register; data line to isp */ +#define BDMICD_ispMODE 0x80 /* data-Register; mode for ips */ +#define BDMICD_ispSDO 0x20 /* stat-Register; data line from isp */ + case BDM_ISPSET: + { + static char ispcmd=0, ispdata=0; + switch(arg & 0xf) { + case BDM_ispSDI: +/* #define ISPVERBOSE 1 */ + if (bdm_debug_level >= BDM_DEBUG_ALL) { + printk("ispSDI "); + } + if (arg & BDM_isp_LEVEL) { /* neg. output */ + ispcmd &= ~BDMICD_ispSDI; + if (bdm_debug_level >= BDM_DEBUG_ALL) { + printk("1\n"); + } + } else { + ispcmd |= BDMICD_ispSDI; + if (bdm_debug_level >= BDM_DEBUG_ALL) { + printk("0\n"); + } + } + bdm_out_ctl(ispcmd, descr); + break; + case BDM_ispSCLK: + if (bdm_debug_level >= BDM_DEBUG_ALL) { + printk("ispSCLK "); + } + if (arg & BDM_isp_LEVEL) { /* neg. output */ + ispcmd &= ~BDMICD_ispSCLK; + if (bdm_debug_level >= BDM_DEBUG_ALL) { + printk("1\n"); + } + } else { + ispcmd |= BDMICD_ispSCLK; + if (bdm_debug_level >= BDM_DEBUG_ALL) { + printk("0\n"); + } + } + bdm_out_ctl(ispcmd, descr); + break; + case BDM_ispMODE: + if (bdm_debug_level >= BDM_DEBUG_ALL) { + printk("ispMODE "); + } + if (arg & BDM_isp_LEVEL) { + ispdata |= BDMICD_ispMODE; + if (bdm_debug_level >= BDM_DEBUG_ALL) { + printk("1\n"); + } + } else { + ispdata &= ~BDMICD_ispMODE; + if (bdm_debug_level >= BDM_DEBUG_ALL) { + printk("0\n"); + } + } + bdm_out_data(ispdata, descr); + break; + case BDM_ispISP: + /* ignore */ + break; + } + udelay(100); + /* this is necessary to mimic the bdm_delay factor for isp */ + break; + } + case BDM_ISPGET: + if (bdm_in_st(descr) & BDMICD_ispSDO) { + retval = 1; + } else { + retval = 0; + } + if (bdm_debug_level >= BDM_DEBUG_ALL) { + printk("ispSDO %d\n", retval); + } + break; +#endif + default: + retval = -EINVAL; + } + return retval; +} + + + +static RWRET +bdm_write(WRITE_PARAMETERS) +{ + short bdm_word; + int ret; + int written = 0; + bdm_descr_t *descr = bdm_file2descr(file); + if(!descr) return -ENODEV; + + if (bdm_debug_level >= BDM_DEBUG_SOME) { + printk("bdm_write minor %d len %d\n", descr->minor, (int)count); + } + if (!access_ok(VERIFY_READ, buf, count)) + return -EINVAL; + + while (count > 0) { + bdm_word = 0; + kc_get_user_word(bdm_word, buf); + ret = descr->ser_clk(descr, bdm_word, 0); + if (bdm_debug_level >= BDM_DEBUG_ALL) { + printk("bdm_write sent: %x received: %x\n", + bdm_word, (unsigned int) ret); + } + if (written) { + switch (ret) { + case 0x1ffff: /* no valid command return */ + return -BDM_FAULT_NVC; + case 0x10001: /* Buserror */ + return -BDM_FAULT_BERR; + case -BDM_FAULT_RESET: + case -BDM_FAULT_CABLE: + case -BDM_FAULT_POWER: + return ret; + } + } + count -= 2; + buf += 2; + written += 2; + if (!(written % BYTECOUNT_FOR_BEING_NICE)) { + schedule(); + } + } + return written; +} + +static RWRET +bdm_read(READ_PARAMETERS) +{ + short bdm_word = BDM_NOP_CMD, value; + int ret; + int read = 0, timeout = 0; + bdm_descr_t *descr = bdm_file2descr(file); + if(!descr) return -ENODEV; + + if (bdm_debug_level >= BDM_DEBUG_SOME) { + printk("bdm_read minor=%d len=%d\n", descr->minor, (int)count); + } + if (!access_ok(VERIFY_WRITE, buf, count)) + return -EINVAL; + + while (count > 0) { + ret = descr->ser_clk(descr, bdm_word, SER_CLK_DSO_WAIT); + + if (bdm_debug_level >= BDM_DEBUG_ALL) { + printk("\n read sent: %x received: %x\n", + bdm_word, (unsigned int) ret); + } + switch (ret) { + case 0x10001: /* test if BERR*/ + return -BDM_FAULT_BERR; + case 0x1ffff: /* no valid command return */ + return -BDM_FAULT_NVC; + case 0x10000: + timeout++; + if (timeout - read / 2 > 4) { + /* + * we assume the FAULT_RESPONSE error, if number of + * failed attempts is by 4 higher than number of + * successful attempts + */ + return -BDM_FAULT_RESPONSE; + } + break; + case -BDM_FAULT_RESET: + case -BDM_FAULT_CABLE: + case -BDM_FAULT_POWER: + return ret; + default: + value = ret; + kc_put_user_word(value, buf); + buf += 2; + count -= 2; + read += 2; + if (!(read % BYTECOUNT_FOR_BEING_NICE)) { + schedule(); + } + } + + } + return read; +} + +/* static struct file_operations bdm_fops */ +KC_CHRDEV_FOPS_BEG(bdm_fops) + KC_FOPS_LSEEK(NULL) /* lseek */ + read:bdm_read, /* read */ + write:bdm_write, /* write */ + readdir:NULL, /* readdir */ + poll:NULL, /* poll/select */ + ioctl:bdm_ioctl, /* ioctl */ + mmap:NULL, /* mmap */ + open:bdm_open, /* open */ + KC_FOPS_FLUSH(NULL) /* flush */ + KC_FOPS_RELEASE(bdm_release) /* release */ + fsync:NULL, /* fsync */ + fasync:NULL, /* fasync */ + NULL, /* check_media_change */ + NULL, /* revalidate */ +KC_CHRDEV_FOPS_END; + +struct kc_class *bdm_class; + +#ifdef WITH_PARPORT_SUPPORT +static int +bdm_preempt(void *handle) +{ + return 1; // 1=don't release parport +} +#endif + + +int +init_module(void) +{ + int i; +#ifdef WITH_PARPORT_SUPPORT + int num; + struct parport *port; + int num_offset=0; +#endif + + printk("BDM init_module\n %s\n %s\n %s\n", + "$RCSfile: bdm.c,v $", "$Revision: 1.8 $", "$Date: 2006/12/28 13:04:58 $"); + /*"$Id: bdm.c,v 1.8 2006/12/28 13:04:58 ppisa Exp $", */ + printk(" Version %s\n Compiled at %s %s\n", +#ifdef PD_INTERFACE + "PD " +#endif +#ifdef ICD_INTERFACE + "ICD " +#ifdef EFIICDISP + "+ISP" +#endif + " " +#endif + "", __DATE__, __TIME__); + +#ifdef WITH_PARPORT_SUPPORT + printk("BDM init_module: compiled with PARPORT support\n"); + for(num=0; num < MAX_BDM_PORTS; num++) + { + port=NULL; + do{ + if(num+num_offset >= PARPORT_MAX) break; + port=parport_find_number(num+num_offset); + if(port) break; + num_offset++; + }while(1); + if(!port) break; + bdm_parports[num] = parport_register_device(port, "bdm", bdm_preempt, NULL, NULL,0,NULL); + if (!bdm_parports[num]){ + printk("BDM init_module: Can't register device no.: %d",num); + } + parport_put_port(port); + } +#endif + +#ifndef BDM_WITH_DEVFS + if (register_chrdev(BDM_MAJOR_NUMBER, "bdm", &bdm_fops)) { + printk("Unable to get major number for BDM driver\n"); + return -EIO; + } +#else /* BDM_WITH_DEVFS */ + if (devfs_register_chrdev(BDM_MAJOR_NUMBER, "bdm", &bdm_fops)) { + printk("Unable to get major number for BDM driver\n"); + return -EIO; + } + /* I hate next conditional compilation, but k_compat.h can not handle + latest changes to devfs done by Adam J. Richter . */ + #if (LINUX_VERSION_CODE >= VERSION(2,5,60)) + #if (LINUX_VERSION_CODE < VERSION(2,6,17)) + devfs_mk_dir (BDM_DEVFS_DIR_NAME); + #endif /* < 2.6.17 */ + bdm_class = kc_class_create(THIS_MODULE, BDM_DEVFS_DIR_NAME); + for(i=0;iname) continue; + /*sprintf(dev_name, "%s/%s", BDM_DEVFS_DIR_NAME, minor2descriptor(i)->name);*/ + #if (LINUX_VERSION_CODE < VERSION(2,6,17)) + devfs_mk_cdev(MKDEV(BDM_MAJOR_NUMBER, i), S_IFCHR | S_IRUGO | S_IWUGO, + "%s/%s", BDM_DEVFS_DIR_NAME, minor2descriptor(i)->name); + #endif /* < 2.6.17 */ + kc_class_device_create(bdm_class, NULL, MKDEV(BDM_MAJOR_NUMBER, i), NULL, minor2descriptor(i)->name); + } + #else /* < 2.5.60 */ + bdm_devfs_handle = devfs_mk_dir (NULL, BDM_DEVFS_DIR_NAME, NULL); + for(i=0;iname) continue; + devfs_register(bdm_devfs_handle, minor2descriptor(i)->name, + DEVFS_FL_DEFAULT, BDM_MAJOR_NUMBER, i, + S_IFCHR | S_IRUGO | S_IWUGO , + &bdm_fops, NULL); + } + #endif /* 2.5.60 */ +#endif /* BDM_WITH_DEVFS */ + printk("BDM driver succesfully registered !!\n"); + return 0; +} + +void +cleanup_module(void) +{ +#ifdef WITH_PARPORT_SUPPORT + int num; +#endif + +#ifdef WITH_PARPORT_SUPPORT + printk("BDM init_module: compiled with PARPORT support\n"); + for(num=0; num < MAX_BDM_PORTS; num++) + { + if (bdm_parports[num]) + parport_unregister_device(bdm_parports[num]); + bdm_parports[num] = NULL; + } +#endif +#ifdef BDM_WITH_DEVFS + /* I hate next conditional compilation, but k_compat.h can not handle + latest changes to devfs done by Adam J. Richter . */ + #if (LINUX_VERSION_CODE >= VERSION(2,5,60)) + { + int i; + for(i=0;iname) continue; + kc_class_device_destroy(bdm_class, MKDEV(BDM_MAJOR_NUMBER, i)); + #if (LINUX_VERSION_CODE < VERSION(2,6,17)) + devfs_remove("%s/%s", BDM_DEVFS_DIR_NAME, minor2descriptor(i)->name); + #endif /* < 2.6.17 */ + } + } + #if (LINUX_VERSION_CODE < VERSION(2,6,17)) + devfs_remove(BDM_DEVFS_DIR_NAME); + #endif /* < 2.6.17 */ + kc_class_destroy(bdm_class); + #else /* < 2.5.60 */ + if(bdm_devfs_handle) + devfs_unregister (bdm_devfs_handle); + #endif /* < 2.5.60 */ + if (devfs_unregister_chrdev(BDM_MAJOR_NUMBER, "bdm") != 0) +#else /* BDM_WITH_DEVFS */ + if (unregister_chrdev(BDM_MAJOR_NUMBER, "bdm") != 0) +#endif /* BDM_WITH_DEVFS */ + printk("BDM cleanup: Unregister failed\n"); + else + printk("BDM cleanup: Unregister O.K.\n"); +} diff --git a/m683xx/bdm-driver/bdm.h b/m683xx/bdm-driver/bdm.h new file mode 100644 index 0000000..797d520 --- /dev/null +++ b/m683xx/bdm-driver/bdm.h @@ -0,0 +1,126 @@ +#ifndef LINUX_BDM_H +#define LINUX_BDM_H +/* + * $Id: bdm.h,v 1.1 2003/06/04 01:31:31 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_NOERROR 0 /* no error, no ret value */ +#define BDM_FAULT_UNKNOWN 610 +#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_RESPW 12 /* arg = width */ +#define BDM_SETLED 13 /* arg = 0-off 1-on */ +#define BDM_ISPSET 50 /* arg = which pin + which level */ +#define BDM_ISPGET 51 /* no argument */ + +/* bits for efiicdbdm isp programming */ +#define BDM_ispSDI 1 +#define BDM_ispSCLK 2 +#define BDM_ispMODE 3 +#define BDM_ispISP 4 +#define BDM_isp_LEVEL 0x80 + +/* 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 --git a/m683xx/bdm-driver/bdmlib.h b/m683xx/bdm-driver/bdmlib.h new file mode 100644 index 0000000..7db7ec4 --- /dev/null +++ b/m683xx/bdm-driver/bdmlib.h @@ -0,0 +1,56 @@ +/* + * $Id: bdmlib.h,v 1.1 2003/06/04 01:31:31 ppisa Exp $ + */ + +#include +#include +#include + +typedef u_short bdmstatus; + +extern unsigned int bdmlib_delay, bdmlib_respw; + +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, u_long *entry_pt); +extern int bdmlib_do_load_binary(char *file_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_get_mbar(u_int, u_int *); +extern int bdmlib_set_mbar(u_int, u_int); +extern int bdmlib_go(void); +extern char *bdmlib_geterror_str(int); +extern char *bdmlib_getstatus_str(bdmstatus); +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(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 + diff --git a/m683xx/bdm-driver/conf.modules b/m683xx/bdm-driver/conf.modules new file mode 100644 index 0000000..68a88dd --- /dev/null +++ b/m683xx/bdm-driver/conf.modules @@ -0,0 +1,9 @@ +# +alias char-major-9 st +alias char-major-27 ftape +# alias char-major-30 oldbdm +# now obsolete +alias char-major-53 m683xx-bdm +alias sl0 slhc +alias eth0 wd +options wd irq=5 io=0x300 diff --git a/m683xx/bdm-driver/k_compat.h b/m683xx/bdm-driver/k_compat.h new file mode 100644 index 0000000..28f8cc7 --- /dev/null +++ b/m683xx/bdm-driver/k_compat.h @@ -0,0 +1,436 @@ +/* + * k_compat.h 1.8 1995/12/03 01:26:43 (David Hinds) + * 1998/07/12 modified by Pavel Pisa pisa@CMP.felk.cvut.cz + */ + +#ifndef _LINUX_K_COMPAT_H +#define _LINUX_K_COMPAT_H + +#define VERSION(v,p,s) (((v)<<16)+(p<<8)+s) + +#ifndef LINUX_VERSION_CODE + #error LINUX_VERSION_CODE not defined +#endif + +#if (LINUX_VERSION_CODE < VERSION(1,3,38)) + +#ifdef MODULE +#include +#if !defined(CONFIG_MODVERSIONS) && !defined(__NO_VERSION__) +char kernel_version[] = UTS_RELEASE; +#endif +#else +#define MOD_DEC_USE_COUNT +#define MOD_INC_USE_COUNT +#endif + +#else /* 1.3.38 */ + +#if (LINUX_VERSION_CODE <= VERSION(2,5,60)) +#ifdef CONFIG_MODVERSIONS +#define MODVERSIONS 1 +#if (LINUX_VERSION_CODE >= VERSION(1,3,40)) +#include +#endif /* >=1.3.40 */ +#endif /* CONFIG_MODVERSIONS */ +#endif /* <=2.5.60 */ + +#include + +#endif /* 1.3.38 */ + +#if (LINUX_VERSION_CODE < VERSION(2,5,50)) +#define kc_MOD_DEC_USE_COUNT MOD_DEC_USE_COUNT +#define kc_MOD_INC_USE_COUNT MOD_INC_USE_COUNT +#else /* 2.5.50 */ +#define kc_MOD_DEC_USE_COUNT +#define kc_MOD_INC_USE_COUNT +#endif /* 2.5.50 */ + +#if ((LINUX_VERSION_CODE < VERSION(2,2,0)) || (LINUX_VERSION_CODE >= VERSION(2,6,0))) + #ifndef EXPORT_NO_SYMBOLS + #define EXPORT_NO_SYMBOLS + #endif /*EXPORT_NO_SYMBOLS*/ +#endif /* 2.2.0 */ + +/*** user memory access ***/ + +/* I do not know exactly all dates of changes */ + +#if (LINUX_VERSION_CODE < VERSION(2,1,5)) + #define kc_copy_from_user(dst,src,len) ({ \ + if(!(verify_area(VERIFY_READ, src, len))) \ + {memcpy_fromfs(dst,src,len);0;} else len; }) + #define kc_copy_to_user(dst,src,len) ({ \ + if(!(verify_area(VERIFY_WRITE, dst, len))) \ + {memcpy_tofs(dst,src,len);0;} else len; }) + #define kc_get_user_long(x,ptr) \ + (if(!verify_area(VERIFY_READ, (ptr), sizeof(long))) {(x)=get_fs_long((ptr));0;} else 1; }) + #define kc_get_user_word(x,ptr) \ + (if(!verify_area(VERIFY_READ, (ptr), sizeof(short))) {(x)=get_fs_word((ptr));0;} else 1; }) + #define kc_get_user_byte(x,ptr) \ + (if(!verify_area(VERIFY_READ, (ptr), sizeof(char))) {(x)=get_fs_byte((ptr));0;} else 1; }) + #define kc_put_user_long(x,ptr) \ + (if(!verify_area(VERIFY_WRITE, (ptr), sizeof(long))) {put_fs_long((x),(ptr));0;} else 1; }) + #define kc_put_user_word(x,ptr) \ + (if(!verify_area(VERIFY_WRITE, (ptr), sizeof(short))){put_fs_word((x),(ptr));0;} else 1; }) + #define kc_put_user_byte(x,ptr) \ + (if(!verify_area(VERIFY_WRITE, (ptr), sizeof(char))) {put_fs_byte((x),(ptr));0;} else 1; }) +#elif (LINUX_VERSION_CODE < VERSION(2,1,100)) /* may need correction */ + #include + #define kc_copy_from_user copy_from_user + #define kc_copy_to_user copy_to_user + #define kc_get_user(x,ptr) \ + (__get_user_check((x),(ptr),sizeof(*(ptr)))) + #define kc_put_user(x,ptr) \ + (__put_user_check((x),(ptr),sizeof(*(ptr)))) +#else /* >= 2.1.100 */ + #include + #define kc_copy_from_user copy_from_user + #define kc_copy_to_user copy_to_user + #define kc_get_user(x,ptr) \ + (get_user((x),(ptr))) + #define kc_put_user(x,ptr) \ + (put_user((x),(ptr))) +#endif /* < 2.1.100 */ + +#if (LINUX_VERSION_CODE >= VERSION(2,1,5)) + #define kc_get_user_long(x,ptr) (kc_get_user((x),(long*)(ptr))) + #define kc_get_user_word(x,ptr) (kc_get_user((x),(unsigned short*)(ptr))) + #define kc_get_user_byte(x,ptr) (kc_get_user((x),(unsigned char*)(ptr))) + #define kc_put_user_long(x,ptr) (kc_put_user((x),(long *)(ptr))) + #define kc_put_user_word(x,ptr) (kc_put_user((x),(unsigned short*)(ptr))) + #define kc_put_user_byte(x,ptr) (kc_put_user((x),(unsigned char*)(ptr))) +#endif /* >= 2.1.5 */ + +/*** resource manipulation changes ***/ + +#if (LINUX_VERSION_CODE >= VERSION(2,4,0)) + #define kc_request_region request_region + #define kc_release_region release_region +#else /* < 2.6.0 */ + #define kc_request_region(start,len,name) \ + ({ unsigned long kc_t_start=(start), kc_t_len=(len); \ + int kc_t_res=!check_region(kc_t_start,kc_t_len); \ + if(kc_t_res) request_region(kc_t_start,kc_t_len,name); \ + kc_t_res; \ + }) + #define kc_release_region release_region +#endif /* < 2.6.0 */ + +/*** bitops changes ***/ + +#if (LINUX_VERSION_CODE < VERSION(2,1,36)) /* may need correction */ + #define test_and_set_bit set_bit +#endif + +/*** interrupt related stuff ***/ + +#if (LINUX_VERSION_CODE < VERSION(2,1,36)) /* may need correction */ + #define kc_synchronize_irq(irqnum) do{cli();sti();}while(0) +#elif (LINUX_VERSION_CODE < VERSION(2,5,33)) /* may need correction */ + #define kc_synchronize_irq(irqnum) synchronize_irq() +#else /* >=2.5.33 */ + #define kc_synchronize_irq synchronize_irq +#endif + +#if (LINUX_VERSION_CODE <= VERSION(2,5,67)) && !defined(IRQ_RETVAL) + typedef void irqreturn_t; + #define IRQ_NONE + #define IRQ_HANDLED + #define IRQ_RETVAL(x) +#endif /* <=2.5.67 */ + +#if (LINUX_VERSION_CODE <= VERSION(2,6,18)) + #define KC_IRQ_HANDLER_ARGS(intno, dev_id) \ + int intno, void *dev_id, struct pt_regs *regs +#else /* <=2.6.18 */ + #define KC_IRQ_HANDLER_ARGS(intno, dev_id) \ + int intno, void *dev_id +#endif /* <=2.6.18 */ + +/*** timming related stuff ***/ + +#if (LINUX_VERSION_CODE < VERSION(2,1,100)) /* needs correction */ + #define schedule_timeout(timeout_jif) ({ \ + current->timeout = jiffies + (timeout_jif); \ + schedule(); \ + current->timeout = 0; \ + }) + + #ifndef set_current_state + #define set_current_state(state_value) do { current->state = state_value; } while (0) + #endif +#endif + +#if (LINUX_VERSION_CODE < VERSION(2,1,36)) /* needs correction */ + #define mod_timer(timer,expires) ({\ + del_timer(timer); \ + timer->expires=expires; \ + add_timer(timer); \ + }) +#endif + +/*** file_operations changes ***/ + +#if (LINUX_VERSION_CODE < VERSION(2,1,5)) + #define CLOSERET void + #define RWRET int + #define RWCOUNT_T int + #define RWINODE_P struct inode *inode, + #define RWPPOS_P + #define RWINODE inode + #define KC_FOPS_FLUSH(ptr) + #define kc_dev2minor MINOR +#elif (LINUX_VERSION_CODE < VERSION(2,1,36)) + #define CLOSERET void + #define RWRET long + #define RWCOUNT_T unsigned long + #define RWINODE_P struct inode *inode, + #define RWPPOS_P + #define RWINODE inode + #define KC_FOPS_FLUSH(ptr) + #define kc_dev2minor MINOR +#elif (LINUX_VERSION_CODE < VERSION(2,1,76)) /* may need correction */ + #define CLOSERET int + #define RWRET long + #define RWCOUNT_T unsigned long + #define RWINODE_P struct inode *inode, + #define RWPPOS_P + #define RWINODE inode + #define KC_FOPS_FLUSH(ptr) + #define kc_dev2minor MINOR +#elif (LINUX_VERSION_CODE < VERSION(2,1,117)) /* may need correction */ + #define CLOSERET int + #define RWRET ssize_t + #define RWCOUNT_T size_t + #define RWINODE_P + #define RWPPOS_P ,loff_t *ppos + #define RWINODE file->f_dentry->d_inode + #define KC_FOPS_FLUSH(ptr) + #define kc_dev2minor MINOR +#elif ((LINUX_VERSION_CODE >= VERSION(2,5,7)) && (LINUX_VERSION_CODE < VERSION(2,6,0))) + #define CLOSERET int + #define RWRET ssize_t + #define RWCOUNT_T size_t + #define RWINODE_P + #define RWPPOS_P ,loff_t *ppos + #define RWINODE file->f_dentry->d_inode + #define KC_FOPS_FLUSH(ptr) flush:(ptr), + #define kc_dev2minor minor +#else /* <2.5.7 >=2.6.0 */ /* may need correction */ + #define CLOSERET int + #define RWRET ssize_t + #define RWCOUNT_T size_t + #define RWINODE_P + #define RWPPOS_P ,loff_t *ppos + #define RWINODE file->f_dentry->d_inode + #define KC_FOPS_FLUSH(ptr) flush:(ptr), + #define kc_dev2minor MINOR +#endif /* 2.1.36 */ + +#if (LINUX_VERSION_CODE < VERSION(2,1,50)) /* may need correction */ + #define kc_poll_wait(file,address,wait) poll_wait(address,wait) +#else /* >= 2.1.50 */ + #define kc_poll_wait poll_wait +#endif /* 2.1.50 */ + +/* definition of standard parameters for read/write file functions */ +#define READ_PARAMETERS \ + RWINODE_P struct file *file, char *buf, RWCOUNT_T count RWPPOS_P + +#define WRITE_PARAMETERS \ + RWINODE_P struct file *file, const char *buf, RWCOUNT_T count RWPPOS_P + +#define LSEEK_PARAMETERS \ + RWINODE_P struct file *file, loff_t pos, int whence + +#if (LINUX_VERSION_CODE < VERSION(2,2,0)) /* may need correction */ + #define KC_CHRDEV_FOPS_BEG(fops_var) \ + static struct file_operations fops_var =\ + { + #define KC_CHRDEV_FOPS_END \ + } + #define KC_FOPS_LSEEK(ptr) lseek:(ptr), + #define KC_FOPS_RELEASE(ptr) close:(ptr), +#elif (LINUX_VERSION_CODE < VERSION(2,4,0)) /* may need correction */ + #define KC_CHRDEV_FOPS_BEG(fops_var) \ + static struct file_operations fops_var =\ + { + #define KC_CHRDEV_FOPS_END \ + } + #define KC_FOPS_LSEEK(ptr) llseek:(ptr), + #define KC_FOPS_RELEASE(ptr) release:(ptr), +#else /* >= 2.4.0 */ + #define KC_CHRDEV_FOPS_BEG(fops_var) \ + static struct file_operations fops_var = {\ + owner:THIS_MODULE, + #define KC_CHRDEV_FOPS_END \ + } + #define KC_FOPS_LSEEK(ptr) llseek:(ptr), + #define KC_FOPS_RELEASE(ptr) release:(ptr), +#endif /* 2.4.0 */ + +/*** devices and drivers registration ***/ + +#if (LINUX_VERSION_CODE >= VERSION(2,5,41)) /* may need correction */ + #define devfs_register_chrdev register_chrdev + #define devfs_unregister_chrdev unregister_chrdev +#endif /* 2.5.40 */ + +#if (LINUX_VERSION_CODE >= VERSION(2,5,60)) /* may need correction */ + #define kc_devfs_handle_t char * + #define kc_devfs_delete(handle) ({ devfs_remove(handle); kfree(handle); }) + + #define kc_devfs_new_cdev(dir_handle, dev_num, dev_mode, dev_ops, dev_info, dev_name) ({ \ + char *kc_t_name; \ + const char *kc_t_dev=(dev_name); \ + const char *kc_t_dir=(dir_handle); \ + const int kc_t_d=kc_t_dir?strlen(kc_t_dir)+1:0; \ + int kc_t_n=strlen(kc_t_dev)+1+kc_t_d; \ + if ((kc_t_name=kmalloc(kc_t_n,GFP_KERNEL))) { \ + if(kc_t_d) {memcpy(kc_t_name,kc_t_dir,kc_t_d-1); kc_t_name[kc_t_d-1]='/';} \ + strcpy(kc_t_name+kc_t_d,kc_t_dev); \ + if(devfs_mk_cdev((dev_num), (dev_mode), kc_t_name)<0) { \ + kfree(kc_t_name); \ + kc_t_name = NULL ; \ + } \ + } \ + kc_t_name; \ + }) + + #define kc_devfs_mk_dir devfs_mk_dir +#else /* 2.5.60 */ + #define kc_devfs_handle_t devfs_handle_t + #define kc_devfs_delete devfs_unregister + + #define kc_devfs_new_cdev(dir_handle, dev_num, dev_mode, dev_ops, dev_info, dev_name) ({ \ + devfs_register((dir_handle), (dev_name), DEVFS_FL_DEFAULT, \ + MAJOR(dev_num), MINOR(dev_num), (dev_mode), (dev_ops), (dev_info)); \ + }) + + #define kc_devfs_mk_dir(dirname...) ({ \ + char kc_buf[64]; int kc_n; \ + kc_n = snprintf(buf, 64, ##dirname); \ + (kc_n >= 64 || !buf[0])? NULL: devfs_mk_dir(NULL, kc_buf, NULL); \ + }) + +#endif /* 2.5.60 */ + +#if (LINUX_VERSION_CODE <= VERSION(2,6,0)) + typedef struct {int dummy;} kc_class; + #define kc_class_create(...) (NULL) + #define kc_class_device_create(...) + #define kc_class_device_destroy(...) + #define kc_class_destroy(...) +#else /* 2.6.0 */ + #define KC_WITH + #include + #if LINUX_VERSION_CODE >= VERSION(2,6,15) + #define kc_class class + #define kc_class_create class_create + #define kc_class_device_create class_device_create + #define kc_class_device_destroy class_device_destroy + #define kc_class_destroy class_destroy + #elif LINUX_VERSION_CODE >= VERSION(2,6,13) + #define kc_class class + #define kc_class_create class_create + #define kc_class_device_create(cls, parent, devt, device, fmt...) \ + class_device_create(cls, devt, device, ##fmt) + #define kc_class_device_destroy class_device_destroy + #define kc_class_destroy class_destroy + #else /* 2.6.0 ... 2.6.12 */ + #define kc_class class_simple + #define kc_class_create class_simple_create + #define kc_class_device_create(cls, parent, devt, device, fmt...) \ + class_simple_device_add(cls, devt, device, ##fmt) + #define kc_class_device_destroy(a,b) class_simple_device_remove(b) + #define kc_class_destroy class_simple_destroy + #endif + #define kc_pci_dev_to_dev(pdev) (&(pdev)->dev) + #define kc_usb_dev_to_dev(pdev) (&(pdev)->dev) +#endif + + +/*** tasklet declaration and processing ***/ + +#if (LINUX_VERSION_CODE < VERSION(2,5,0)) /* may need correction */ + #define kc_tasklet_struct tq_struct + #define kc_tasklet_data_type void * + #define KC_DECLARE_TASKLET(_name, _func, _data) \ + struct tq_struct _name = { sync: 0, routine: _func, data: (void*)_data } + + /* void tasklet_init(struct tasklet_struct *t, void (*func)(unsigned long), unsigned long data); */ + #define kc_tasklet_init(_tasklet, _func, _data) \ + do{ \ + /* (_tasklet)->next=NULL; */ \ + /* Above not needed for 2.2.x and buggy for 2.4.x */ \ + (_tasklet)->sync=0; \ + (_tasklet)->routine=_func; \ + (_tasklet)->data=(void*)_data; \ + }while(0) + + /* void tasklet_schedule(struct tasklet_struct *t) */ + #define kc_tasklet_schedule(_tasklet) \ + do{ \ + queue_task(_tasklet,&tq_immediate); \ + mark_bh(IMMEDIATE_BH); \ + }while(0) + + /* void tasklet_kill(struct tasklet_struct *t); */ + #define kc_tasklet_kill(_tasklet) \ + synchronize_irq() + +#else /* 2.5.40 */ + /* struct tasklet_struct */ + #define kc_tasklet_struct tasklet_struct + /* DECLARE_TASKLET(name, func, data) */ + #define kc_tasklet_data_type unsigned long + #define KC_DECLARE_TASKLET DECLARE_TASKLET + /* void tasklet_init(struct tasklet_struct *t, void (*func)(unsigned long), unsigned long data); */ + #define kc_tasklet_init tasklet_init + /* void tasklet_schedule(struct tasklet_struct *t) */ + #define kc_tasklet_schedule tasklet_schedule + /* void tasklet_kill(struct tasklet_struct *t); */ + #define kc_tasklet_kill tasklet_kill +#endif /* 2.5.40 */ + +/*** scheduler changes ***/ + +#if (LINUX_VERSION_CODE < VERSION(2,3,0)) /* may need correction */ + #define kc_yield schedule +#else /* 2.3.0 */ + #define kc_yield yield +#endif /* 2.3.0 */ + +/*** PCI changes ***/ + +#if (LINUX_VERSION_CODE < VERSION(2,6,11)) /* may need correction */ + #define kc_pci_name(pdev) (pdev->slot_name) +#else /* 2.6.11 */ + #define kc_pci_name pci_name +#endif /* 2.6.11 */ + +/*** wait queues changes ***/ + +/* Next is not sctrictly correct, because of 2.3.0, 2.3.1, 2.3.2 + probably need next definitions */ +#if (LINUX_VERSION_CODE < VERSION(2,2,19)) /* may need correction */ + #define wait_queue_head_t struct wait_queue * + #define wait_queue_t struct wait_queue + #define init_waitqueue_head(queue_head) (*queue_head=NULL) + #define init_waitqueue_entry(qentry,qtask) \ + (qentry->next=NULL,qentry->task=qtask) + #define DECLARE_WAIT_QUEUE_HEAD(name) \ + struct wait_queue * name=NULL + #define DECLARE_WAITQUEUE(wait, current) \ + struct wait_queue wait = { current, NULL } + #define init_MUTEX(sem) (*sem=MUTEX) + #define DECLARE_MUTEX(name) struct semaphore name=MUTEX +#endif /* 2.2.19 */ + +#ifndef MODULE_LICENSE + #define MODULE_LICENSE(dummy) +#endif /* MODULE_LICENSE */ + +#endif /* _LINUX_K_COMPAT_H */ diff --git a/m683xx/bdm-load/Makefile b/m683xx/bdm-load/Makefile new file mode 100644 index 0000000..1673e62 --- /dev/null +++ b/m683xx/bdm-load/Makefile @@ -0,0 +1,33 @@ +#TARGET_ARCH = -bi586-pc-linux-gnulibc1 +#CC = egcc + +CFLAGS += -Wall -ggdb -O2 +CFLAGS += -Wstrict-prototypes +CFLAGS += ${TARGET_ARCH} + +#/* Select right place or libraries with configured m68k-coff support */ +LDLIBS += -lbfd +#CFLAGS += -I ./gdblibs +#LOCLIBS += ./gdblibs/libbfd.a ./gdblibs/libiberty.a +#LDFLAGS += -lintl +LDLIBS += -liberty +LDFLAGS += ${TARGET_ARCH} + +all : bdm-load bdm_test tpudb + +dep: + $(CC) $(CFLAGS) $(CPPFLAGS) -w -E -M *.c $(MORE_C_FILES) > depend + +depend: + @touch depend + +clean : + rm -f *.o *.lo *~ *.a *.so *.so.* depend + +bdm-load : bdm-load.o bdmlib.o bdmflash.o ${LOCLIBS} + +bdm_test : bdm_test.o bdmlib.o ${LOCLIBS} + +tpudb : tpudb.o bdmlib.o tpudis.o ${LOCLIBS} + +-include depend diff --git a/m683xx/bdm-load/README b/m683xx/bdm-load/README new file mode 100644 index 0000000..2fdd31f --- /dev/null +++ b/m683xx/bdm-load/README @@ -0,0 +1,188 @@ + BDM-LOAD snapshot 2003-08-15 + +This is attempt to rewrite bdm-load utility for 683xx based +embedded systems. + +This code is in experimental and rewrite phase, it works for me, +but there is no warranty that it is useful or safe for others. + +Except "bdm-load" program, two test utilities are build. +It is "bdm_test" program. It was my first experiment with +interfacing BDM library with stand-alone program. +The second project is to write free TPU debugger, but this +code does not do anything useful yet. + +INSTALL + +To compile and install "bdm-load" you need: + - mc683xx target system with BDM interface + - GCC compiler for your Linux system. + - BDM driver - latest version is attached into "bdm-load" archive + - BFD object file handling library + - some time and experience with Linux system and make utility + +To be able load other formats than S-record and IntelHEX, you +need to link with BFD library with m68kcoff and/or m68kelf +targets. I have system wide BFD with all targets I use. +I build my Linux binutils configured by next line in created +source tree subdirectory i586-linux + +---System wide multi binutils configuration----------------------- +../configure \ + --with-ld --exec-prefix=/usr --prefix=/usr \ + --enable-shared --enable-commonbfdlib --verbose --with-mmap \ + --enable-targets=i586-pc-linux-gnulibc1,i386-a.out-linux,i386-coff,\ + m68k-linux-elf,m68k-coff,m68k-a.out-linux,h8300-hitachi-coff,\ + sparc-linux-elf,i586-win-pe,tic30-ti-coff,tic30-ti-aout +------------------------------------------------------------------ + +You need not to rebuild your system wide BFD. You can statically link +with "libbfd.a", "libiberty.a" and "bfd.h" taken, for example, +from GDB build tree configured for m68k-coff. Configuration of GDB +is bellow + +---GDB for m683xx with BDM configuration-------------------------- +../configure --target=m68k-bdm-coff --enable-gdbtk --with-x --verbose \ + --enable-targets=m68k-linux-elf,m68k-coff,m68k-a.out-linux +------------------------------------------------------------------ + +To compile statically copy three needed files to gdblibs subdirectory +and change next lines in "Makefile" to form + +CFLAGS += -I ./gdblibs +#LDFLAGS += -lbfd -liberty +LOCLIBS += ./gdblibs/libbfd.a ./gdblibs/libiberty.a + +Prebuild version of "bdm-load" is attached to archive under name +"bdm-load-i586-linux-static". + +PROGRAMMERS NOTES + +Sources of "bdm-load" are in next files + + bdmlib.c,bdmlib.h library for communication with CPU32 + through BDM + + bdmflash.c,bdmflash.h flash write and erase algorithms and + flash areas write filter routines + + bdm-load.c loader command line and interactive + interface + +It is necessary to add new entries into array flash_alg_infos_def +in "bdmflash.c" file for every new flash programming algorithm. +Flash types should be sorted from smallest to biggest. + +RUNNING BDM-LOAD + +Command line interface + +Usage bdm-load [OPTIONS] file1 ... + -h --help - this help information! + -i --init-file=FILE - object file to initialize processor + -r --reset - reset target CPU before other operations + -c --check - check flash setup (needed for auto) + -e --erase - erase flash + -b --blankck - blank check of flash + -l --load - download listed filenames + --go[=address] - run target CPU from entry address + -M --mbar=val - setup 68360 MBAR register + -s --script - do actions and return + -d --bdm-delay=d - sets BDM driver speed/delay + -D --bdm-device - sets BDM device file + -f --flash=TYPE@ADR - select flash +For flash TYPE@ADR can be + {|auto}[@{csboot|cs|{+|-}}] +Examples + auto@csboot amd29f400@0x800000-0x87ffff auto@0+0x80000 +If auto type or cs address is used, check must be +specified to take effect. +Known flash types/algorithms : + amd29f010x2 amd29f040 amd29f400 amd29f800 at49f040x2 amd29f080x4 + +Possible commands in interactive mode : + - run + starts CPU32 execution at address taken from last downloaded + object file. If no file is loaded, it starts at address + fetched during last reset command. + + - reset + resets CPU32 and if no entry address is defined, PC address is + remembered + + - erase + sets erase request and starts erase procedure + + -load [] + sets load request and starts download of files from + object file list. + if is specified, object file list is cleared + and specified file is added on-to list + + - exit/quit + exit interactive mode and return to shell + + - dump
+ dumps memory contents from specified address. + bytes specifies number of bytes to print. + + - stat + shows CPU32 state, does not require CPU32 to stop + + - check + checks flash memories at specified ranges, + if auto type or "cs" address is specified for some + flash, CS address is fetched and flash autodetection + is run + + - autoset + same as check, but all flash types are revalidated + + - stop + stops CPU32 and clears all reset, erase, load and run + requests + + - make + make in current directory is called + + +The simplest way to initialize CPU32 chipselect subsystem +and other SIM parameters is to provide "cpu32init" file +in same directory as "bdm-load" is started from. +The "cpu32init" file is processed at every reset of target. +The syntax of the macro file is: + + + +The nums are either in hex (form 0x), in decimal (form 123) or in octal +(form 0234) + +The meaning of the nums depends on the command letter: + +w or W means: (write) + + write to address (num1) contents (num2) length is (num3) bytes. Only + 1, 2, 4 bytes are permitted. + +z or Z means: (zap, zero) + + fill memory area beginning at (num1) with byte value (num2) length + (num3) bytes. + +c or C means: (copy) + + copy memory area from (num1) to (num2) with length (num3) bytes. + +m or M is new command to set 68360 MBAR register. + + the MBAR register is set to value of (num3) + +Empty lines and lines with a leading '#' are ignored. See GDB-BDM +patches for more information. + + +For more questions contact + + Pavel Pisa + + diff --git a/m683xx/bdm-load/bdm-load.c b/m683xx/bdm-load/bdm-load.c new file mode 100644 index 0000000..80de958 --- /dev/null +++ b/m683xx/bdm-load/bdm-load.c @@ -0,0 +1,903 @@ +/* + * Adapted from.... + * + * Remote debugging interface for 683xx via Background Debug Mode + * needs a driver, which controls the BDM interface. + * written by G.Magin + * (C) 1995 Technische Universitaet Muenchen, Lehrstuhl fuer Prozessrechner + * + * D.Jeff Dionne + * (C) 1995, Dionne & Associates + * + * V0.2 Enhancements: + * Added command line arguments + * Rewritten flash programming functions for more flexability + * + * Andrew Dennison + * December 1995 + * + * Modified by Pavel Pisa pisa@cmp.felk.cvut.cz 2000 + +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. + + */ + +/* + * 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. + * + * 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 + +#include +#include "bdm.h" +#include "bdmlib.h" +#include "bdmflash.h" + +/* + * Global Types + ************** + */ +typedef caddr_t CORE_ADDR; + +#define END_MACRO 0 +#define BEGIN_MACRO 1 +#define NO_SUFFIX_MACRO 2 +#define DEBUG_MESSAGES + +#define swap_l(x) (x>>24) | ((x>>8)&0xff00) | ((x<<8)&0xff0000) | ((x&0xff)<<24) + +#define AUTO_ADR_CSBOOT ((caddr_t)-100) +#define AUTO_ADR_CSX ((caddr_t)-100+1) + +typedef struct str_list_t{ + char **items; + int count; + int alloccnt; +}str_list_t; /* to store list of filenames */ + +/* + * Global Variables + ****************** + */ + +char hashmark = 0; /* flag set by "set hash" */ +int bdm_autoreset = 0; /* automatic reset before load */ +int bdm_ttcu = 0; /* time to come up for init by rom */ +char *initname; /* need reimplement !!!!!!!!! */ +char *bdm_dev_name; /* device name */ +static char *entry_name=NULL; + +int +mem_dump (char *buf) +{ + caddr_t adr; + long len, l; + int i, ret; + u_char mem[16]; + char *dump_fname = NULL; + FILE *dump_file = NULL; + i = sscanf (buf, " %li %li %as", &l, &len, &dump_fname); + if (i < 2) + { + printf ("use : dump address len [file]\n"); + return -1; + } + if(dump_fname && *dump_fname) + { dump_file=fopen(dump_fname,"wb"); + if(dump_file==NULL) + { + printf ("mem_dump : file \"%s\" open for write error\n", dump_fname); + free(dump_fname); + return -1; + } + free(dump_fname); + } + + adr = (caddr_t) l; + while (len) + { + l = len > 16 ? 16 : len; + ret = bdmlib_read_block (adr, l, mem); + if (ret != l) + { + printf ("error to read 0x%lx len 0x%lx ret %d\n", + (u_long) adr, l, ret); + if(dump_file!=NULL) + fclose(dump_file); + return -2; + } + printf ("%06lx:", (u_long) adr); + for (i = 0; i < l; i++) + printf (" %02x", mem[i]); + printf ("\n"); + if(dump_file!=NULL) + fwrite(mem, l, 1, dump_file); + len -= l; + adr += l; + } + if(dump_file!=NULL) + fclose(dump_file); + return 0; +} + +int +mem_modify (char *buf) +{ + int ret; + char *p; + long addr; + long count=0; + long capacity=0; + u_char *data=NULL; + u_char val; + + while(*buf&&!isblank(*buf)) buf++; + while(*buf&&isblank(*buf)) buf++; + if(!*buf) + { usage_error: + if(data) free(data); + printf ("use : modify address byte1 byte2 ...\n"); + return -1; + } + addr=strtol(buf,&p,0); + if(p==buf) goto usage_error; + buf=p; + capacity=128; + data=malloc(capacity); + while(*buf&&isblank(*buf)) buf++; + while(*buf){ + val=strtol(buf,&p,0); + if(p==buf) goto usage_error; + buf=p; + if(count>=capacity){ + capacity*=2; + data=realloc(data,capacity); + if(!data) goto usage_error; + } + data[count++]=val; + while(*buf&&isblank(*buf)) buf++; + } + + ret=bdmlib_wrb_filt(bdmlib_bfilt, (caddr_t)addr, count, data); + //if(ret!=count) + printf("bdmlib_wrb_filt: addr=0x%08lx count=%ld return=%ld\n", + (long)addr,(long)count,(long)ret); + + if(data) free(data); + return ret; +} + +int +cpu_get_rpc(u_int32_t *val) +{ + int ret; + u_int32_t rpc; + if ((ret = bdmlib_get_sys_reg (BDM_REG_RPC, &rpc)) < 0) + return ret; + *val=swap_l(rpc); + return 0; +} + +int +cpu_stat (char *buf) +{ + int ret; + u_int32_t rpc; + ret = bdmlib_getstatus (); + printf ("MCU "); + if (ret & BDM_TARGETRESET) + printf ("Reset "); + if (ret & BDM_TARGETSTOPPED) + printf ("Stopped "); + if (ret & BDM_TARGETPOWER) + printf ("NoPower "); + if (ret & BDM_TARGETNC) + printf ("NoConnect "); + printf ("\n"); + if (ret & BDM_TARGETSTOPPED) + { + if ((ret = cpu_get_rpc (&rpc)) < 0) + return ret; + printf ("RPC=%x\n",rpc); + } + return 0; +} + +int +flash_check_one (bdmlib_bfilt_t *filt, int autoset) +{ + flash_alg_info_t const *alg; + caddr_t adr; + flash_d_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 ("Flash addresses taken from CSBOOT\n"); + else + printf ("Flash addresses taken from CS%d\n", + (int)(adr-AUTO_ADR_CSX)); + printf ("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; + printf ("Flash@%06lX-%06lX ManID %08X DevID %08X\n", + (long) adr, (long) filt->end_adr, + (unsigned) readid[0], (unsigned) readid[1]); + if (ret >= 0) + { + printf ("Flash ID is OK\nUsed algorithm %s\n", alg->alg_name); + return 1; + } + if (!autoset & 2) + { + printf ("Flash parameters are incorrect !!!\n"); + return -1; + } + alg = bdmflash_alg_probe (adr); + if (alg == NULL) + { + printf ("Flash parameters cannot be probed\n"); + return -1; + } + ret = bdmflash_check_id (alg, adr, readid); + if (ret < 0) + { + printf ("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; + printf ("Probed flash parameters\n"); + printf ("Flash@%06lX-%06lX ManID %04X DevID %04X\n", + (long) filt->begin_adr, (long) filt->end_adr, + (unsigned) readid[0], (unsigned) readid[1]); + printf ("Used algorithm %s\n", alg->alg_name); + + return 1; +} + +int +flash_check(char *buf, int autoset) +{ + int ret; + bdmlib_bfilt_t *filt = bdmlib_bfilt; + printf("\n"); + while(filt) + { + if(filt->flags&BDMLIB_FILT_FLASH) + { + ret=flash_check_one(filt,autoset); + printf("\n"); + if(ret<0) + return ret; + } + filt=filt->next; + } + return 0; +} + +int +flash_erase(void) +{ + 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) + return ret; + } + filt=filt->next; + } + return 0; +} + +int +flash_blankck(void) +{ + int ret,sum=0; + bdmlib_bfilt_t *filt = bdmlib_bfilt; + while(filt) + { + if(filt->flags&BDMLIB_FILT_FLASH) + { + ret=bdmflash_blankck_filt (filt, (caddr_t) 0, 0); + if(ret<0) + return ret; + sum+=ret; + } + filt=filt->next; + } + return sum; +} + +/* bdmlib_propeller(stdout); */ + +int +flash_setup(char *buf) +{ + 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; + + 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)){ + fprintf(stderr,"%s : bad chipselect format\n",buf); + return -1; + } + p=r; + }else{ /* take begin address after '@' */ + end_adr=begin_adr=(caddr_t)strtoul(p,&r,0); + if(p==r){ + fprintf(stderr,"%s : bad begin address format\n",buf); + return -1; + } + p=r; + if(*p=='+'){ /* take end address from size */ + end_adr=begin_adr+strtoul(++p,&r,0)-1; + if(p==r){ + fprintf(stderr,"%s : bad size format\n",buf); + return -1; + } + p=r; + } else if(*p=='-') { /* take absolute end address */ + end_adr=(caddr_t)strtoul(++p,&r,0); + if(p==r){ + fprintf(stderr,"%s : bad end address format\n",buf); + return -1; + } + p=r; + } + } + while(*buf&&isblank(*buf)) buf++; + if(*p){ + fprintf(stderr,"%s : extra characters in specification %s\n",buf,p); + return -1; + } + } + 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){ + fprintf(stderr,"%s : unknown flash type or algorithm\n",alg_name); + return -1; + } + }while(strcmp(alg_name,alg->alg_name)); + } + + filt=(bdmlib_bfilt_t*)malloc(sizeof(bdmlib_bfilt_t)); + if(filt==NULL){ + fprintf(stderr,"No memory for flash_setup\n"); + return -1; + } + + 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=1; + filt->wrb_filt=&bdmflash_wrb_filt; + + filt->next=bdmlib_bfilt; + bdmlib_bfilt=filt; + return 0; +} + +int +str_list_add(str_list_t *list, char *str) +{ + char **p; + int a; + if(list->count>=list->alloccnt) + { + a=list->alloccnt+5; + if(list->items==NULL) + p=(char**)malloc(sizeof(char *)*a); + else + p=(char**)realloc(list->items,sizeof(char *)*a); + if(p==NULL) return -1; + list->items=p; + list->alloccnt=a; + } + list->items[list->count++]=str; + return list->count; +} + +void str_list_clear(str_list_t *list) +{ + while(list->count--) + { + if(list->items[list->count]!=NULL) + free(list->items[list->count]); + } + list->alloccnt=list->count=0; + if(list->items!=NULL) free(list->items); + list->items=NULL; +} + +/* + * Main Program + ************** + */ +int +main (int argc, char *argv[]) +{ + int done; + int error; + int ret; + static int print_help = 0; /* Help */ + static int reset = 0; /* Reset target */ + static int check = 0; /* Check flash configuration */ + static int erase = 0; /* Erase flash */ + static int blankck = 0; /* Check, that flash is blank */ + static int load = 0; /* Load files to flash */ + static int run = 0; /* Run target from entry point */ + static int script = 0; /* Batch mode */ + static int bdm_delay = 0; /* Delay/speed for BDM driver */ + static int set_mbar_fl = 0; /* Set MBAR requested */ + static u_long mbar_val = 0; + static u_long entry_pt=0; + str_list_t files2load={0,}; /* List of filenames to load */ + int cmd; + char buf[255]; + char *p; + int i; + + /* initialize global flash control variables */ + initname = strdup ("ram_init.srec"); /* default init file for EFI332 */ + + /* initialize name of bdm device */ + bdm_dev_name = strdup ("/dev/bdm"); + + /* start bdmlib debugging */ + bdmlib_setdebug (0); + + /* Parse arguments and options. Taken from GDB. */ + { + int c; + /* When var field is 0, use flag field to record the equivalent + short option (or arbitrary numbers starting at 10 for those + with no equivalent). */ + static struct option long_options[] = + { + {"help", no_argument, &print_help, 1}, + {"h", no_argument, &print_help, 1}, + {"flash", required_argument, 0, 'f'}, + {"f", required_argument, 0, 'f'}, + {"init-file", required_argument, 0, 'i'}, + {"i", required_argument, 0, 'i'}, + {"reset", no_argument, &reset, 1}, + {"r", no_argument, &reset, 1}, + {"check", no_argument, &check, 1}, + {"c", no_argument, &check, 1}, + {"erase", no_argument, &erase, 1}, + {"e", no_argument, &erase, 1}, + {"blankck", no_argument, &blankck, 1}, + {"b", no_argument, &blankck, 1}, + {"load", no_argument, &load, 1}, + {"l", no_argument, &load, 1}, + {"go", optional_argument, NULL, 'g'}, + {"g", no_argument, &run, 1}, + {"mbar", required_argument, NULL, 'M'}, + {"M", required_argument, NULL, 'M'}, + {"script", no_argument, &script, 1}, + {"s", no_argument, &script, 1}, + {"bdm-delay", required_argument, 0, 'd'}, + {"d", required_argument, 0, 'd'}, + {"bdm-device", required_argument, 0, 'D'}, + {"D", required_argument, 0, 'D'}, + {0, no_argument, 0, 0} + }; + + while (1) + { + int option_index; + + c = getopt_long_only (argc, argv, "", + long_options, &option_index); + if (c == EOF) + break; + + /* Long option that takes an argument. */ + if (c == 0 && long_options[option_index].flag == 0) + c = long_options[option_index].val; + + switch (c) + { + case 0: + /* Long option that just sets a flag. */ + break; + case 'f': + /* Setup flash region */ + if(flash_setup(optarg)<0) + exit(1); + break; + case 'g': + /* Run target from default or optional entry point */ + run=1; + if (optarg) { + if (entry_name) free (entry_name); + entry_name = strdup (optarg); + } + break; + case 'M': + /* Set MBAR register */ + mbar_val=strtoul(optarg,&p,0); + set_mbar_fl=1; + if(optarg==p){ + fprintf(stderr,"%s: bad numeric format for MBAR\n",argv[0]); + exit(1); + } + break; + case 'D': + if (bdm_dev_name) + free (bdm_dev_name); + bdm_dev_name = strdup (optarg); + break; + case 'i': + /* Init File */ + if(initname) + free(initname); + initname = strdup (optarg); + break; + case 'd': + /* BDM driver delay */ + bdm_delay=strtol(optarg,&p,0); + if(optarg==p){ + fprintf(stderr,"%s: bad numeric format for BDM delay\n",argv[0]); + exit(1); + } + break; + case '?': + fprintf(stderr, + "Use `%s --help' for a complete list of options.\n", + argv[0]); + exit (1); + } + } + } + + if(print_help) + { + printf ("Usage bdm-load [OPTIONS] file1 ...\n" + "\t-h --help - this help information!\n" + "\t-i --init-file=FILE - object file to initialize processor\n" + "\t-r --reset - reset target CPU before other operations\n" + "\t-c --check - check flash setup (needed for auto)\n" + "\t-e --erase - erase flash\n" + "\t-b --blankck - blank check of flash\n" + "\t-l --load - download listed filenames\n" + "\t --go[=address] - run target CPU from entry address\n" + "\t-M --mbar=val - setup 68360 MBAR register\n" + "\t-s --script - do actions and return\n" + "\t-d --bdm-delay=d - sets BDM driver speed/delay\n" + "\t-D --bdm-device - sets BDM device file\n" + "\t-f --flash=TYPE@ADR - select flash\n" + "For flash TYPE@ADR can be\n" + " {|auto}[@{csboot|cs|{+|-}}]\n" + "Examples\n" + " auto@csboot amd29f400@0x800000-0x87ffff auto@0+0x80000\n" + "If auto type or cs address is used, check must be\n" + "specified to take effect.\n" + "Known flash types/algorithms :\n"); + for(i=0;flash_alg_infos[i]!=NULL;i++) + printf(" %s",flash_alg_infos[i]->alg_name); + printf("\n\n"); + exit (0); + } + + while(optind0) + bdmlib_do_load_macro (files2load.items[0], BEGIN_MACRO); + + done = cmd = 0; + + do + { + error = 0; + if (reset) + { + /* bdmlib_init(); */ + if(bdmlib_reset()<0) + { + printf ("Reset Failed\n"); + error=4; + } + else + { + if(cpu_stat(NULL)<0) + { + printf ("CPU Stat Failed\n"); + error=4; + } + else + { + u_int32_t rpc; + reset = 0; + if(entry_pt==0) + { + cpu_get_rpc (&rpc); + entry_pt=rpc; + } + } + } + } + + if (check && !error) + { + if(flash_check(NULL,0)<0) + { + printf ("Flash Check Failed\n"); + error=3; + } + else + check = 0; + } + + if (erase && !error) + { + printf ("Erasing Flash..."); + fflush (stdout); + if (flash_erase() >= 0) + { + printf ("done.\n"); + erase = 0; + } + else + { + printf ("Erase Failed\n"); + error = 2; + } + } + + if (blankck && !error) + { + int res; + printf ("Flash blank check ...\n"); + res=flash_blankck(); + if(!res){ + printf("Flash blank check OK\n"); + blankck = 0; + }else{ + error = 5; + if(res<0) printf("Flash blank check FAILED\n"); + else printf("Flash is NOT erased\n"); + } + } + + if (load && !error) + { + bdmlib_load_use_lma = 1; + for(i=0;i ", ++cmd); + fgets (buf, 250, stdin); + + if (!strncmp (buf, "run", 3)) + { + run = 1; + } + + if (!strncmp (buf, "reset", 5)) + { + reset = 1; + } + + if (!strncmp (buf, "erase", 5)) + erase = 1; + + if (!strncmp (buf, "blankck", 5)) + blankck = 1; + + if (!strncmp (buf, "load", 4)) + { + load = 1; + if ((strlen (buf) > 5)) + { + str_list_clear(&files2load); + str_list_add(&files2load,strdup(&buf[5])); + } + } + + if (!strncmp (buf, "exit", 4) || !strncmp (buf, "quit", 4)) + done = 1; + + if (!strncmp (buf, "dump", 4)) + mem_dump (buf + 4); + + if (!strncmp (buf, "modify", 3)) + mem_modify (buf + 3); + + if (!strncmp (buf, "stat", 4)) + cpu_stat (buf + 4); + + if (!strncmp (buf, "check", 5)) + flash_check (buf + 5, 0); + + if (!strncmp (buf, "autoset", 5)) + flash_check (buf + 5, 0xff); + + if (!strncmp (buf, "stop", 5)) + { + bdmlib_ioctl(BDM_STOP_CHIP); + reset=check=erase=blankck=load=run=0; + } + + if (!strncmp (buf, "make", 4)) + system (buf); + + if (!strncmp (buf, "help", 4) || !strncmp (buf, "?", 1)) + { + printf("Next commands are accepted :\n"\ + " run - enable full speed ran of target CPU\n"\ + " stop - stop target CPU\n"\ + " reset - reset target\n"\ + " erase - erase all configured FLASH chips\n"\ + " blankck - check blank state of chips\n"\ + " load - loand all object files specified\n"\ + " at command line to RAM or FLASH\n"\ + " using VMA addresses, name of file to\n"\ + " can be optionaly specified after \"load\"\n"\ + " dump - dump target memory\n"\ + " modify ... - modify target memory (even flash)\n"\ + " state - print target status\n"\ + " check - check presence of configured chips\n"\ + " autoset - set FLASH chip types from their IDs\n"\ + " make - call make command in current directory\n"\ + " quit - leave loader\n"\ + ); + } + } + while (!done); + + str_list_clear(&files2load); + + exit (0); +} diff --git a/m683xx/bdm-load/bdm-load.lsm b/m683xx/bdm-load/bdm-load.lsm new file mode 100644 index 0000000..13da71b --- /dev/null +++ b/m683xx/bdm-load/bdm-load.lsm @@ -0,0 +1,25 @@ +Begin4 +Title: bdm-load +Version: 030815 +Entered-date: 2003-08-15 +Description: Flash writer utility for 683xx target systems through + Background Debug Mode interface for Motorola CPU32 and Linux + Both Public Domain and ICD interfaces are supported. + Code contains first experimental tests of GPLed TPU debugger + project. + * More info about related software and BDM driver at + http://cmp.felk.cvut.cz/~pisa + http://cmp.felk.cvut.cz/~pisa/m683xx/bdm_driver.html +Keywords: debugger GDB m68k 68332 683xx BDM flash embedded TPU +Author: jeff@uclinux.org (D.Jeff Dionne) + adennison@swin.edu.au (Andrew Dennison) + pisa@cvlinux.felk.cvut.cz (Pavel Pisa) +Maintained-by: pisa@cvlinux.felk.cvut.cz (Pavel Pisa) +Primary-site: metalab.unc.edu /pub/Linux/devel/debuggers + 210 kB bdm-load-030519.tar.gz +Alternate-site: ftp.cygnus.com /pub/embedded + 210 kB bdm-load-030519.tar.gz +Original-site: freeware.aus.sps.mot.com +Platforms: Linux 2.0.xx, 2.2.yy, 2.4.zz ( last tested 2.5.69 ) +Copying-policy: GPL +End diff --git a/m683xx/bdm-load/bdm.h b/m683xx/bdm-load/bdm.h new file mode 100644 index 0000000..d45e36a --- /dev/null +++ b/m683xx/bdm-load/bdm.h @@ -0,0 +1,115 @@ +#ifndef LINUX_BDM_H +#define LINUX_BDM_H +/* + * $Id: bdm.h,v 1.1 2003/06/04 01:31:32 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 --git a/m683xx/bdm-load/bdm_test.c b/m683xx/bdm-load/bdm_test.c new file mode 100644 index 0000000..640c23e --- /dev/null +++ b/m683xx/bdm-load/bdm_test.c @@ -0,0 +1,272 @@ + + +#include +#include +#include +#include +#include +#include +#include +#include "bdm.h" +#include "bdmlib.h" + +char* TestSW(int argc,char *argv[],char swch); + +#define swap_l(x) (x>>24) | ((x>>8)&0xff00) | ((x<<8)&0xff0000) | ((x&0xff)<<24) + +/* for BDMLIB to work */ +char hashmark; +int bdm_autoreset; +int bdm_ttcu; + +int bdm_step_chip() +{ + int ret; + u_int32_t rpc; + + if (!bdmlib_isopen()) + return BDM_ERR_NOT_OPEN; + + if (!(bdmlib_getstatus()&BDM_TARGETSTOPPED)) + if((ret=bdmlib_ioctl(BDM_STOP_CHIP)<0)) + {return ret;}; + + if((ret=bdmlib_get_sys_reg(BDM_REG_RPC, &rpc))<0) return ret; + printf("RPC=%x\n",swap_l(rpc)); + ret=bdmlib_ioctl(BDM_STEP_CHIP); + if((ret=bdmlib_get_sys_reg(BDM_REG_RPC, &rpc))<0) return ret; + printf("RPC=%x\n",swap_l(rpc)); + return ret; +} + +int bdm_show_regs(void) +{ + u_int reg; + if (!bdmlib_isopen()) + return BDM_ERR_NOT_OPEN; + + bdmlib_get_reg(BDM_REG_D0, ®); + return 0; +}; + + +int rd_test(void) +{ + u_int16_t val; + caddr_t adr=(caddr_t)0xFFAA; + int counter=0; + + if (!bdmlib_isopen()) + return BDM_ERR_NOT_OPEN; + while(1){ + if(bdmlib_read_var(adr,BDM_SIZE_WORD,&val)<0) + goto mem_op_error; + //usleep(1); + if(counter++>=10000){ + printf("."); + fflush(stdout); + counter=0; + } + } + return 0; + + mem_op_error: + printf("Memory read error\n"); + return -1; +}; + +int wr_test(void) +{ + u_int16_t val=0xAAAA; + caddr_t adr=(caddr_t)0xFFAA; + int counter=0; + + if (!bdmlib_isopen()) + return BDM_ERR_NOT_OPEN; + while(1){ + if(bdmlib_write_var(adr,BDM_SIZE_WORD,val)<0) + goto mem_op_error; + //usleep(1); + if(counter++>=10000){ + printf("."); + fflush(stdout); + counter=0; + } + } + return 0; + + mem_op_error: + printf("Memory write error\n"); + return -1; +}; + + +int step_test(void) +{ + int counter=0; + + if (!bdmlib_isopen()) + return BDM_ERR_NOT_OPEN; + while(1){ + if(bdmlib_ioctl(BDM_STEP_CHIP)<0) + goto step_op_error; + usleep(1); + if(counter++>=10000){ + printf("."); + fflush(stdout); + counter=0; + } + } + return 0; + + step_op_error: + printf("Stepping error\n"); + return -1; +}; + + +int main(int argc, char *argv[]) +{ + int quit_fl=0; + int ret; + char c; + char *p; + char file_name[100]=""; + char bdm_dev_name[100]="/dev/bdm"; + unsigned long entry_pt=0; + + bdmlib_setdebug(1); + if((p=TestSW(argc,argv,'D'))!=NULL) + strncpy(bdm_dev_name,p,sizeof(bdm_dev_name)); + if((ret=bdmlib_open(bdm_dev_name))<0) + { printf("bdmlib_open : %s\n",bdmlib_geterror_str(ret)); return 1; }; + bdmlib_setioctl(BDM_SPEED,0); + + if((p=TestSW(argc,argv,'F'))!=NULL) + { + strncpy(file_name,p,sizeof(file_name)); + bdmlib_setioctl(BDM_SPEED,100); + bdmlib_reset(); + bdmlib_setioctl(BDM_SPEED,10); + bdmlib_go(); + sleep(2); + bdm_step_chip(); + ret=bdmlib_load(file_name, NULL, &entry_pt); + if(ret<0) printf("bdmlib_load : %s\n",bdmlib_geterror_str(ret)); + bdmlib_set_sys_reg(BDM_REG_RPC, entry_pt); + ret=bdmlib_go(); + }; + + do { + c=getchar(); + + ret=bdmlib_getstatus(); + if(ret<0) printf("bdmlib_go : %s\n",bdmlib_geterror_str(ret)); + else { + printf("MCU "); + if(ret&BDM_TARGETRESET) printf("Reset "); + if(ret&BDM_TARGETSTOPPED) printf("Stopped "); + if(ret&BDM_TARGETPOWER) printf("NoPower "); + if(ret&BDM_TARGETNC) printf("NoConnect "); + printf("\n"); + }; + + c=toupper(c); + + switch(c) { + + case 'B': + + case 'D': + bdmlib_showpc(); + break; + + case 'S': + ret=bdm_step_chip(); + if(ret<0) printf("bdmlib_go : %s\n",bdmlib_geterror_str(ret)); + break; + + case 'G': + ret=bdmlib_go(); + if(ret<0) printf("bdmlib_go : %s\n",bdmlib_geterror_str(ret)); + break; + + case 'R': + bdmlib_setioctl(BDM_SPEED,100); + ret=bdmlib_reset(); + bdmlib_setioctl(BDM_SPEED,0); + if(ret<0) printf("bdmlib_reset : %s\n",bdmlib_geterror_str(ret)); + break; + + case 'Q': + quit_fl=1; + break; + + case 'X': + wr_test(); + break; + + case 'Y': + rd_test(); + break; + + case 'Z': + step_test(); + break; + + case 'L': + printf("Enter file name : "); + scanf("%s",file_name); + printf("\n"); + ret=bdmlib_load(file_name, NULL, &entry_pt); + if(ret<0) printf("bdmlib_load : %s\n",bdmlib_geterror_str(ret)); + else + {printf("loaded OK, entrypoint %lx\n",entry_pt); + if((ret=bdmlib_set_sys_reg(BDM_REG_RPC, entry_pt))<0) + printf("set PC error : %s\n",bdmlib_geterror_str(ret)); + } + break; + + case '\n': + break; + + default: + printf ("Help for BDM_TEST\n" + "B: Begin Program Execution from Reset\n" + "D: Dump Target MCU Registers\n" + "H: Print This Help Summary\n" + "L: Load S-Record or Object File into Target\n" + "M: Memory Hex/ASCII Display\n" + "R: Hardware Reset Target MCU\n" + "S: Single Step Target MCU\n" + "G: Go Full Speed Target MCU\n" + "Q: Quit back to DOS\n"); + }; + + } while(!quit_fl); + + bdmlib_close(1); + + return(0); + +}; + + +char* TestSW(int argc,char *argv[],char swch) +{ + int i; + char *p; + for(i=1;i + + 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 --git a/m683xx/bdm-load/bdmlib.c b/m683xx/bdm-load/bdmlib.c new file mode 100644 index 0000000..c656714 --- /dev/null +++ b/m683xx/bdm-load/bdmlib.c @@ -0,0 +1,1701 @@ +/* + * $Id: bdmlib.c,v 1.5 2005/11/04 14:33:54 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) +{ +#if SUPPORT_RAMINIT + u_long dummy; +#endif + 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, &dummy)) < 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%08lx cooked_size 0x%08lx\n", + sec->flags, (long)bfd_get_section_limit(abfd, sec), (long)bfd_get_section_size(sec)); + 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); + + /* there used to be bfd_get_section_size_before_reloc() */ + if ((load_bytes = bfd_section_size(abfd,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 SUPPORT_RAMINIT + u_long dummy; +#endif + + 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, &dummy)) < 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 --git a/m683xx/bdm-load/bdmlib.h b/m683xx/bdm-load/bdmlib.h new file mode 100644 index 0000000..f9d5c18 --- /dev/null +++ b/m683xx/bdm-load/bdmlib.h @@ -0,0 +1,83 @@ +/* + * $Id: bdmlib.h,v 1.2 2003/08/15 12:06:47 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 --git a/m683xx/bdm-load/cpu32init b/m683xx/bdm-load/cpu32init new file mode 100644 index 0000000..50ffac9 --- /dev/null +++ b/m683xx/bdm-load/cpu32init @@ -0,0 +1,65 @@ +# initialization macro-file for MO_CPU1 + +# 0xFFFA00 - SIMCR - SIM Configuration Register +w 0xfffa00 0x40cf 2 + +# 0xFFFA21 - SYPCR - System Protection Control Register +w 0xfffa21 0x06 1 + +# 0xFFFA04 - SYNCR Clock Synthesizer Control Register +w 0xfffa04 0xd408 2 + +# 0xFFFA17 - PEPAR - Port E Pin Assignment Register +w 0xfffa17 0xf4 1 + +# 0xFFFA1F - PFPAR - Port F Pin Assignment Register +w 0xfffa1f 0 1 + +# setup STANBY RAM at 0xFFD000 +w 0xFFFB40 0x8000 2 +w 0xFFFB44 0xFFD000 4 +w 0xFFFB40 0x0000 2 + +# setup TPU RAM at 0xFFE000 +w 0xFFFB00 0x8000 2 +w 0xFFFB04 0xFFE0 2 +w 0xFFFB00 0x0000 2 + +# 0xYFFA44 - CSPAR0 - Chip Select Pin Assignment Register 0 +w 0xfffa44 0x3bff 2 + +# 0xFFFA46 - CSPAR1 - Chip Select Pin Assignment Register 1 +w 0xfffa46 0x03a9 2 + +# BOOT ROM 0x800000 1MB RW UL - Boot FLASH +w 0xfffa48 0x8007 2 +w 0xfffa4A 0x7830 2 + +# CS0 ROM 0x900000 1MB RW UL - 2nd FLASH +w 0xfffa4c 0x9007 2 +w 0xfffa4e 0x7830 2 + +# CS2 RAM 0x000000 1MB RW UL - Main RAM first 1MB +w 0xfffa54 0x0007 2 +w 0xfffa56 0x7830 2 + +# CS3 RAM 0x100000 1MB RW UL - Main RAM second 1MB +w 0xfffa58 0x1007 2 +w 0xfffa5a 0x7830 2 + +# CS4 PER 0xf00000 512kB RW UL - CMOS RAM, RTC, other devices +w 0xfffa5c 0xf006 2 +w 0xfffa5e 0x7cb0 2 + +# CS7 PER 0xf87000 2k RW UL - MO_PWR +w 0xfffa68 0xf870 2 +w 0xfffa6a 0x7c70 2 + +# CS8 PER 0xf88000 2k RO UL - IRC +w 0xfffa6c 0xf880 2 +w 0xfffa6e 0x7c70 2 + +# CS9 PER 0xf89000 2k WR UL - KBD +w 0xfffa70 0xf890 2 +w 0xfffa72 0x7cf0 2 + diff --git a/m683xx/bdm-load/tpudb.c b/m683xx/bdm-load/tpudb.c new file mode 100644 index 0000000..15e8dd1 --- /dev/null +++ b/m683xx/bdm-load/tpudb.c @@ -0,0 +1,830 @@ +/******************************************************************* + TPUDB Project to Create Free Motorola 683xx TPU Debugger + + tpudb.c - first test + + (C) Copyright 2000 by Pavel Pisa - Original Author + e-mail: pisa@cmp.felk.cvut.cz + homepage: http://cmp.felk.cvut.cz/~pisa + work: http://www.pikron.com/ + + This package can be copied and modified under + GNU General Public License with all its conditions. + See file GPL for details. Under this license nobody can + distribute this work and any derived work without full source code + for all modules compiled and linked into executable. + + *******************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include "bdm.h" +#include "bdmlib.h" + +#define __val2mfld(mask,val) (((mask)&~((mask)<<1))*(val)&(mask)) +#define __mfld2val(mask,val) (((val)&(mask))/((mask)&~((mask)<<1))) + +#define val2mfld __val2mfld +#define mfld2val __mfld2val + +#if 0 + #define TPU_WR16(adr,val) (*(volatile u_int16_t*)(adr)=(val)) + #define TPU_RD16(adr) (*(volatile u_int16_t*)(adr)) +#else + #define TPU_WR16(adr,val) \ + ({ \ + if(bdmlib_write_var(adr,BDM_SIZE_WORD,val)<0) \ + goto mem_op_error; \ + val; \ + }) + #define TPU_RD16(adr) \ + ({ u_int16_t temp_val; \ + if(bdmlib_read_var(adr,BDM_SIZE_WORD,&temp_val)<0) \ + goto mem_op_error; \ + temp_val; \ + }) +#endif + +char hashmark=0; /* flag set by "set hash" */ +int bdm_autoreset=1; /* automatic reset before load */ +int bdm_ttcu=0; /* time to come up for init by rom */ +char initname[255]; /* need reimplement !!!!!!!!! */ +char bdm_dev_name[255]="/dev/bdm"; /* device name */ + +/* Numberring of TPU register */ +/* First part are aliases for main CPU accesible registers */ +#define TPUREG_TSTMSRA 0x0 /* Master Shift Register A */ +#define TPUREG_TSTMSRB 0x1 /* Master Shift Register B */ +#define TPUREG_TSTSC 0x2 /* Test Module Shift Count */ +#define TPU_TSTSCA 0xff00 /* Bits Shifted from TSTMSRA to Tested Module */ +#define TPU_TSTSCB 0x00ff /* Bits Shifted from Tested Module to TSTMSRB */ +#define TPUREG_TSTRC 0x3 /* Test Module Repetition Count */ +#define TPUREG_CREG 0x4 /* Test Submodule Control Register */ +#define TPU_TSTBUSY 0x8000 /* Test Submodule Busy Status Bit */ +#define TPU_TMARM 0x4000 /* Test Mode Armed Status Bit (latched /TSTME) */ +#define TPU_COMP 0x2000 /* Compare Status Bit */ +#define TPU_IMBTST 0x1000 /* Intermodule Bus Test (SCANA/SCANB) */ +#define TPU_CPUTR 0x0800 /* Scan to CPU Test Register */ +#define TPU_QBIT 0x0400 /* Quotient Bit at FREEZE/QUOT Pin */ +#define TPU_MUXEL 0x0200 /* Multiplexer Select Bit for MSRB from Int/Ext */ +#define TPU_ACUT 0x0010 /* Activate Circuit Under Test */ +#define TPU_SCONT 0x0008 /* Start Continuous Operation */ +#define TPU_SSHOP 0x0004 /* Start Shifting Operation */ +#define TPU_SATO 0x0002 /* Start Automatic Test Operation */ +#define TPU_EMT 0x0001 /* Enter test mode */ +#define TPUREG_DREG 0x5 /* Distributed Register */ +#define TPU_WAIT 0x0700 /* Wait Counter Preset 2-16 SCLK */ +#define TPU_MSRAHI 0x0e0 /* MSRA High Bits 18-16 */ +#define TPU_MSRAC 0x0010 /* Master Shift Register A Configuration */ +#define TPU_MSRBHI 0x00e /* MSRB High Bits 18-16 */ +#define TPU_MSRBC 0x0001 /* Master Shift Register B Configuration */ +#define TPUREG_MCR 0x6 /* TPU Module Configuration Register */ +#define TPU_STOP 0x8000 /* Low-Power Stop Mode Enable */ +#define TPU_TCR1P 0x6000 /* Timer Count Register 1 Prescaler Control */ +#define TPU_TCR2P 0x1800 /* Timer Count Register 2 Prescaler Control */ +#define TPU_EMU 0x0400 /* Emulation Control */ +#define TPU_T2CG 0x0200 /* TCR2 Clock/Gate Control */ +#define TPU_STF 0x0100 /* Stop Flag */ +#define TPU_SUPV 0x0080 /* Supervisor/Unrestricted */ +#define TPU_PSCK 0x0040 /* Prescaler Clock */ +#define TPU_IARB 0x000f /* Interrupt Arbitration ID */ +#define TPUREG_TCR 0x7 /* Test Configuration Register */ +#define TPU_INCAD 0x1000 /* Increment Address in uPC at ACUTL */ +#define TPU_TCR1C 0x0800 /* TCR1 Clock - TCR2 pin */ +#define TPU_ACUTR 0x0600 /* Activate Circuit Under Test Response 1, 0 */ +#define TPU_ACUTR_NONE 0 /* None */ +#define TPU_ACUTR_STEPTPU 1 /* Run ONE TPU microcycle */ +#define TPU_ACUTR_SHEOT 2 /* Scheduler End of Time Slot */ +#define TPU_SOSEL 0x0070 /* Scan-Out Select */ +#define TPU_SISEL 0x000e /* Scan-in Select */ +#define TPU_SxSEL_NONE 0 /* None */ +#define TPU_SxSEL_PC 1 /* uPC */ +#define TPU_SxSEL_IR 2 /* Microinstruction */ +#define TPU_SxSEL_BPLA 3 /* Branch PLA */ +#define TPU_SxSEL_PCBR 4 /* uPC Breakpoint */ +#define TPU_SxSEL_SPLA 5 /* Scheduler PLA */ +#define TPU_SxSEL_CHANBR 6 /* Channel Breakpoint */ +#define TPU_TMW 0x0001 /* Test Memory Map */ +#define TPUREG_DSCR 0x8 /* Development Support Control Register */ +#define TPU_HOT4 0x8000 /* Hang on T4 */ +#define TPU_BLC 0x0400 /* Branch Latch Control */ +#define TPU_CLKS 0x0200 /* Stop Clocks (to TCRs) */ +#define TPU_FRZ 0x0180 /* FREEZE Assertion Response */ +#define TPU_CCL 0x0040 /* Channel Conditions Latch */ +#define TPU_BMSK 0x003F /* Break cond mask */ +#define TPU_BP 0x0020 /* Break mPC == mPC breakpoint register */ +#define TPU_BC 0x0010 /* Break if CHAN start or set */ +#define TPU_BH 0x0008 /* Break if host service latch set */ +#define TPU_BL 0x0004 /* Break if link service latch set */ +#define TPU_BM 0x0002 /* Break if MRL set at beginning*/ +#define TPU_BT 0x0001 /* Break if TDL set at beginnibg */ +#define TPUREG_DSSR 0x9 /* Development Support Status Register */ +#define TPU_BKPT 0x0080 /* Breakpoint Asserted Flag */ +#define TPU_PCBK 0x0040 /* mPC Breakpoint Flag */ +#define TPU_CHBK 0x0020 /* Channel Register Breakpoint Flag */ +#define TPU_SRBK 0x0010 /* Service Request Breakpoint Flag */ +#define TPU_TPUF 0x0008 /* TPU FREEZE Flag */ +#define TPUREG_TICR 0xA /* TPU Interrupt Configuration Register */ +#define TPU_CIRL 0x0700 /* Channel Interrupt Request Level */ +#define TPU_CIBV 0x00f0 /* Bits [7:4] of Channel Interrupt Base Vector */ +#define TPUREG_CIER 0xB /* Channel Interrupt Enable Register */ +#define TPUREG_CFSR 0xC /* Channel Function Select Register 0 */ +#define TPUREG_HSQR 0xD /* Host Sequence Register 0 */ +#define TPUREG_HSRR 0xE /* Host Service Request Register 0 */ +#define TPUREG_CPR 0xF /* Channel Priority Register 0 */ +#define TPUREG_CISR 0x10 /* Channel Interrupt Status Register */ +#define TPUREG_LR 0x11 /* Link Register */ +#define TPUREG_SGLR 0x12 /* Service Grant Latch Register */ +#define TPUREG_DCNR 0x13 /* Decoded Channel Number Register */ +/* Registers not accesible from main CPU */ +#define TPUREG_P 0x14 /* Parameter Register (16-bit) */ +#define TPUREG_A 0x15 /* Accumulator (16-bit) */ +#define TPUREG_DIOB 0x16 /* Data I/O Buffer (16-bit) */ +#define TPUREG_SR 0x17 /* Shift Register (16-bit) */ +#define TPUREG_ERT 0x18 /* Event Temporary Register (16-b.) */ +#define TPUREG_CHAN 0x19 /* Channel Number (4-bit) */ +#define TPUREG_DEC 0x1A /* Decrementator Reg (4-bit) */ +#define TPUREG_TCR2 0x1B /* Timebase Register 2 (16-bit) */ +#define TPUREG_TCR1 0x1C /* Timebase Register 1 (16-bit) */ +#define TPUREG_PC 0x1D /* Microprogram Counter (9-bit) */ +#define TPUREG_IR 0x1E /* */ +#define TPUREG_BPLA 0x1F /* */ +#define TPUREG_SPLA 0x20 /* */ +#define TPUREG_PCBR 0x21 /* */ +#define TPUREG_CHANBR 0x22 /* */ +/* Aditional CPU Accessible Registers */ +#define TPUREG_DEBPAR 0x23 /* Parameter register at 0xFFFF00 for debugging */ +#define TRAMREG_CR 0x24 /* TPURAM Configuration Register */ +#define TRAM_STOP 0x8000 /* Low-Power Stop Mode Enable */ +#define TRAM_RASP 0x0080 /* TPURAM Array Space */ +#define TRAMREG_TST 0x25 /* TPURAM Test Register */ +#define TRAMREG_BAR 0x26 /* TPURAM Base Address and Status Register */ +#define TRAM_ADDR 0xfff0 /* TPURAM Array Base Address */ +#define TRAM_RAMDS 0x0001 /* RAM Array Disable */ + +#define TPUREG_MAX 0x26 + +/* Descriptor of TPU register access */ +typedef struct tpu_reg_des { + int (*reg_rd)(struct tpu_reg_des *des, int indx); + int (*reg_wr)(struct tpu_reg_des *des, int indx, int val); + int adr; + int adr1; + int flags; + int arr_len; /* array size, 0 .. no array */ + int bfld_bits; /* bitfield length, 0 .. no bitfields */ + int bfld_arr_len; /* bitfield array */ +}tpu_reg_des_t; + +int tpu_mem_rd16(struct tpu_reg_des *des, int indx); +int tpu_mem_wr16(struct tpu_reg_des *des, int indx, int val); +int tpu_t1_rd(struct tpu_reg_des *des, int indx); +int tpu_t1_wr(struct tpu_reg_des *des, int indx, int val); +int tpu_t2_rd(struct tpu_reg_des *des, int indx); +int tpu_t2_wr(struct tpu_reg_des *des, int indx, int val); +int tpu_reg_rd(int reg, int indx); +int tpu_reg_wr(int reg, int indx, int val); +int tpu_reg_or(int reg, int indx, int val); +int tpu_reg_and(int reg, int indx, int val); + +#define TPUREG_FL_SH4 1 /* shift value by 4 bits */ +#define TPUREG_FL_PMOD 2 /* modification for reg P */ +#define TPUREG_FL_DIOB 4 /* modification for reg DIOB */ + +#define TPUREG_INDX_BFLD (0x1<<24) /* index for bitfields */ + +/* Descriptors of TPU register access */ +tpu_reg_des_t tpu_regs[]={ + /* CPU accessible */ + [TPUREG_TSTMSRA]= {reg_rd:tpu_mem_rd16,reg_wr:tpu_mem_wr16,adr:0xFFFA30,}, + [TPUREG_TSTMSRB]= {reg_rd:tpu_mem_rd16,reg_wr:tpu_mem_wr16,adr:0xFFFA32,}, + [TPUREG_TSTSC] = {reg_rd:tpu_mem_rd16,reg_wr:tpu_mem_wr16,adr:0xFFFA34,}, + [TPUREG_TSTRC] = {reg_rd:tpu_mem_rd16,reg_wr:tpu_mem_wr16,adr:0xFFFA36,}, + [TPUREG_CREG] = {reg_rd:tpu_mem_rd16,reg_wr:tpu_mem_wr16,adr:0xFFFA38,}, + [TPUREG_DREG] = {reg_rd:tpu_mem_rd16,reg_wr:tpu_mem_wr16,adr:0xFFFA3A,}, + [TPUREG_MCR] = {reg_rd:tpu_mem_rd16,reg_wr:tpu_mem_wr16,adr:0xFFFE00,}, + [TPUREG_TCR] = {reg_rd:tpu_mem_rd16,reg_wr:tpu_mem_wr16,adr:0xFFFE02,}, + [TPUREG_DSCR] = {reg_rd:tpu_mem_rd16,reg_wr:tpu_mem_wr16,adr:0xFFFE04,}, + [TPUREG_DSSR] = {reg_rd:tpu_mem_rd16,reg_wr:tpu_mem_wr16,adr:0xFFFE06,}, + [TPUREG_TICR] = {reg_rd:tpu_mem_rd16,reg_wr:tpu_mem_wr16,adr:0xFFFE08,}, + [TPUREG_CIER] = {reg_rd:tpu_mem_rd16,reg_wr:tpu_mem_wr16,adr:0xFFFE0A, + arr_len:0,bfld_bits:1,bfld_arr_len:16,}, + [TPUREG_CFSR] = {reg_rd:tpu_mem_rd16,reg_wr:tpu_mem_wr16,adr:0xFFFE0C, + arr_len:4,bfld_bits:4,bfld_arr_len:16,}, + [TPUREG_HSQR] = {reg_rd:tpu_mem_rd16,reg_wr:tpu_mem_wr16,adr:0xFFFE14, + arr_len:2,bfld_bits:2,bfld_arr_len:16,}, + [TPUREG_HSRR] = {reg_rd:tpu_mem_rd16,reg_wr:tpu_mem_wr16,adr:0xFFFE18, + arr_len:2,bfld_bits:2,bfld_arr_len:16,}, + [TPUREG_CPR] = {reg_rd:tpu_mem_rd16,reg_wr:tpu_mem_wr16,adr:0xFFFE1C, + arr_len:2,bfld_bits:2,bfld_arr_len:16,}, + [TPUREG_CISR] = {reg_rd:tpu_mem_rd16,reg_wr:tpu_mem_wr16,adr:0xFFFE20, + arr_len:0,bfld_bits:1,bfld_arr_len:16,}, + [TPUREG_LR] = {reg_rd:tpu_mem_rd16,reg_wr:tpu_mem_wr16,adr:0xFFFE22,}, + [TPUREG_SGLR] = {reg_rd:tpu_mem_rd16,reg_wr:tpu_mem_wr16,adr:0xFFFE24,}, + [TPUREG_DCNR] = {reg_rd:tpu_mem_rd16,reg_wr:tpu_mem_wr16,adr:0xFFFE26,}, + /* Special TPU - group 1 */ + /* internal TPU registers, ounly access possible through forced TPU microengine instructions */ + /* adr .. instruction for reg read, adr1 .. instruction for reg write */ + [TPUREG_P] = {reg_rd:tpu_t1_rd,reg_wr:tpu_t1_wr,adr:0x3fff,adr1:0x36ff, + flags:TPUREG_FL_PMOD,}, + [TPUREG_A] = {reg_rd:tpu_t1_rd,reg_wr:tpu_t1_wr,adr:0x327f,adr1:0x361f}, + [TPUREG_DIOB] = {reg_rd:tpu_t1_rd,reg_wr:tpu_t1_wr,adr:0,adr1:0, + flags:TPUREG_FL_DIOB,}, + [TPUREG_SR] = {reg_rd:tpu_t1_rd,reg_wr:tpu_t1_wr,adr:0x347f,adr1:0x363f}, + [TPUREG_ERT] = {reg_rd:tpu_t1_rd,reg_wr:tpu_t1_wr,adr:0x3c7f,adr1:0x365f}, + [TPUREG_CHAN] = {reg_rd:tpu_t1_rd,reg_wr:tpu_t1_wr,adr:0x267f,adr1:0x373f, + flags:TPUREG_FL_SH4,}, + [TPUREG_DEC] = {reg_rd:tpu_t1_rd,reg_wr:tpu_t1_wr,adr:0x247f,adr1:0x375f}, + [TPUREG_TCR2] = {reg_rd:tpu_t1_rd,reg_wr:tpu_t1_wr,adr:0x387f,adr1:0x379f}, + [TPUREG_TCR1] = {reg_rd:tpu_t1_rd,reg_wr:tpu_t1_wr,adr:0x3a7f,adr1:0x37bf}, + /* Special TPU - group 2 */ + /* access through test subsystem serial scan lines */ + /* adr .. number of register bits, adr1 .. TPU scan line selection */ + [TPUREG_PC] = {reg_rd:tpu_t2_rd,reg_wr:tpu_t2_wr,adr: 9,adr1:TPU_SxSEL_PC}, + [TPUREG_IR] = {reg_rd:NULL,reg_wr:NULL,adr:0,adr1:0}, + [TPUREG_BPLA] = {reg_rd:tpu_t2_rd,reg_wr:tpu_t2_wr,adr:16,adr1:TPU_SxSEL_BPLA}, + [TPUREG_SPLA] = {reg_rd:tpu_t2_rd,reg_wr:tpu_t2_wr,adr:15,adr1:TPU_SxSEL_SPLA}, + [TPUREG_PCBR] = {reg_rd:tpu_t2_rd,reg_wr:tpu_t2_wr,adr: 9,adr1:TPU_SxSEL_PCBR}, + [TPUREG_CHANBR] = {reg_rd:tpu_t2_rd,reg_wr:tpu_t2_wr,adr: 4,adr1:TPU_SxSEL_CHANBR}, + /* One of parameter registers used for internal registers access */ /* was TPUREG_DEBUR */ + [TPUREG_DEBPAR] = {reg_rd:tpu_mem_rd16,reg_wr:tpu_mem_wr16,adr:0xFFFF00,}, + [TRAMREG_CR] = {reg_rd:tpu_mem_rd16,reg_wr:tpu_mem_wr16,adr:0xFFFB00,}, + [TRAMREG_TST] = {reg_rd:tpu_mem_rd16,reg_wr:tpu_mem_wr16,adr:0xFFFB02,}, + [TRAMREG_BAR] = {reg_rd:tpu_mem_rd16,reg_wr:tpu_mem_wr16,adr:0xFFFB04,}, +}; + +/**************************************************************************/ +/* Helper function for test register access */ + +static int use_fetched_reg; +static u_int16_t fetched_dscr; +static u_int16_t fetched_creg; +static u_int16_t fetched_tcr; + +static u_int16_t stored_diob; +static u_int16_t stored_pc; +static u_int16_t stored_debpar2; /* was strored_debur2 */ +static u_int32_t stored_ir; /* was strored_x1 */ + /* was strored_x2 */ + +static +void test_shift_wait(unsigned creg) +{ + int cnt=0x8000; + tpu_reg_wr(TPUREG_CREG,0,creg|TPU_SSHOP); /* 4 */ + do{ + creg=tpu_reg_rd(TPUREG_CREG,0); + if(!(creg&TPU_TSTBUSY)) return; /* 0x8000 */ + }while(cnt--); + fprintf(stderr,"test_shift_wait : stalled busy condition\n"); +} + +/* Write 32 Bit Instruction Register */ +static /* was test_shift_1 */ +void test_shift_irwr(u_int32_t new_ir ) +{ + u_int16_t dscr; /* [bp-6] */ + u_int16_t creg; /* si */ + u_int16_t tcr; /* di */ + + if (!use_fetched_reg){ + tpu_reg_wr(TPUREG_TSTMSRB,0,0); + tpu_reg_wr(TPUREG_TSTRC,0,0); + tpu_reg_wr(TPUREG_DREG,0,0); + dscr=tpu_reg_rd(TPUREG_DSCR,0); + creg=tpu_reg_rd(TPUREG_CREG,0); + tcr=tpu_reg_rd(TPUREG_TCR,0); + }else{ + creg=fetched_creg; + tcr=fetched_tcr; + dscr=fetched_dscr; + } + + creg=(creg|TPU_IMBTST)&~TPU_MUXEL; /*!!!!!!!!!!!*/ + tpu_reg_wr(TPUREG_CREG,0,creg); + + if(!(dscr&TPU_HOT4)) /* ???????? */ + tpu_reg_wr(TPUREG_DSCR,0,dscr|TPU_HOT4); + + tcr&=TPU_INCAD | TPU_TCR1C | TPU_TMW; /* 0x1801 */ + tpu_reg_wr(TPUREG_TCR,0,tcr | val2mfld(TPU_ACUTR,TPU_ACUTR_STEPTPU) | + val2mfld(TPU_SISEL,TPU_SxSEL_IR)); /* 0x204 */ + tpu_reg_wr(TPUREG_TSTSC,0,0x1000); + tpu_reg_wr(TPUREG_TSTMSRA,0,new_ir&0xffff); + + test_shift_wait(creg); /* test shift */ + + tpu_reg_wr(TPUREG_TCR,0,tcr | val2mfld(TPU_ACUTR,TPU_ACUTR_STEPTPU) | + val2mfld(TPU_SISEL,TPU_SxSEL_IR)); /* 0x204 */ + tpu_reg_wr(TPUREG_TSTSC,0,0x1000); + tpu_reg_wr(TPUREG_TSTMSRA,0,(new_ir>>16)&0xffff); + + test_shift_wait(creg); /* test shift */ + + if(!(dscr&TPU_HOT4)) /* ???????? */ + tpu_reg_wr(TPUREG_DSCR,0,dscr); +} + +/* Read 32 Bit Instruction Register */ +static /* was test_shift_2 */ +u_int32_t test_shift_irrd(void) +{ + u_int16_t dscr; /* [bp-0a] */ + u_int16_t creg; /* si */ + u_int16_t tcr; /* di */ + u_int16_t ir_lo,ir_hi; + + if (!use_fetched_reg){ + tpu_reg_wr(TPUREG_TSTMSRB,0,0); + tpu_reg_wr(TPUREG_TSTRC,0,0); + tpu_reg_wr(TPUREG_DREG,0,0); + dscr=tpu_reg_rd(TPUREG_DSCR,0); + creg=tpu_reg_rd(TPUREG_CREG,0); + tcr=tpu_reg_rd(TPUREG_TCR,0); + }else{ + creg=fetched_creg; + tcr=fetched_tcr; + dscr=fetched_dscr; + } + + creg=(creg|TPU_IMBTST)&~TPU_MUXEL; /*!!!!!!!!!!!*/ + tpu_reg_wr(TPUREG_CREG,0,creg); + + if(!(dscr&TPU_HOT4)) /* ???????? */ + tpu_reg_wr(TPUREG_DSCR,0,dscr|TPU_HOT4); + + tcr&=TPU_INCAD | TPU_TCR1C | TPU_TMW; /* 0x1801 */ + tpu_reg_wr(TPUREG_TCR,0,tcr | val2mfld(TPU_ACUTR,TPU_ACUTR_STEPTPU) | + val2mfld(TPU_SOSEL,TPU_SxSEL_IR)); /* 0x220 */ + tpu_reg_wr(TPUREG_TSTSC,0,0x0010); + + test_shift_wait(creg); /* test shift */ + + ir_lo=tpu_reg_rd(TPUREG_TSTMSRB,0); + tpu_reg_wr(TPUREG_TCR,0,tcr | val2mfld(TPU_ACUTR,TPU_ACUTR_STEPTPU) | + val2mfld(TPU_SOSEL,TPU_SxSEL_IR) | + val2mfld(TPU_SISEL,TPU_SxSEL_IR)); /* 0x224 */ + tpu_reg_wr(TPUREG_TSTSC,0,0x1010); + tpu_reg_wr(TPUREG_TSTMSRA,0,ir_lo); + + test_shift_wait(creg); /* test shift */ + + ir_hi=tpu_reg_rd(TPUREG_TSTMSRB,0); + tpu_reg_wr(TPUREG_TCR,0,tcr | val2mfld(TPU_ACUTR,TPU_ACUTR_STEPTPU) | + val2mfld(TPU_SISEL,TPU_SxSEL_IR)); /* 0x204 */ + tpu_reg_wr(TPUREG_TSTSC,0,0x1000); + tpu_reg_wr(TPUREG_TSTMSRA,0,ir_hi); + + test_shift_wait(creg); /* test shift */ + + if(!(dscr&TPU_HOT4)) /* ???????? */ + tpu_reg_wr(TPUREG_DSCR,0,dscr); + + return ir_lo|((u_int32_t)ir_hi<<16); +} + +static /* was test_shift_3 */ +int test_shift_regrd(int shiftcnt ,int sxsel) +{ + u_int16_t dscr; /* [bp-8] */ + u_int16_t creg; /* si */ + u_int16_t tcr; /* di */ + u_int16_t ret; + + if (!use_fetched_reg){ + tpu_reg_wr(TPUREG_TSTMSRB,0,0); + tpu_reg_wr(TPUREG_TSTRC,0,0); + tpu_reg_wr(TPUREG_DREG,0,0); + dscr=tpu_reg_rd(TPUREG_DSCR,0); + creg=tpu_reg_rd(TPUREG_CREG,0); + tcr=tpu_reg_rd(TPUREG_TCR,0); + }else{ + creg=fetched_creg; + tcr=fetched_tcr; + dscr=fetched_dscr; + } + + creg=(creg|TPU_IMBTST)&~TPU_MUXEL; /*!!!!!!!!!!!*/ + tpu_reg_wr(TPUREG_CREG,0,creg); + + if(!(dscr&TPU_HOT4)) /* ???????? */ + tpu_reg_wr(TPUREG_DSCR,0,dscr|TPU_HOT4); + + tcr&=TPU_INCAD | TPU_TCR1C | TPU_TMW; /* 0x1801 */ + tpu_reg_wr(TPUREG_TCR,0,tcr | val2mfld(TPU_ACUTR,TPU_ACUTR_STEPTPU) | + val2mfld(TPU_SOSEL,sxsel)); /* (sxsel<<4)|0x200 */ + tpu_reg_wr(TPUREG_TSTSC,0,shiftcnt); + + test_shift_wait(creg); /* test shift */ + + ret=tpu_reg_rd(TPUREG_TSTMSRB,0)>>(0x10-shiftcnt); + tpu_reg_wr(TPUREG_TCR,0,tcr | val2mfld(TPU_ACUTR,TPU_ACUTR_STEPTPU) | + val2mfld(TPU_SISEL,sxsel)); /* (sxsel<<1)|0x200 */ + tpu_reg_wr(TPUREG_TSTSC,0,shiftcnt<<8); + tpu_reg_wr(TPUREG_TSTMSRA,0,ret); + + test_shift_wait(creg); /* test shift */ + + if(!(dscr&TPU_HOT4)) /* ???????? */ + tpu_reg_wr(TPUREG_DSCR,0,dscr); + + return ret; +} + +static /* was test_shift_4 */ +int test_shift_regwr(int shiftcnt, int sxsel, int val) +{ + u_int16_t dscr; /* di */ + u_int16_t creg; /* si */ + u_int16_t tcr; /* [bp-6] */ + + if (!use_fetched_reg){ + tpu_reg_wr(TPUREG_TSTMSRB,0,0); + tpu_reg_wr(TPUREG_TSTRC,0,0); + tpu_reg_wr(TPUREG_DREG,0,0); + dscr=tpu_reg_rd(TPUREG_DSCR,0); + creg=tpu_reg_rd(TPUREG_CREG,0); + tcr=tpu_reg_rd(TPUREG_TCR,0); + }else{ + creg=fetched_creg; + tcr=fetched_tcr; + dscr=fetched_dscr; + } + + if(!(dscr&TPU_HOT4)) /* ???????? */ + tpu_reg_wr(TPUREG_DSCR,0,dscr|TPU_HOT4); + + creg=(creg|TPU_IMBTST)&~TPU_MUXEL; /*!!!!!!!!!!!*/ + tpu_reg_wr(TPUREG_CREG,0,creg); + tcr&=TPU_INCAD | TPU_TCR1C | TPU_TMW; /* 0x1801 */ + tpu_reg_wr(TPUREG_TCR,0,tcr | val2mfld(TPU_ACUTR,TPU_ACUTR_STEPTPU) | + val2mfld(TPU_SISEL,sxsel)); /* (sxsel<<1)|0x200 */ + tpu_reg_wr(TPUREG_TSTSC,0,shiftcnt<<8); + tpu_reg_wr(TPUREG_TSTMSRA,0,val); + + test_shift_wait(creg); /* test shift */ + + if(!(dscr&TPU_HOT4)) /* ???????? */ + tpu_reg_wr(TPUREG_DSCR,0,dscr); + + return 0; +} + +static /* was test_pha_2 */ +void test_forced_inst(u_int32_t new_ir) +{ + test_shift_irwr(new_ir); + tpu_reg_or(TPUREG_CREG,0,TPU_ACUT); +} + +static /* was test_pha_1 */ +void test_store_ir(void) +{ + stored_debpar2=tpu_reg_rd(TPUREG_DEBPAR,0); + stored_pc=tpu_reg_rd(TPUREG_PC,0); + stored_ir=test_shift_irrd(); + test_forced_inst(0x3ffffc03); + stored_diob=tpu_reg_rd(TPUREG_DEBPAR,0); +} + +static /* was test_pha_3 */ +void test_restore_ir(void) +{ + tpu_reg_wr(TPUREG_DEBPAR,0,stored_diob); + test_forced_inst(0x1ffffc03); + tpu_reg_wr(TPUREG_DEBPAR,0,stored_debpar2); + tpu_reg_wr(TPUREG_PC,0,stored_pc); + test_shift_irwr(stored_ir); +} + +/**************************************************************************/ +/* Other supporting routines */ + +static u_int16_t test_dssrdscr_1; /* 0 => stop, 1 =>run */ +static u_int16_t test_dscr_arm; +static u_int16_t test_dssr_bkpt; + +int test_init_1(void) +{ + u_int16_t creg; /* bp-2 */ + int cnt=0x1000; + + tpu_reg_wr(TPUREG_CREG,0,TPU_MUXEL|TPU_EMT); + creg=tpu_reg_rd(TPUREG_CREG,0); + do{ + creg=tpu_reg_rd(TPUREG_CREG,0); + }while(!(creg&TPU_EMT)&&(--cnt)); + tpu_reg_wr(TPUREG_CIER,0,0); /* disable interrupt generation */ + if(!cnt){ + fprintf(stderr,"test_init_1 : cannot enter test mode\n"); + return -1; + } + return 0; +} + +int test_init_2(void) +{ + u_int16_t dssr; /* si */ + u_int16_t dscr; /* bx */ + dssr=tpu_reg_rd(TPUREG_DSSR,0); + dscr=tpu_reg_rd(TPUREG_DSCR,0); + if((dssr&TPU_BKPT)||(dscr&TPU_HOT4)) + test_dssrdscr_1=0; + else + test_dssrdscr_1=1; + test_dscr_arm=dscr&TPU_BMSK; + if (dssr&TPU_BKPT) + test_dssr_bkpt=1; + else + test_dssr_bkpt=0; + return 0; +} + +int tpu_halt(void) +{ + int i; + if(test_dssrdscr_1==0){ + /* already halted */ + /* return 0; */ + } + tpu_reg_or(TPUREG_CREG,0,TPU_IMBTST); /* stop microengine */ + tpu_reg_wr(TPUREG_DSCR,0,TPU_HOT4|TPU_CLKS|test_dscr_arm); + test_dssrdscr_1=0; + /* old_cpr = CPR0,CPR1 */ + /* CPR0,CPR1 = 0 */ + for(i=0;i<5;i++){ + if(tpu_reg_rd(TPUREG_DSSR,0)&TPU_BKPT) + tpu_reg_and(TPUREG_DSSR,0,~TPU_BKPT); + tpu_reg_or(TPUREG_CREG,0,TPU_IMBTST|TPU_ACUT); + } + /* CPR0,CPR1 = old_cpr */ + + return 0; +} + +#define TPU_UCODE_LEN 0x200 + +u_int32_t tpu_ucode_img[TPU_UCODE_LEN]; + +int tpu_ucode_read(int print) +{ + int adr; + u_int32_t ir; + adr=0; + + test_store_ir(); + + if(print)printf("reading microcode\n"); + tpu_reg_wr(TPUREG_PC,0,adr); + for(;adrflags&TPUREG_FL_DIOB){ + val=stored_diob; /* DIOB read */ + }else{ + if(des->flags&TPUREG_FL_PMOD) + test_forced_inst(0xf403|(des->adr<<16)); /* P read */ + else + test_forced_inst(0xfc03|(des->adr<<16)); /* rest */ + /* read value from mem 0xFFFF00 */ + val=tpu_reg_rd(TPUREG_DEBPAR,0); + } + test_restore_ir(); + if(des->flags&TPUREG_FL_SH4) + val>>=4; + return val; +} + +/* write TPU register - method 1 */ +int tpu_t1_wr(struct tpu_reg_des *des, int indx, int val) +{ + int ret; + test_store_ir(); + if(des->flags&TPUREG_FL_SH4) + val<<=4; + ret=tpu_reg_wr(TPUREG_DEBPAR,0,val); + test_forced_inst(0x1ffffc03); + if(des->flags&TPUREG_FL_DIOB){ + stored_diob=val; /* DIOB write */ + }else{ + test_forced_inst(0xffff|(des->adr1<<16)); /* rest */ + } + test_restore_ir(); + return 0; +} + +/* read TPU register - method 2 */ +int tpu_t2_rd(struct tpu_reg_des *des, int indx) +{ + return test_shift_regrd(des->adr,des->adr1); +} + +/* write TPU register - method 2 */ +int tpu_t2_wr(struct tpu_reg_des *des, int indx, int val) +{ + return test_shift_regwr(des->adr,des->adr1,val); +} + +/* read 16 bit variable from main CPU address space */ +int tpu_mem_rd16(struct tpu_reg_des *des, int indx) +{ + u_int16_t val; + int adr=des->adr; + if(indx){ + if(indx>=des->arr_len) return -1; + adr+=2*indx; + } + val=TPU_RD16((caddr_t)adr); + return val; + + mem_op_error: + fprintf(stderr,"tpu_mem_rd16 : read from address %06x error\n",adr); + fflush(NULL); + return -1; +} + +/* write 16 bit variable to main CPU address space */ +int tpu_mem_wr16(struct tpu_reg_des *des, int indx, int val) +{ + int adr=des->adr; + if(indx){ + if(indx>=des->arr_len) return -1; + adr+=2*indx; + } + TPU_WR16((caddr_t)adr,val); + return 0; + + mem_op_error: + fprintf(stderr,"tpu_mem_wr16 : write to address %06x error\n",adr); + fflush(NULL); + return -1; +} + +/* Read TPU register */ +int tpu_reg_rd(int reg, int indx) +{ + if((reg>TPUREG_MAX)||(tpu_regs[reg].reg_rd==NULL)) + return -1; + return tpu_regs[reg].reg_rd(&tpu_regs[reg],indx); +} + +/* Write TPU register */ +int tpu_reg_wr(int reg, int indx, int val) +{ + if((reg>TPUREG_MAX)||(tpu_regs[reg].reg_wr==NULL)) + return -1; + return tpu_regs[reg].reg_wr(&tpu_regs[reg],indx,val); +} + +int tpu_reg_or(int reg, int indx, int val) +{ + int reg_val; + reg_val=tpu_reg_rd(reg,indx); + reg_val|=val; + tpu_reg_wr(reg,indx,reg_val); + return reg_val; +} + +int tpu_reg_and(int reg, int indx, int val) +{ + int reg_val; + reg_val=tpu_reg_rd(reg,indx); + reg_val&=val; + tpu_reg_wr(reg,indx,reg_val); + return reg_val; +} + +/**************************************************************************/ + +#define swap_l(x) (x>>24) | ((x>>8)&0xff00) | ((x<<8)&0xff0000) | ((x&0xff)<<24) + +/* external TPU disassembler */ +void DisInst (unsigned long i, FILE * fp); + + +int cpu_stat(void) +{ + int ret; + u_int rpc; + + ret=bdmlib_getstatus(); + printf("MCU "); + if(ret&BDM_TARGETRESET) printf("Reset "); + if(ret&BDM_TARGETSTOPPED) printf("Stopped "); + if(ret&BDM_TARGETPOWER) printf("NoPower "); + if(ret&BDM_TARGETNC) printf("NoConnect "); + printf("\n"); + if(ret&BDM_TARGETSTOPPED) { + if((ret=bdmlib_get_sys_reg(BDM_REG_RPC, &rpc))<0) return ret; + printf("RPC=0x%06x\n",swap_l(rpc)); + } + return 0; +} + +int main(int argc, char *argv[]) +{ + int ret; + + bdmlib_setdebug(1); + if((ret=bdmlib_open(bdm_dev_name))<0) + { printf("bdmlib_open : %s\n",bdmlib_geterror_str(ret)); return 1; }; + bdmlib_setioctl(BDM_SPEED,0); + if (!(bdmlib_getstatus() & BDM_TARGETSTOPPED)) + ret=bdmlib_ioctl(BDM_STOP_CHIP); + + if(1){ + printf("We need to reset target for first run\n"); + if((ret=bdmlib_reset())<0){ + printf("Cannot reset target - exitting\n"); + exit(1); + } + } + + if(cpu_stat()<0){ + printf("trying to reset !!!!!!!\n"); + ret=bdmlib_reset(); + cpu_stat(); + } + + bdmlib_set_sys_reg(BDM_REG_DFC, 5); + bdmlib_set_sys_reg(BDM_REG_SFC, 5); + + ret=test_init_1(); + printf("test_init_1 returned %d\n",ret); + ret=test_init_2(); + printf("test_init_2 returned %d\n",ret); + printf("test_dssrdscr_1(run)=%d test_dscr_arm=0x%02x test_dssr_bkpt=%d\n", + test_dssrdscr_1,test_dscr_arm,test_dssr_bkpt); + + fflush(NULL); + +// tpu_halt(); + + printf("DCNR %04X\n",tpu_reg_rd(TPUREG_DCNR,0)); + printf("DSCR %04X\n",tpu_reg_rd(TPUREG_DSCR,0)); + +// tpu_reg_or(TPUREG_CREG,0,TPU_IMBTST); /* stop microengine */ +// tpu_reg_or(TPUREG_DSCR,0,0x8200); /* ???????????? */ + + printf("P %04X DIOB %04X A %04X SR %04X DEC %01X\n" + "ERT %04X TCR1 %04X TCR2 %04X PC %03X CHAN %01X\n", + tpu_reg_rd(TPUREG_P,0),tpu_reg_rd(TPUREG_DIOB,0), + tpu_reg_rd(TPUREG_A,0),tpu_reg_rd(TPUREG_SR,0), + tpu_reg_rd(TPUREG_DEC,0),tpu_reg_rd(TPUREG_ERT,0), + tpu_reg_rd(TPUREG_TCR1,0),tpu_reg_rd(TPUREG_TCR2,0), + tpu_reg_rd(TPUREG_PC,0),tpu_reg_rd(TPUREG_CHAN,0)); + + if(0){ + printf("TCR2 %04X\n",tpu_reg_rd(TPUREG_TCR2,0)); + printf("TCR1 %04X\n",tpu_reg_rd(TPUREG_TCR1,0)); + printf("TCR2 %04X\n",tpu_reg_rd(TPUREG_TCR2,0)); + + tpu_reg_wr(TPUREG_P ,0,0xABCD);tpu_reg_wr(TPUREG_DIOB,0,0xEF01); + tpu_reg_wr(TPUREG_A ,0,0x2345);tpu_reg_wr(TPUREG_SR ,0,0x6789); + tpu_reg_wr(TPUREG_DEC ,0, 0xA);tpu_reg_wr(TPUREG_ERT ,0,0xBCDE); + tpu_reg_wr(TPUREG_TCR1,0,0xF012);tpu_reg_wr(TPUREG_TCR2,0,0x3456); + tpu_reg_wr(TPUREG_PC ,0, 0x789);tpu_reg_wr(TPUREG_CHAN,0, 0xB); + } + + { + int i; + tpu_ucode_read(0); + + for(i=0;i +#include +#define TRUE 1 +#define FALSE 0 + +static FILE *f; +static unsigned long inst; + +void +Error (char *s) +{ + fprintf (stderr, "\ntpudis: %s\n", s); + exit (1); +} + + +#define put(x) s=x +#define I(h,l) ( (inst>>(l)) & (((1<<((h)+1-(l))))-1) ) + +void +T1ABS (void) +{ + char *s=NULL; + + switch (I (28, 25)) + { + case 0: + put ("plow"); + break; + case 1: + put ("phi"); + break; + case 2: + put ("dec"); + break; + case 3: + put ("chan"); + break; + case 4: + put ("#0 special"); + break; + case 5: + put ("{Illegal T1ABS: 5}"); + break; + case 6: + put ("{Illegal T1ABS: 6}"); + break; + case 7: + put ("#0"); + break; + case 8: + put ("p"); + break; + case 9: + put ("a"); + break; + case 10: + put ("sr"); + break; + case 11: + put ("diob"); + break; + case 12: + put ("tcr1"); + break; + case 13: + put ("tcr2"); + break; + case 14: + put ("ert"); + break; + case 15: + put ("#0"); + break; + default: + Error ("T1ABS decoding error"); + } + fprintf (f, "%s + ", s); +} + + +void +T3ABD (void) +{ + char *s=NULL; + + switch (inst >> 21 & 0xF) + { + case 0: + put ("a"); + break; + case 1: + put ("sr"); + break; + case 2: + put ("ert"); + break; + case 3: + put ("diob"); + break; + case 4: + put ("phi"); + break; + case 5: + put ("{Illegal T3ABD: 5}"); + break; + case 6: + put ("plow"); + break; + case 7: + put ("p"); + break; + case 8: + put ("link"); + break; + case 9: + put ("chan"); + break; + case 10: + put ("dec"); + break; + case 11: + put ("dec&chan"); + break; + case 12: + put ("tcr1"); + break; + case 13: + put ("tcr2"); + break; + case 14: + put ("{Illegal T3ABD: 14}"); + break; + case 15: + put ("Nil"); + break; + default: + Error ("T3ABD decoding error"); + } + fprintf (f, "AU %s :=", s); +} + + +void +SHF (void) +{ + char *s=NULL; + + switch (inst >> 19 & 3) + { + case 0: + s = "<<"; + break; + case 1: + s = ">>"; + break; + case 2: + s = "R>"; + break; + case 3: + s = ""; + break; + default: + Error ("SHF decoding error"); + } + fprintf (f, "%s ", s); +} + + +void +T1BBSetc (void) +{ + char *s=NULL; + + switch (inst >> 14 & 7) + { + case 0: + s = "p"; + break; + case 1: + s = "a"; + break; + case 2: + s = "sr"; + break; + case 3: + s = "diob"; + break; + case 7: + s = "#0"; + break; + case 4: + case 5: + case 6: + s = "{Illegal T1BBS}"; + break; + default: + Error ("T1BBS decoding error"); + } + fprintf (f, "%s%s%s ", + inst & (1L << 12) ? "" : "!", s, inst & (1L << 13) ? "" : " + 1"); +} + + +void +SRCCCL (void) +{ + if (~inst & (1L << 18)) + fprintf (f, ", ensr"); + if (~inst & (1L << 17)) + fprintf (f, ", cc"); +} + + +void +T1BBI (void) +{ + fprintf (f, "#$%2lx", inst >> 9 & 0xFF); +} + + +void +DECEND (void) +{ + char *s=NULL; + + switch (inst & 3) + { + case 0: + s = "DEC_RTS"; + break; + case 1: + s = "DEC_RPT"; + break; + case 2: + s = "end"; + break; + case 3: + return; + default: + Error ("DECEND decoding error"); + } + fprintf (f, "%s", s); +} + + +void +IOMetc (int rwPos) +{ + char *fm=NULL; + int aid=0; + + switch (inst >> 9 & 7) + { + case 0: + fm = "RAM p %s @prm%d ; "; + aid = inst >> 2 & 7; + break; + case 1: + fm = "RAM p %s by_diob ; "; + break; + case 2: + fm = "RAM p %s @$%x ; "; + aid = inst >> 2 & 0x7F; + break; + case 4: + fm = "RAM diob %s @prm%d ; "; + aid = inst >> 2 & 7; + break; + case 5: + fm = "RAM diob %s by_diob ; "; + break; + case 6: + fm = "RAM diob %s @$%x ; "; + aid = inst >> 2 & 0x7F; + break; + case 3: + case 7: + return; + default: + Error ("IOM decoding error"); + + } + fprintf (f, fm, inst & (1L << rwPos) ? "->" : "<-", aid); +} + + +void +CJCetc (void) +{ + char *s=NULL; + + if (I (29, 16) == 0x3FFF) + return; + + switch (inst >> 26 & 0xF) + { + case 0: + s = "LESS_THAN"; + break; + case 1: + s = "LOW_SAME"; + break; + case 2: + s = "V"; + break; + case 3: + s = "N"; + break; + case 4: + s = "C"; + break; + case 5: + s = "Z"; + break; + case 6: + s = "cflg1"; + break; + case 7: + s = "cflg0"; + break; + case 8: + s = "TDL"; + break; + case 9: + s = "MRL"; + break; + case 10: + s = "LSL"; + break; + case 11: + s = "SEQ1"; + break; + case 12: + s = "SEQ0"; + break; + case 13: + s = "PSL"; + break; + case 14: + s = "{Illegal branch}"; + break; + case 15: + s = "false"; + break; + default: + Error ("CJC decoding error"); + } + fprintf (f, "if %s = %s then goto $%lx%s; ", + s, + inst & (1L << 8) ? "true" : "false", + inst >> 16 & 0x1FF, inst & (1L << 25) ? "" : ", flsh"); +} + + +void +NMAetc (void) +{ + char *s=NULL; + + switch (inst >> 26 & 3) + { + case 0: + s = "jmp"; + break; + case 1: + s = "jsr"; + break; + case 2: + s = "rts"; + break; + case 3: + return; + default: + Error ("NMA decoding error"); + } + fprintf (f, "%s%s $%lx ; ", s, inst & (1L << 25) ? "" : " ,flsh", + inst >> 16 & 0x1FF); +} + +void +TBS (void) +{ + char *s=NULL; + + switch (I (15, 12)) + { + case 0: + s = "in_mtcr1_ctcr1"; + break; + case 1: + s = "in_mtcr2_ctcr1"; + break; + case 2: + s = "in_mtcr1_ctcr2"; + break; + case 3: + s = "in_mtcr2_ctcr2"; + break; + case 4: + s = "out_mtcr1_ctcr1"; + break; + case 5: + s = "out_mtcr2_ctcr1"; + break; + case 6: + s = "out_mtcr1_ctcr2"; + break; + case 7: + s = "out_mtcr2_ctcr2"; + break; + case 8: + case 9: + case 10: + case 11: + case 12: + case 13: + case 14: + case 15: + return; + default: + Error ("TBS decoding error"); + } + fprintf (f, "tbs:=%s ", s); +} + +void +ERWTDLMRL (void) +{ + if (~inst & (1L << 29)) + fprintf (f, "write_mer "); + if (~inst & (1L << 18)) + fprintf (f, "neg_tdl "); + if (~inst & (1L << 17)) + fprintf (f, "neg_mrl "); +} + +void +PSC (void) +{ + char *s=NULL; + + switch (I (7, 6)) + { + case 0: + s = "PAC"; + break; + case 1: + s = "high"; + break; + case 2: + s = "low"; + break; + case 3: + return; + default: + Error ("PSC decoding error"); + } + fprintf (f, "pin:=%s ", s); +} + +void +PAC (void) +{ + char *s=NULL; + + switch (I (11, 9)) + { + case 0: + s = "off"; + break; + case 1: + s = "high"; + break; + case 2: + s = "low"; + break; + case 3: + s = "h+l"; + break; + case 4: + case 5: + case 6: + case 7: + return; + default: + Error ("PAC decoding error"); + } + fprintf (f, "pac:=%s ", s); +} + +void +FLC (int pos) /* at position 5 or 15 */ +{ + char *s=NULL; + + fprintf (f, "chan "); + switch (I (pos, pos - 2)) + { + case 0: + s = "clr cflg0"; + break; + case 1: + s = "set cflg0"; + break; + case 2: + s = "clr cflg1"; + break; + case 3: + s = "set cflg1"; + break; + case 4: + case 5: + case 6: + case 7: + return; + default: + Error ("FLC decoding error"); + } + fprintf (f, "%s ", s); +} + +void +LSL (int pos) /* at position 8 or 12 */ +{ + if (~inst & (1L << pos)) + fprintf (f, "neg_lsr "); +} + +void +CIR (void) +{ + if (~inst & (1L << 2)) + fprintf (f, "pir "); +} + +void +CCM (void) +{ + if (~inst & (1L << 2)) + fprintf (f, "by_p "); +} + +void +MTD (void) +{ + char *s=NULL; + + switch (I (1, 0)) + { + case 0: + s = "en"; + break; + case 1: + s = "ds"; + break; + case 2: + case 3: + return; + default: + Error ("MTD decoding error"); + } + fprintf (f, "%ssr ", s); +} + +void +sep (void) +{ + fprintf (f, "; "); +} + +void +DisInst (unsigned long i, FILE * fp) +{ + f = fp; + inst = i; + + if (inst != 0xffffffff) + switch (inst >> 30 & 3) /* type of instruction */ + { + case 0: /* format 1 */ + T3ABD (); + SHF (); + T1ABS (); + T1BBSetc (); + SRCCCL (); + sep (); + IOMetc (29); + DECEND (); + break; + case 1: /* format 2 */ + T3ABD (); + SHF (); + T1ABS (); + T1BBSetc (); + sep (); + FLC (5); + ERWTDLMRL (); + PAC (); + LSL (8); + PSC (); + CIR (); + sep (); + DECEND (); + break; + case 2: /* format 3 */ + CJCetc (); + FLC (5); + TBS (); + PAC (); + PSC (); + CCM (); + MTD (); + break; + case 3: + if (inst & (1L << 29)) /* format 5 */ + { + T3ABD (); + SHF (); + T1ABS (); + T1BBI (); + SRCCCL (); + sep (); + FLC (5); + LSL (8); + CIR (); + sep (); + } + else /* format 4 */ + { + NMAetc (); + FLC (15); + LSL (12); + sep (); + IOMetc (28); + } + DECEND (); + break; + default: + Error ("format decoding error"); + } + fprintf (f, "\n"); +} + +#if 0 +void +EntryPoint (unsigned int ep) +{ + int pc; + + pc = ep & 0x1FF; + + if (ep >> 9 & 3 == 0) + { + fprintf (f, "Error in EntryPoint format\n"); + } + else + { + fprintf (f, "PreLoad=%d ME=%d PPD=%4s PC=$%03x\n", + ep >> 13 & 7, + ep & (1L << 12) ? 1 : 0, ep & (1L << 11) ? "DIOB" : "P", pc); + epCnt[pc]++; + } +} + +#endif diff --git a/m683xx/gdb-5.2.1-bdm-patches-pi1.lsm b/m683xx/gdb-5.2.1-bdm-patches-pi1.lsm new file mode 100644 index 0000000..3ea60ae --- /dev/null +++ b/m683xx/gdb-5.2.1-bdm-patches-pi1.lsm @@ -0,0 +1,28 @@ +Begin4 +Title: gdb-5.2.1-bdm-patches +Version: 1.8.3 +Entered-date: 2002-11-04 +Description: Background Debug Mode interface for Motorola CPU32 and Linux + These are the patches for gdb-5.2.1 to enable remote debugging + for a 683xx target with BDM under Linux and Linux kernel BDM + driver sources. + Patches are usable for insight-5.2.1 as well. + Both Public Domain and ICD interfaces are supported. + * More info can be found at + http://cmp.felk.cvut.cz/~pisa/m683xx/bdm_driver.html + * WWW access to patches + http://cmp.felk.cvut.cz/~pisa/m683xx/ +Keywords: debugger GDB m68k 68332 683xx BDM ICE driver embedded +Author: Scott_Howard-SCN088@email.mot.com + Jeff@RyeHam.EE.Ryerson.Ca (D.Jeff Dionne) + magin@skil.camelot.de (Gunter Magin) + pisa@cvlinux.felk.cvut.cz (Pavel Pisa) +Maintained-by: pisa@cvlinux.felk.cvut.cz (Pavel Pisa) +Primary-site: metalab.unc.edu /pub/Linux/devel/debuggers + 320 kB gdb-5.2.1-bdm-patches-pi1.tar.gz +Alternate-site: ftp.cygnus.com /pub/embedded + 320 kB gdb-5.2.1-bdm-patches-pi1.tar.gz +Original-site: freeware.aus.sps.mot.com +Platforms: Linux 2.0.xx, 2.2.yy, 2.4.zz ( last tested 2.4.7 ) +Copying-policy: GPL +End diff --git a/m683xx/gdb-5.2.1-bdm.patch-1 b/m683xx/gdb-5.2.1-bdm.patch-1 new file mode 100644 index 0000000..ad94651 --- /dev/null +++ b/m683xx/gdb-5.2.1-bdm.patch-1 @@ -0,0 +1,4645 @@ +diff -c -r -P gdb-5.2.1.original/gdb/Makefile.in gdb-5.2.1/gdb/Makefile.in +*** gdb-5.2.1.original/gdb/Makefile.in Fri Jul 19 20:22:06 2002 +--- gdb-5.2.1/gdb/Makefile.in Sat Nov 2 17:19:49 2002 +*************** +*** 1049,1054 **** +--- 1049,1059 ---- + mv version.c-tmp version.c + 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 ++ + # c-exp.tab.c is generated in objdir from c-exp.y if it doesn't exist + # in srcdir, then compiled in objdir to c-exp.tab.o. + +*************** +*** 1200,1205 **** +--- 1205,1211 ---- + remote-adapt.c remote-array.c remote-bug.c remote-e7000.c remote-eb.c \ + remote-es.c remote-hms.c remote-mips.c \ + remote-mm.c remote-nindy.c remote-os9k.c remote-rdp.c remote-sim.c \ ++ remote-bdm.c \ + remote-st.c remote-utils.c dcache.c \ + remote-udi.c remote-vx.c remote-vx29k.c \ + rs6000-nat.c rs6000-tdep.c \ +*************** +*** 1916,1921 **** +--- 1922,1930 ---- + + # OBSOLETE remote-mm.o: remote-mm.c $(bfd_h) $(defs_h) $(inferior_h) \ + # OBSOLETE minimon.h $(target_h) $(terminal_h) $(gdb_string_h) $(regcache_h) ++ ++ remote-bdm.o: remote-bdm.c bdmlib.h bdmflash.h bdm.h gdb_wait.h \ ++ $(command_h) $(defs_h) $(gdbcore_h) target.h + + remote-nindy.o: remote-nindy.c $(floatformat_h) $(command_h) \ + $(defs_h) $(gdbcore_h) $(inferior_h) \ +diff -c -r -P gdb-5.2.1.original/gdb/bdm.h gdb-5.2.1/gdb/bdm.h +*** gdb-5.2.1.original/gdb/bdm.h Sat Nov 2 17:19:49 2002 +--- gdb-5.2.1/gdb/bdm.h Sat Nov 2 17:19:49 2002 +*************** +*** 0 **** +--- 1,115 ---- ++ #ifndef LINUX_BDM_H ++ #define LINUX_BDM_H ++ /* ++ * $Id: gdb-5.2.1-bdm.patch-1,v 1.1 2003/06/04 01:31:31 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.2.1.original/gdb/bdmflash.c gdb-5.2.1/gdb/bdmflash.c +*** gdb-5.2.1.original/gdb/bdmflash.c Sat Nov 2 17:19:49 2002 +--- gdb-5.2.1/gdb/bdmflash.c Sat Nov 2 17:19:49 2002 +*************** +*** 0 **** +--- 1,684 ---- ++ /******************************************************************* ++ 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 ++ */ ++ ++ #include ++ #include "bdm.h" ++ #include "bdmlib.h" ++ #include "bdmflash.h" ++ ++ /* predefined flash algorithms metods */ ++ ++ int bdmflash_check_id_x16(flash_alg_info_t const *alg, void *addr, u_int16_t retid[2]); ++ int bdmflash_prog_x16(flash_alg_info_t const *alg, void *addr, u_int16_t val); ++ int bdmflash_erase_x16(flash_alg_info_t const *alg, void *addr, long size); ++ ++ int bdmflash_check_id_x8(flash_alg_info_t const *alg, void *addr, u_int16_t retid[2]); ++ int bdmflash_prog_x8(flash_alg_info_t const *alg, void *addr, u_int16_t val); ++ int bdmflash_erase_x8(flash_alg_info_t const *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_x16x2={ ++ 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" ++ }; ++ ++ /* please keep sorted by flash sizes, smallest first */ ++ flash_alg_info_t *flash_alg_infos_def[]={ ++ &amd_29f010_x8x2, ++ &amd_29f040_x8, ++ &amd_29f400_x16, ++ &amd_29f800_x16, ++ &at_49f040_x16x2, ++ NULL ++ }; ++ ++ flash_alg_info_t **flash_alg_infos=flash_alg_infos_def; ++ ++ #if 0 ++ #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_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 ++ ++ /*******************************************************************/ ++ /* routines for 16 bit wide Intel or AMD flash or two interleaved ++ 8 bit flashes */ ++ ++ int bdmflash_check_id_x16(flash_alg_info_t const *alg, void *addr, u_int16_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_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: ++ fprintf(stderr, "bdm memory access error\n"); ++ return -5; ++ } ++ ++ int bdmflash_prog_x16(flash_alg_info_t const *alg, void *addr, u_int16_t val) ++ { ++ int ret=0; ++ u_int16_t old,new,fault; ++ caddr_t a=(caddr_t)((u_int32_t)addr&~alg->addr_mask); ++ /* check if programming needed */ ++ 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--; ++ return ret; ++ ++ mem_op_error: ++ fprintf(stderr, "bdm memory access error\n"); ++ return -5; ++ } ++ ++ int bdmflash_erase_x16(flash_alg_info_t const *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: ++ fprintf(stderr, "bdm memory access error\n"); ++ return -5; ++ } ++ ++ /*******************************************************************/ ++ /* routines for single 8 bit wide Intel or AMD flash */ ++ ++ int bdmflash_check_id_x8(flash_alg_info_t const *alg, void *addr, ++ u_int16_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: ++ fprintf(stderr, "bdm memory access error\n"); ++ return -5; ++ } ++ ++ int bdmflash_prog_x8(flash_alg_info_t const *alg, void *addr, u_int16_t val) ++ { ++ int ret=0; ++ u_int8_t old,new; ++ caddr_t a=(caddr_t)((u_int32_t)addr&~alg->addr_mask); ++ val=(u_int8_t)val; ++ /* check if programming needed */ ++ 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--; ++ return ret; ++ ++ mem_op_error: ++ fprintf(stderr, "bdm memory access error\n"); ++ return -5; ++ } ++ ++ int bdmflash_erase_x8(flash_alg_info_t const *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: ++ fprintf(stderr, "bdm memory access error\n"); ++ return -5; ++ } ++ ++ ++ /*******************************************************************/ ++ ++ /* flash type independent check_id */ ++ int bdmflash_check_id(flash_alg_info_t const *alg, void *addr, u_int16_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(flash_alg_info_t const *alg, void *addr, u_int16_t val) ++ { ++ if(alg->prog) ++ return alg->prog(alg,addr,val); ++ else ++ return -10; ++ } ++ ++ /* flash type independent erase region */ ++ int bdmflash_erase(flash_alg_info_t const *alg, void *addr, long size) ++ { ++ if(alg->erase) ++ return alg->erase(alg,addr,size); ++ else ++ return -10; ++ } ++ ++ flash_alg_info_t const * ++ bdmflash_alg_from_id(u_int16_t id[2]) ++ { ++ int i; ++ flash_alg_info_t const *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; ++ } ++ ++ flash_alg_info_t const * ++ bdmflash_alg_probe(caddr_t flash_adr) ++ { ++ int i; ++ flash_alg_info_t const *alg,*alg1; ++ u_int16_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; ++ u_int16_t val; ++ flash_alg_info_t const *alg=(flash_alg_info_t*)filt->info; ++ ++ 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; ++ } ++ }else{ ++ /* 8 bit wide flash write path */ ++ while(size>=1) { ++ val=bl_ptr[offs]; ++ 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+=1; ++ size-=1; ++ offs+=1; ++ } ++ } ++ return offs; ++ ++ mem_op_error: ++ fprintf(stderr, "bdm memory access error\n"); ++ return 0; ++ } ++ ++ int ++ bdmflash_erase_filt(bdmlib_bfilt_t * filt, caddr_t in_adr, ++ u_int size) ++ { ++ int res=0; ++ flash_alg_info_t const *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 1 ++ #define FLASH_ALG_BITS_x8x2 2 ++ ++ /* 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)(struct flash_alg_info const *alg, void *addr, u_int16_t retid[2]); ++ /* Programs one location of flash (16 bits for width=1 or 2; 8 bits for width8=0) */ ++ int (*prog)(struct flash_alg_info const *alg, void *addr, u_int16_t val); ++ /* 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)(struct flash_alg_info const *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 */ ++ u_int16_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 */ ++ u_int16_t cmd_unlock1;/* first byte of command sequence */ ++ u_int16_t cmd_unlock2;/* second byte of command sequence */ ++ u_int16_t cmd_rdid; /* read identifier */ ++ u_int16_t cmd_prog; /* program one loc */ ++ u_int16_t cmd_erase; /* erase command */ ++ u_int16_t cmd_reset; /* leave program mode */ ++ u_int16_t erase_all; /* erase all */ ++ u_int16_t erase_sec; /* erase sector */ ++ u_int16_t fault_bit; /* programing of location failed */ ++ u_int16_t manid; /* manufacturer ID */ ++ u_int16_t devid; /* device ID */ ++ char *alg_name; /* informative flash type name */ ++ } flash_alg_info_t; ++ ++ int bdmflash_check_id(flash_alg_info_t const *alg, void *addr, ++ u_int16_t retid[2]); ++ ++ int bdmflash_prog(flash_alg_info_t const *alg, void *addr, u_int16_t val); ++ ++ int bdmflash_erase(flash_alg_info_t const *alg, void *addr, long size); ++ ++ flash_alg_info_t **flash_alg_infos; ++ ++ flash_alg_info_t const *bdmflash_alg_from_id(u_int16_t id[2]); ++ ++ flash_alg_info_t const *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); ++ ++ #endif /* BDMFLASH_H */ +diff -c -r -P gdb-5.2.1.original/gdb/bdmlib.c gdb-5.2.1/gdb/bdmlib.c +*** gdb-5.2.1.original/gdb/bdmlib.c Sat Nov 2 17:19:49 2002 +--- gdb-5.2.1/gdb/bdmlib.c Sat Nov 2 17:19:49 2002 +*************** +*** 0 **** +--- 1,1634 ---- ++ /* ++ * $Id: gdb-5.2.1-bdm.patch-1,v 1.1 2003/06/04 01:31:31 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 ++ ++ /* 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. */ ++ ++ #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; ++ 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_reset(void) ++ { ++ #if SUPPORT_RAMINIT ++ u_long dummy; ++ #endif ++ 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); ++ ++ /* ++ * 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, &dummy)) < 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; ++ 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, (u_int *) & 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, (u_int *) & 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, (u_int *) & 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, (u_int *) & 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(FILE * fp) ++ { ++ static char *str = "\\|/-"; ++ static int index; ++ ++ if (!hashmark) return; ++ fprintf(fp, "%c\b", str[index++]); ++ 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_fd; ++ } ++ 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; ++ bfd_vma addr1, addr2; ++ u_int size; ++ int 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))) { ++ bdmlib_propeller(stdout); ++ ++ sscanf(lptr, "%c %i %i %i", ++ &cmd, (unsigned int *) &addr1, (unsigned int *) &addr2, &size); ++ 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; ++ #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"); ++ 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 %d cooked_size %d\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(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, u_long *entry_pt) ++ { ++ bfd *abfd; ++ int ret; ++ ++ if ((abfd = prepare_binary(file_name)) == NULL) ++ return BDM_ERR_OPEN; ++ *entry_pt = bfd_get_start_address(abfd); ++ 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"); ++ 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, u_long * entry_pt) ++ { ++ int ret = 0; ++ u_int sfc, dfc; ++ int we_have_macro_files = 0; ++ #if SUPPORT_RAMINIT ++ u_long dummy; ++ #endif ++ ++ 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, &dummy)) < 0) { ++ error("ram_init load error.\n"); ++ } ++ #endif /* SUPPORT_RAMINIT */ ++ ++ if ((ret = bdmlib_do_load_binary(file, 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.2.1.original/gdb/bdmlib.h gdb-5.2.1/gdb/bdmlib.h +*** gdb-5.2.1.original/gdb/bdmlib.h Sat Nov 2 17:19:49 2002 +--- gdb-5.2.1/gdb/bdmlib.h Sat Nov 2 17:19:49 2002 +*************** +*** 0 **** +--- 1,81 ---- ++ /* ++ * $Id: gdb-5.2.1-bdm.patch-1,v 1.1 2003/06/04 01:31:31 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, u_long *entry_pt); ++ extern int bdmlib_do_load_binary(char *file_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_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(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.2.1.original/gdb/blockframe.c gdb-5.2.1/gdb/blockframe.c +*** gdb-5.2.1.original/gdb/blockframe.c Wed Feb 27 21:04:29 2002 +--- gdb-5.2.1/gdb/blockframe.c Sat Nov 2 17:19:49 2002 +*************** +*** 239,245 **** + struct frame_info * + get_next_frame (struct frame_info *frame) + { +! return frame->next; + } + + /* Flush the entire frame cache. */ +--- 239,249 ---- + 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.2.1.original/gdb/config/m68k/bdm.mt gdb-5.2.1/gdb/config/m68k/bdm.mt +*** gdb-5.2.1.original/gdb/config/m68k/bdm.mt Sat Nov 2 17:19:49 2002 +--- gdb-5.2.1/gdb/config/m68k/bdm.mt Sat Nov 2 17:19:49 2002 +*************** +*** 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.2.1.original/gdb/config/m68k/tm-bdm.h gdb-5.2.1/gdb/config/m68k/tm-bdm.h +*** gdb-5.2.1.original/gdb/config/m68k/tm-bdm.h Sat Nov 2 17:19:49 2002 +--- gdb-5.2.1/gdb/config/m68k/tm-bdm.h Sat Nov 2 17:19:49 2002 +*************** +*** 0 **** +--- 1,135 ---- ++ /* 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} ++ ++ #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 ++ #define REGISTER_BYTES (16*4 + 8 + 9*4 + 8*12 + 3*4) ++ ++ /* ++ * 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 ++ #define REGISTER_BYTES (16*4 + 2*4 + 9*4 + 8*12 + 3*4) ++ /* 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 ++ /* ++ * 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.2.1.original/gdb/configure.tgt gdb-5.2.1/gdb/configure.tgt +*** gdb-5.2.1.original/gdb/configure.tgt Wed May 29 04:36:55 2002 +--- gdb-5.2.1/gdb/configure.tgt Sat Nov 2 17:19:49 2002 +*************** +*** 159,164 **** +--- 159,165 ---- + 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.2.1.original/gdb/m68k-tdep.c gdb-5.2.1/gdb/m68k-tdep.c +*** gdb-5.2.1.original/gdb/m68k-tdep.c Sun Dec 2 00:06:46 2001 +--- gdb-5.2.1/gdb/m68k-tdep.c Sat Nov 2 17:19:49 2002 +*************** +*** 183,189 **** + 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); + } + +--- 183,192 ---- + 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); + } + +*************** +*** 211,216 **** +--- 214,220 ---- + get_frame_saved_regs (frame, &fsr); + for (regnum = FP0_REGNUM + 7; regnum >= FP0_REGNUM; regnum--) + { ++ if(regnum >= NUM_REGS) continue; + if (fsr.regs[regnum]) + { + read_memory (fsr.regs[regnum], raw_buffer, 12); +*************** +*** 377,383 **** + /* Regmask's low bit is for register fp7, the first pushed */ + for (regnum = FP0_REGNUM + 8; --regnum >= FP0_REGNUM; regmask >>= 1) + if (regmask & 1) +! saved_regs->regs[regnum] = (next_addr -= 12); + pc += 4; + } + /* fmovemx to (fp + displacement) */ +--- 381,391 ---- + /* 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) +! saved_regs->regs[regnum] = next_addr; +! } + pc += 4; + } + /* fmovemx to (fp + displacement) */ +*************** +*** 390,396 **** + for (regnum = FP0_REGNUM + 8; --regnum >= FP0_REGNUM; regmask >>= 1) + if (regmask & 1) + { +! saved_regs->regs[regnum] = addr; + addr += 12; + } + pc += 6; +--- 398,405 ---- + for (regnum = FP0_REGNUM + 8; --regnum >= FP0_REGNUM; regmask >>= 1) + if (regmask & 1) + { +! if(regnum < NUM_REGS) +! saved_regs->regs[regnum] = addr; + addr += 12; + } + pc += 6; +*************** +*** 445,451 **** + for (regnum = FP0_REGNUM + 8; --regnum >= FP0_REGNUM; regmask >>= 1) + if (regmask & 1) + { +! saved_regs->regs[regnum] = next_addr; + next_addr += 12; + } + pc += 10; +--- 454,461 ---- + for (regnum = FP0_REGNUM + 8; --regnum >= FP0_REGNUM; regmask >>= 1) + if (regmask & 1) + { +! if(regnum < NUM_REGS) +! saved_regs->regs[regnum] = next_addr; + next_addr += 12; + } + pc += 10; +diff -c -r -P gdb-5.2.1.original/gdb/monitor.c gdb-5.2.1/gdb/monitor.c +*** gdb-5.2.1.original/gdb/monitor.c Sun Feb 10 05:08:41 2002 +--- gdb-5.2.1/gdb/monitor.c Sat Nov 2 17:19:49 2002 +*************** +*** 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.2.1.original/gdb/remote-bdm.c gdb-5.2.1/gdb/remote-bdm.c +*** gdb-5.2.1.original/gdb/remote-bdm.c Sat Nov 2 17:19:49 2002 +--- gdb-5.2.1/gdb/remote-bdm.c Sat Nov 2 17:19:49 2002 +*************** +*** 0 **** +--- 1,1676 ---- ++ /* ++ * $Id: gdb-5.2.1-bdm.patch-1,v 1.1 2003/06/04 01:31:31 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. ++ ++ */ ++ ++ #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; ++ static u_long entry_pt; ++ 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 */ ++ #define BDM_DEFAULT_DELAY 75 ++ ++ #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) 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 ((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) ++ { ++ char *dummy; ++ ++ bdmlib_log("bdm_setentry_interactive: arg <%s> from_tty %d\n", ++ arg, from_tty); ++ bdm_check_fd(); ++ if (!arg) { ++ printf_filtered("current entry point is %#lx\n", entry_pt); ++ } else { ++ entry_pt = strtol(arg, &dummy, 0); ++ } ++ } ++ ++ /* ++ * 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(); ++ ++ 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; ++ ++ 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; ++ if (( ret = bdmlib_load(prg_file, &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) ++ error("No entry point defined, cannot start program."); ++ ++ 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(entry_pt, 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("\ ++ 'load' must be called together with the filename to load.\n\ ++ You may want to use 'run', which uses the parameter supplied when gdb ++ 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, &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.2.1.original/gdb/target.c gdb-5.2.1/gdb/target.c +*** gdb-5.2.1.original/gdb/target.c Fri Feb 1 02:01:21 2002 +--- gdb-5.2.1/gdb/target.c Sat Nov 2 17:19:49 2002 +*************** +*** 248,253 **** +--- 248,255 ---- + return 0; /* No bytes handled */ + } + ++ char hashmark; ++ + static void + tcomplain (void) + { diff --git a/m683xx/gdb-5.3-bdm-683xx-patch b/m683xx/gdb-5.3-bdm-683xx-patch new file mode 100644 index 0000000..b06d666 --- /dev/null +++ b/m683xx/gdb-5.3-bdm-683xx-patch @@ -0,0 +1,5240 @@ +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) + { diff --git a/m683xx/insight-5.3-bdm-683xx-patch b/m683xx/insight-5.3-bdm-683xx-patch new file mode 100644 index 0000000..eb56cbf --- /dev/null +++ b/m683xx/insight-5.3-bdm-683xx-patch @@ -0,0 +1,41 @@ +diff -Nurd insight-5.3.orig/gdb/gdbtk/generic/gdbtk-hooks.c insight-5.3.patched/gdb/gdbtk/generic/gdbtk-hooks.c +--- insight-5.3.orig/gdb/gdbtk/generic/gdbtk-hooks.c 2002-07-03 19:38:22.000000000 +0200 ++++ insight-5.3.patched/gdb/gdbtk/generic/gdbtk-hooks.c 2003-09-05 14:02:42.000000000 +0200 +@@ -518,6 +518,10 @@ + gdbtk_call_command (struct cmd_list_element *cmdblk, + char *arg, int from_tty) + { ++ struct cleanup *old_chain; ++ ++ old_chain = make_cleanup (null_cleanup, 0); ++ + running_now = 0; + if (cmdblk->class == class_run || cmdblk->class == class_trace) + { +@@ -532,6 +536,8 @@ + } + else + cmd_func (cmdblk, arg, from_tty); ++ ++ do_cleanups (old_chain); + } + + /* Called after a `set' command succeeds. Runs the Tcl hook +diff -Nurd insight-5.3.orig/gdb/gdbtk/library/targetselection.itb insight-5.3.patched/gdb/gdbtk/library/targetselection.itb +--- insight-5.3.orig/gdb/gdbtk/library/targetselection.itb 2002-02-12 21:05:14.000000000 +0100 ++++ insight-5.3.patched/gdb/gdbtk/library/targetselection.itb 2003-09-05 14:02:57.000000000 +0200 +@@ -261,6 +261,14 @@ + set gdb_target(vxworks,cmd) "vxworks ethX" + set gdb_target(vxworks,runlist) { 1 0 1 1} + set gdb_target(vxworks,after_attaching) { sym vxWorks.st } ++ ++ # BDM ++ set gdb_target(bdm,pretty-name) "BDM" ++ set gdb_target(bdm,defbaud) "" ++ set gdb_target(bdm,baud-rates) {} ++ set gdb_target(bdm,cmd) "bdm /dev/icd_bdm0" ++ set gdb_target(bdm,runlist) {1 0 1 0} ++ set gdb_target(bdm,after_attaching) "reset" + } + + body TargetSelection::default_port {} { diff --git a/m683xx/scripts/profi360.gdb b/m683xx/scripts/profi360.gdb new file mode 100644 index 0000000..21f3652 --- /dev/null +++ b/m683xx/scripts/profi360.gdb @@ -0,0 +1,221 @@ +# invoke by "source run376.gdb" + +echo Setting bdm\n + +file m.out + +target bdm /dev/bdm +#target bdm /dev/icd_bdm0 +#target bdm /dev/pd_bdm0 + +#=========================================================== +# sets chipselects and configuration + +define set_CS_BR + #$arg0 = BA31-BA11 + #$arg1 = Offset From REGB + set *(unsigned int*)($ptr_REGB+$arg1) = ((unsigned int)$arg0)+1 + #p /ox *(unsigned int*)($ptr_REGB+$arg1) +end + +define set_CS_OR + #$arg0 = AM27-AM11 + #$arg1 = Number Of Wait States + #$arg2 = Sram Port Size + #$arg3 = Offset From REGB + set *(unsigned int*)($ptr_REGB+$arg3) = $arg0+(($arg1+1) << 28)+($arg2 << 1) + #p /ox *(unsigned int*)($ptr_REGB+$arg3) +end + +define bdm_hw_init +echo bdm_hw_init ...\n + +set remotecache off +bdm_timetocomeup 0 +bdm_autoreset off +bdm_setdelay 70 +bdm_reset +bdm_setdelay 0 +set $sfc=5 +set $dfc=5 + + +# system configuration + +# MBAR Module Base Address Register +# 31 30 13 12 11 10 9 8 1 0 +# BA31 BA30 .... BA13 0 0 0 AS8 AS7 ... AS0 V +# BA = BaseAddress +# AS = Address Space = Maskovani adresniho prostoru +# V = data valid +# set *(unsigned int *)0x0003ff00=0 +set $sfc=7 +set $dfc=7 +set $ptr_MBAR = (unsigned int *)0x0003ff00 +set *$ptr_MBAR = 0x0ffffe001 +set $ptr_DPRBASE = (unsigned char *)0x0ffffe000 +set $ptr_REGB = $ptr_DPRBASE + 0x1000 +set $sfc=5 +set $dfc=5 + + +#diody +set $ptr_PADIR = (unsigned short *)($ptr_REGB + 0x550) +set *$ptr_PADIR = 0xf000 +set $ptr_PAPAR = (unsigned short *)($ptr_REGB + 0x552) +set *$ptr_PAPAR = 0 +set $ptr_PAODR = (unsigned short *)($ptr_REGB + 0x554) +set *$ptr_PAODR = 0xffff +set $ptr_PADAT = (unsigned short *)($ptr_REGB + 0x556) +set *$ptr_PADAT = 0xefff + +# MCR Module Configuration Register - urcuje, zda konfigurace SIM60 se muze cist/zapisovat kdykoli +# 31 30 29 28 ... 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 0 +# BR040ID2-BR040ID0 - - BSTM ASTM FRZ1-FRZ0 BCLROID2-BCLOID0 SHEN1-SHEN0 SUPV BCLRISM2-BCLRISM0 IARB3-IARB0 +# nebo BCLRIID2-BCLRIID0 +# 0 0 0 - - 0 0 ? ? +set *(unsigned int *)($ptr_REGB + 0x000) = 0x00006c7f +#set *(unsigned int *)($ptr_REGB + 0x000) = 0x00006c71 + +#PEPAR config +set *(unsigned short*)($ptr_REGB + 0x16) = 0x0080 + +#GMR +set *(unsigned int *)($ptr_REGB + 0x40) = 0x00001100 + +#SYPCR +set *($ptr_REGB + 0x22) = 0x03 + +#settings for chip selects + +#set_CS_BR BaseAddress OffsetFromREGB +#set_CS_OR AddressMask NumberOfWaitStates(0-14) SramPortSize OffsetFromREGB + +#CS0 - BootFlash 1 MB - 16Bit +set_CS_BR 0x0000000 0x50 +set_CS_OR 0xff00000 0 1 0x54 + +#CS1 - Flash 2MB - 32Bit +set_CS_BR 0x0200000 0x60 +set_CS_OR 0xfe00000 0 0 0x64 + +#CS7 - SRAM 2 MB - 32Bit +set_CS_BR 0x0400000 0xc0 +set_CS_OR 0xfe00000 0 0 0xc4 + +#CS6 - USB Chip - 8Bit +set_CS_BR 0x0800000 0xb0 +set_CS_OR 0xf800000 0 2 0xb4 + + + + +# CPU registers + +# SR=PS Status Register +# 15 14 13 12 11 10 8 7 6 5 4 3 2 1 0 +# T1 T0 S 0 0 IP___ 0 0 0 X N Z V C +# 0 0 1 0 0 1 1 1 0 0 0 U U U U U + +bdm_setdelay 1 + +bdm_status + +end +#=========================================================== + +# sets well defined values into VBR +define vbr_set_all + set $vec_num=0 + set $vbr_val=(unsigned)$vbr + while $vec_num<256 + set *(unsigned*)($vbr_val+$vec_num*4)=($vec_num*16)+0xf0000 + set $vec_num++ + end +end + +# Test writability of RAM location +define bdm_test_ram_acc + echo testing ... + p /x $arg0 + set $ram_addr=(unsigned int)$arg0 + set $old_ram_val=*(int*)$ram_addr + set *(int*)$ram_addr=0x12345678 + if *(int*)$ram_addr!=0x12345678 + echo Error1\n + end + set *(char*)$ram_addr=0xab + if *(int*)$ram_addr!=0xab345678 + echo Error2\n + end + set *(char*)($ram_addr+1)=0xcd + if *(int*)$ram_addr!=0xabcd5678 + echo Error3\n + end + set *(char*)($ram_addr+3)=0x01 + if *(int*)$ram_addr!=0xabcd5601 + echo Error4\n + end + set *(char*)($ram_addr+2)=0xef + if *(int*)$ram_addr!=0xabcdef01 + echo Error5\n + end + set *(int*)$ram_addr=$old_ram_val +end + +# Read flash identification +define bdm_read_flash_id + set $flash_base=(int)$arg0&~0xffff + output /x $flash_base + echo \n + set *(char*)($flash_base+0x555*2+1)=0xf0 + set *(char*)($flash_base+0x555*2+1)=0xaa + set *(char*)($flash_base+0x2aa*2+1)=0x55 + set *(char*)($flash_base+0x555*2+1)=0x90 + p /x *(char*)($flash_base+0x00*2+1) + set *(char*)($flash_base+0x555*2+1)=0xf0 + set *(char*)($flash_base+0x555*2+1)=0xaa + set *(char*)($flash_base+0x2aa*2+1)=0x55 + set *(char*)($flash_base+0x555*2+1)=0x90 + p /x *(char*)($flash_base+0x01*2+1) +end + +define bdm_read_flash1_id + bdm_read_flash_id 0x800000 +end + +define bdm_read_flash2_id + bdm_read_flash_id 0x900000 +end + +define bdm_test_flash_write +# set $flash_base=(int)$arg0 & ~0xfffff + set $flash_base=(int)$arg0 + output /x $flash_base + echo \n +# set *(char*)($flash_base+0x5555*2+1)=0xf0 +# set *(short*)($flash_base+0x25554)=0xaaaa +# set *(short*)($flash_base+0x02aaa)=0x5555 +# set *(short*)($flash_base+0x25554)=0xA0A0 + set *(short*)(0x825554)=0xf0f0 + set *(short*)(0x825554)=0xaaaa + set *(short*)(0x802aaa)=0x5555 + set *(short*)(0x825554)=0xA0A0 + set *(short*)($arg0)=$arg1 +end + + +bdm_hw_init + +b do_trap_break +b exception_hook_nop +#b profi_rx_internal +#b write +#b smc_uart_tx +#b smc_interrupt +#b quicc_init + +b main + +#run + diff --git a/m683xx/scripts/run332.gdb b/m683xx/scripts/run332.gdb new file mode 100644 index 0000000..3a174c8 --- /dev/null +++ b/m683xx/scripts/run332.gdb @@ -0,0 +1,335 @@ +# invoke by "source run376.gdb" + +echo Setting bdm\n + +#set prompt (gdb68) + +file tst + +target bdm /dev/bdm +#target bdm /dev/icd_bdm0 +#target bdm /dev/pd_bdm0 + +#=========================================================== +# sets chipselects and configuration +define bdm_hw_init +echo bdm_hw_init ...\n + +set remotecache off +bdm_timetocomeup 0 +bdm_autoreset off +bdm_setdelay 100 +bdm_reset +bdm_setdelay 0 +set $sfc=5 +set $dfc=5 + +# system configuration + +# 0xFFFA00 - SIMCR - SIM Configuration Register +# 15 14 13 12 11 10 9 8 7 6 5 4 3 0 +# EXOFF FRZSW FRZBM 0 SLVEN 0 SHEN SUPV MM 0 0 IARB +# 0 0 0 0 DATA11 0 0 0 1 1 0 0 1 1 1 1 +set *(short *)0xfffa00=0x42cf + +# 0xFFFA21 - SYPCR - System Protection Control Register +# 7 6 5 4 3 2 1 0 +# SWE SWP SWT HME BME BMT +# 1 MODCLK 0 0 0 0 0 0 +set *(char *)0xfffa21=0x06 + +# 0xYFFA27 - SWSR - Software Service Register +# write 0x55 0xAA for watchdog + +# 0xFFFA04 - SYNCR Clock Synthesizer Control Register +# 15 14 13 8 7 6 5 4 3 2 1 0 +# W X Y EDIV 0 0 SLIMP SLOCK RSTEN STSIM STEXT +# 0 0 1 1 1 1 1 1 0 0 0 U U 0 0 0 +set *(short *)0xfffa04=0x7f00 + +# $YFFA17 - PEPAR - Port E Pin Assignment Register +# 7 6 5 4 3 2 1 0 +# PEPA7 PEPA6 PEPA5 PEPA4 PEPA3 PEPA2 PEPA1 PEPA0 +# SIZ1 SIZ0 AS DS RMC AVEC DSACK1 DSACK0 +# 1 .. control signal, 0 .. port F +# after reset determined by DATA8 +set *(char*)0xfffa17=0xf4 + +# 0xFFFA1F - PFPAR - Port F Pin Assignment Register +# 7 6 5 4 3 2 1 0 +# PFPA7 PFPA6 PFPA5 PFPA4 PFPA3 PFPA2 PFPA1 PFPA0 +# INT7 INT6 INT5 INT4 INT3 INT2 INT1 MODCLK +# 1 .. control signal, 0 .. port F +# after reset determined by DATA9 +set *(char*)0xfffa1f=0 + +# Setup internal RAM + +# setup TPU RAM at 0x8000 +# TRAMMCR +set *(short *)0xFFFB00=0x8000 +# TRAMBAR +set *(short *)0xFFFB04=0xFFE000>>8 +# TRAMMCR +set *(short *)0xFFFB00=0 + +# 0xYFFA44 - CSPAR0 - Chip Select Pin Assignment Register 0 +# 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 +# 0 0 CSPA0[6] CSPA0[5] CSPA0[4] CSPA0[3] CSPA0[2] CSPA0[1] CSBOOT +# 0 0 DATA2 1 DATA2 1 DATA2 1 DATA1 1 DATA1 1 DATA1 1 1 DATA0 +# CS5 CS4 CS3 CS2 CS1 CS0 CSBOOT +# FC2 PC2 FC1 PC1 FC0 PC0 BGACK BG BR +# +# 00 Discrete Output +# 01 Alternate Function +# 10 Chip Select (8-Bit Port) +# 11 Chip Select (16-Bit Port) +# +set *(short *)0xfffa44=0x3fff + + +# 0xFFFA46 - CSPAR1 - Chip Select Pin Assignment Register 1 +# 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 +# 0 0 0 0 0 0 CSPA1[4] CSPA1[3] CSPA1[2] CSPA1[1] CSPA1[0] +# 0 0 0 0 0 0 DATA7 1 DATA76 1 DATA75 1 DATA74 1 DATA73 1 +# CS10 CS9 CS8 CS7 CS6 +# A23 ECLK A22 PC6 A21 PC5 A20 PC4 A19 PC3 +# +set *(short *)0xfffa46=0x03ff + +# +# Chip selects configuration +# +# 0xFFFA48 - CSBARBT - Chip-Select Base Address Register Boot ROM +# 0xFFFA4C..0xFFFA74 - CSBAR[10:0] - Chip-Select Base Address Registers +# 15 14 13 12 11 10 9 8 7 6 5 4 3 2 0 +# A23 A22 A21 A20 A19 A18 A17 A16 A15 A14 A13 A12 A11 BLKSZ +# reset 0x0003 for CSBARBT and 0x0000 for CSBAR[10:0] +# +# BLKSZ Size Address Lines Compared +# 000 2k ADDR[23:11] +# 001 8k ADDR[23:13] +# 010 16k ADDR[23:14] +# 011 64k ADDR[23:16] +# 100 128k ADDR[23:17] +# 101 256k ADDR[23:18] +# 110 512k ADDR[23:19] +# 111 1M ADDR[23:20] +# +# +# 0xFFFA4A - CSORBT - Chip-Select Option Register Boot ROM +# 0xFFFA4E..0xFFFA76 - CSOR[10:0] - Chip-Select Option Registers +# 15 14 13 12 11 10 9 6 5 4 3 1 0 +# MODE BYTE R/W STRB DSACK SPACE IPL AVEC +# 0 1 1 1 1 0 1 1 0 1 1 1 0 0 0 0 - for CSORBT +# +# BYTE 00 Disable, 01 Lower Byte, 10 Upper Byte, 11 Both Bytes +# R/W 00 Reserved,01 Read Only, 10 Write Only, 11 Read/Write +# SPACE 00 CPU, 01 User, 10 Supervisor, 11 Supervisor/User +# +set *(long *)0xfffa48=0x0e0468b0 +# BOOT ROM 0x0e0000 128k RO UL + +set *(long *)0xfffa4c=0x0003503e +# CS0 RAM 0x000000 64k WR U + +set *(long *)0xfffa50=0x0003303e +# CS1 RAM 0x000000 64k WR L + +set *(long *)0xfffa54=0x0003683e +# CS2 RAM 0x000000 64k RO UL + +set *(long *)0xfffa58=0x00000000 +# CS3 + +set *(long *)0xfffa5C=0xfff8680f +# CS4 + +set *(long *)0xfffa60=0xffe8783f +# CS5 + +set *(long *)0xfffa64=0x100438f0 +# CS6 R/R 0x100000 128k RW L + +set *(long *)0xfffa68=0x100458f0 +# CS7 R/R 0x100000 128k RW U + +set *(long *)0xfffa6c=0x01036870 +# CS8 RAM 0x010000 64k RO UL + +set *(long *)0xfffa70=0x01033030 +# CS9 RAM 0x010000 64k WR L + +set *(long *)0xfffa74=0x01035030 +# CS10 RAM 0x010000 64k WR U + +# +# My change +# +set *(long *)0xfffa58=0x02036870 +# CS3 RAM 0x020000 64k RO UL + +set *(long *)0xfffa64=0x02033030 +# CS6 RAM 0x020000 64k WR L + +set *(long *)0xfffa68=0x02035030 +# CS7 RAM 0x020000 64k WR U + + +# CPU registers + +# SR=PS Status Register +# 15 14 13 12 11 10 8 7 6 5 4 3 2 1 0 +# T1 T0 S 0 0 IP___ 0 0 0 X N Z V C +# 0 0 1 0 0 1 1 1 0 0 0 U U U U U + +bdm_status + +end +#=========================================================== + +# sets well defined values into VBR +define vbr_set_all + set $vec_num=0 + set $vbr_val=(unsigned)$vbr + while $vec_num<256 + set *(unsigned*)($vbr_val+$vec_num*4)=($vec_num*16)+0xf0000 + set $vec_num++ + end +end + +# Test writability of RAM location +define bdm_test_ram_acc + echo testing ... + p /x $arg0 + set $ram_addr=(unsigned int)$arg0 + set $old_ram_val=*(int*)$ram_addr + set *(int*)$ram_addr=0x12345678 + if *(int*)$ram_addr!=0x12345678 + printf "Error1 %08X\n",*(int*)$ram_addr + end + set *(char*)$ram_addr=0xab + if *(int*)$ram_addr!=0xab345678 + printf "Error2 %08X\n",*(int*)$ram_addr + end + set *(char*)($ram_addr+1)=0xcd + if *(int*)$ram_addr!=0xabcd5678 + printf "Error3 %08X\n",*(int*)$ram_addr + end + set *(char*)($ram_addr+3)=0x01 + if *(int*)$ram_addr!=0xabcd5601 + printf "Error4 %08X\n",*(int*)$ram_addr + end + set *(char*)($ram_addr+2)=0xef + if *(int*)$ram_addr!=0xabcdef01 + printf "Error5 %08X\n",*(int*)$ram_addr + end + set *(int*)$ram_addr=$old_ram_val +end + +# Read flash identification +define bdm_read_flash_id + set $flash_base=(int)$arg0&~0xffff + output /x $flash_base + echo \n + set *(char*)($flash_base+0x555*2+1)=0xf0 + set *(char*)($flash_base+0x555*2+1)=0xaa + set *(char*)($flash_base+0x2aa*2+1)=0x55 + set *(char*)($flash_base+0x555*2+1)=0x90 + p /x *(char*)($flash_base+0x00*2+1) + set *(char*)($flash_base+0x555*2+1)=0xf0 + set *(char*)($flash_base+0x555*2+1)=0xaa + set *(char*)($flash_base+0x2aa*2+1)=0x55 + set *(char*)($flash_base+0x555*2+1)=0x90 + p /x *(char*)($flash_base+0x01*2+1) +end + +define bdm_read_flash1_id + bdm_read_flash_id 0x800000 +end + +define bdm_read_flash2_id + bdm_read_flash_id 0x900000 +end + +define bdm_test_flash_write + set $flash_base=(int)$arg0 & ~0xffff + output /x $flash_base + echo \n + set *(char*)($flash_base+0x555*2+1)=0xf0 + set *(char*)($flash_base+0x555*2+1)=0xaa + set *(char*)($flash_base+0x2aa*2+1)=0x55 + set *(char*)($flash_base+0x555*2+1)=0xA0 + set *(char*)($arg0)=$arg1 +end + +define bdm_test_pwm0 + + #BIUMCR - BIU Module Configuration Register $YFF400 + set *(short*)0xfff400=*(short*)0xfff400&~0x8000 + #CPCR - CPSM Control Register $YFF408 + set *(short*)0xfff408=*(short*)0xfff408|8 + #PWM5SIC - PWM5 Status/Interrupt/Control Register $YFF428 + set *(short*)0xfff428=0x18 + #PWM5A1 - PWM5 Period Register $YFF42A + set *(short*)0xfff42a=512 + #PWM5B1 - PWM5 Pulse Width Register $YFF42C + set *(short*)0xfff42c=0 + + if $arg0==0 + set *(short*)0xf87000=0 + set $pwm_val=0 + else + if $arg0>0 + set *(char*)0xf87000=1 + set $pwm_val=$arg0 + else + set *(char*)0xf87000=2 + set $pwm_val=-($arg0) + end + end + #DDRQA + set *(short*)0xfff208=0x8000 + #PORTQA + set *(short*)0xfff206=~0x8000 + + #PWM5B1 - PWM5 Pulse Width Register $YFF42C + set *(short*)0xfff42c=$pwm_val + +end + +define bdm_test_usd_irc + set $usd_irc_d=0xf88000 + set $usd_irc_c=0xf88001 + if $arg0!=0 + # Load Gate + set *(unsigned char*)0xf88020=0 + # CMR + set *(unsigned char*)$usd_irc_c=0x38 + # IOR + set *(unsigned char*)$usd_irc_c=0x49 + # IDR + set *(unsigned char*)$usd_irc_c=0x61 + # RLD - Reset BP, BT CT CPT S + set *(unsigned char*)$usd_irc_c=0x05 + # DATA - PSC + set *(unsigned char*)$usd_irc_d=0x02 + # RLD - Reset BP, PR0 -> PSC + set *(unsigned char*)$usd_irc_c=0x1B + end + # RLD - Reset BP, CNTR -> OL + set *(unsigned char*)$usd_irc_c=0x11 + + set $usd_irc_val=((int)(*(unsigned char*)$usd_irc_d)) + set $usd_irc_val+=((int)(*(unsigned char*)$usd_irc_d))<<8 + set $usd_irc_val+=((int)(*(unsigned char*)$usd_irc_d))<<16 + print /x $usd_irc_val + +end + +bdm_hw_init + +#b main + +#run + diff --git a/m683xx/scripts/run376.gdb b/m683xx/scripts/run376.gdb new file mode 100644 index 0000000..7c665c9 --- /dev/null +++ b/m683xx/scripts/run376.gdb @@ -0,0 +1,394 @@ +# invoke by "source run376.gdb" + +echo Setting bdm\n + +#set prompt (gdb68) + +file tst + +# Linux +target bdm /dev/bdm +#target bdm /dev/m683xx-bdm/icd0 +#target bdm /dev/icd_bdm0 +#target bdm /dev/pd_bdm0 + +# Windows +#target bdm bdm-cpu32-icd1 + +# Serial targets +#target remote COM2 +#target remote /dev/ttyS1 + +# automatic resed of board before "run" command execution +# depends on correct "cpu32init" file in current ditectory +bdm_autoreset on + +# confirmation of dangerous operations (kill, run, ..) +set confirm on + +#=========================================================== +# sets chipselects and configuration +define bdm_hw_init +echo bdm_hw_init ...\n + +set remotecache off +bdm_timetocomeup 0 +bdm_autoreset off +bdm_setdelay 100 +bdm_reset +bdm_setdelay 0 +set $sfc=5 +set $dfc=5 + +# system configuration + +# 0xFFFA00 - SIMCR - SIM Configuration Register +# 15 14 13 12 11 10 9 8 7 6 5 4 3 0 +# EXOFF FRZSW FRZBM 0 SLVEN 0 SHEN SUPV MM 0 0 IARB +# 0 0 0 0 DATA11 0 0 0 1 1 0 0 1 1 1 1 +# set *(short *)0xfffa00=0x42cf +set *(short *)0xfffa00=0x40cf + +# 0xFFFA21 - SYPCR - System Protection Control Register +# 7 6 5 4 3 2 1 0 +# SWE SWP SWT HME BME BMT +# 1 MODCLK 0 0 0 0 0 0 +set *(char *)0xfffa21=0x06 + +# 0xYFFA27 - SWSR - Software Service Register +# write 0x55 0xAA for watchdog + +# 0xFFFA04 - SYNCR Clock Synthesizer Control Register +# 15 14 13 8 7 6 5 4 3 2 1 0 +# W X Y EDIV 0 0 SLIMP SLOCK RSTEN STSIM STEXT +# 0 0 1 1 1 1 1 1 0 0 0 U U 0 0 0 +#set *(short *)0xfffa04=0xd408 +# set 21 MHz system clock for ref 4 MHz + +# $YFFA17 - PEPAR - Port E Pin Assignment Register +# 7 6 5 4 3 2 1 0 +# PEPA7 PEPA6 PEPA5 PEPA4 PEPA3 PEPA2 PEPA1 PEPA0 +# SIZ1 SIZ0 AS DS RMC AVEC DSACK1 DSACK0 +# 1 .. control signal, 0 .. port F +# after reset determined by DATA8 +set *(char*)0xfffa17=0xf4 + +# 0xFFFA1F - PFPAR - Port F Pin Assignment Register +# 7 6 5 4 3 2 1 0 +# PFPA7 PFPA6 PFPA5 PFPA4 PFPA3 PFPA2 PFPA1 PFPA0 +# INT7 INT6 INT5 INT4 INT3 INT2 INT1 MODCLK +# 1 .. control signal, 0 .. port F +# after reset determined by DATA9 +set *(char*)0xfffa1f=0 + +# Setup internal RAM + +# setup STANBY RAM at 0x8000 +# RAMMCR ... STOP +set *(short *)0xFFFB40=0x8000 +# RAMBAH RAMBAL +set *(int *)0xFFFB44=0xFFD000 +# RAMMCR ... ENABLE +set *(short *)0xFFFB40=0 + +# setup TPU RAM at 0x8000 +# TRAMMCR +set *(short *)0xFFFB00=0x8000 +# TRAMBAR +set *(short *)0xFFFB04=0xFFE000>>8 +# TRAMMCR +set *(short *)0xFFFB00=0 + +# 0xYFFA44 - CSPAR0 - Chip Select Pin Assignment Register 0 +# 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 +# 0 0 CSPA0[6] CSPA0[5] CSPA0[4] CSPA0[3] CSPA0[2] CSPA0[1] CSBOOT +# 0 0 DATA2 1 DATA2 1 DATA2 1 DATA1 1 DATA1 1 DATA1 1 1 DATA0 +# CS5 CS4 CS3 CS2 CS1 CS0 CSBOOT +# FC2 PC2 FC1 PC1 FC0 PC0 BGACK BG BR +# +# 00 Discrete Output +# 01 Alternate Function +# 10 Chip Select (8-Bit Port) +# 11 Chip Select (16-Bit Port) +# +set *(short *)0xfffa44=0x3bff +# CS4 8-bit rest 16-bit + + +# 0xFFFA46 - CSPAR1 - Chip Select Pin Assignment Register 1 +# 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 +# 0 0 0 0 0 0 CSPA1[4] CSPA1[3] CSPA1[2] CSPA1[1] CSPA1[0] +# 0 0 0 0 0 0 DATA7 1 DATA76 1 DATA75 1 DATA74 1 DATA73 1 +# CS10 CS9 CS8 CS7 CS6 +# A23 ECLK A22 PC6 A21 PC5 A20 PC4 A19 PC3 +# +set *(short *)0xfffa46=0x03a9 +# CS7,CS8,CS9 8-bit CS10 16-bit and A19 + +# +# Chip selects configuration +# +# 0xFFFA48 - CSBARBT - Chip-Select Base Address Register Boot ROM +# 0xFFFA4C..0xFFFA74 - CSBAR[10:0] - Chip-Select Base Address Registers +# 15 14 13 12 11 10 9 8 7 6 5 4 3 2 0 +# A23 A22 A21 A20 A19 A18 A17 A16 A15 A14 A13 A12 A11 BLKSZ +# reset 0x0003 for CSBARBT and 0x0000 for CSBAR[10:0] +# +# BLKSZ Size Address Lines Compared +# 000 2k ADDR[23:11] +# 001 8k ADDR[23:13] +# 010 16k ADDR[23:14] +# 011 64k ADDR[23:16] +# 100 128k ADDR[23:17] +# 101 256k ADDR[23:18] +# 110 512k ADDR[23:19] +# 111 1M ADDR[23:20] +# +# +# 0xFFFA4A - CSORBT - Chip-Select Option Register Boot ROM +# 0xFFFA4E..0xFFFA76 - CSOR[10:0] - Chip-Select Option Registers +# 15 14 13 12 11 10 9 6 5 4 3 1 0 +# MODE BYTE R/W STRB DSACK SPACE IPL AVEC +# 0 1 1 1 1 0 1 1 0 1 1 1 0 0 0 0 - for CSORBT +# +# BYTE 00 Disable, 01 Lower Byte, 10 Upper Byte, 11 Both Bytes +# R/W 00 Reserved,01 Read Only, 10 Write Only, 11 Read/Write +# SPACE 00 CPU, 01 User, 10 Supervisor, 11 Supervisor/User +# +set *(short *)0xfffa48=(0x800000>>8)&0xfff8 | 7 +set *(short *)0xfffa4a=(0<<15)|(3<<13)|(3<<11)|(0<<10)|(0<<6)|(3<<4) +# BOOT ROM 0x800000 1MB RW UL + +set *(short *)0xfffa4c=(0x900000>>8)&0xfff8 | 7 +set *(short *)0xfffa4e=(0<<15)|(3<<13)|(3<<11)|(0<<10)|(0<<6)|(3<<4) +# CS0 ROM 0x900000 1MB RW UL + +#set *(long *)0xfffa50=0x0003303e +# CS1 RAM 0x000000 64k WR L + +set *(short *)0xfffa54=(0x000000>>8)&0xfff8 | 7 +set *(short *)0xfffa56=(0<<15)|(3<<13)|(3<<11)|(0<<10)|(0<<6)|(3<<4) +# CS2 RAM 0x000000 1MB RW UL - Main RAM first 1MB + +#set *(short *)0xfffa58=(0x100000>>8)&0xfff8 | 7 +#set *(short *)0xfffa5A=(0<<15)|(3<<13)|(3<<11)|(0<<10)|(0<<6)|(3<<4) +# CS3 RAM 0x100000 1MB RW UL - Main RAM second 1MB + +set *(short *)0xfffa5c=(0xf00000>>8)&0xfff8 | 6 +set *(short *)0xfffa5e=(0<<15)|(3<<13)|(3<<11)|(1<<10)|(2<<6)|(3<<4) +# CS4 PER 0xf00000 512kB RW UL - CMOS RAM, RTC, other devices + +#set *(long *)0xfffa60=0xffe8783f +# CS5 + +#set *(long *)0xfffa64=0x100438f0 +# CS6 R/R 0x100000 128k RW L + +set *(short *)0xfffa68=(0xf87000>>8)&0xfff8 | 0 +set *(short *)0xfffa6a=(0<<15)|(3<<13)|(3<<11)|(1<<10)|(1<<6)|(3<<4) +# CS7 PER 0xf87000 2k RW UL - MO_PWR + +set *(short *)0xfffa6c=(0xf88000>>8)&0xfff8 | 0 +set *(short *)0xfffa6e=(0<<15)|(3<<13)|(3<<11)|(1<<10)|(1<<6)|(3<<4) +# CS8 PER 0xf88000 2k RO UL - IRC + +set *(short *)0xfffa70=(0xf89000>>8)&0xfff8 | 0 +set *(short *)0xfffa72=(0<<15)|(3<<13)|(3<<11)|(1<<10)|(3<<6)|(3<<4) +# CS9 PER 0xf89000 2k WR UL - KBD + +#set *(long *)0xfffa74=0x01035030 +# CS10 RAM 0x010000 64k WR U + +# +# My change +# +#set *(long *)0xfffa58=0x02036870 +# CS3 RAM 0x020000 64k RO UL + +#set *(long *)0xfffa64=0x02033030 +# CS6 RAM 0x020000 64k WR L + +#set *(long *)0xfffa68=0x02035030 +# CS7 RAM 0x020000 64k WR U + + +# CPU registers + +# SR=PS Status Register +# 15 14 13 12 11 10 8 7 6 5 4 3 2 1 0 +# T1 T0 S 0 0 IP___ 0 0 0 X N Z V C +# 0 0 1 0 0 1 1 1 0 0 0 U U U U U + +bdm_status + +end +#=========================================================== + +# sets well defined values into VBR +define vbr_set_all + set $vec_num=0 + set $vbr_val=(unsigned)$vbr + while $vec_num<256 + set *(unsigned*)($vbr_val+$vec_num*4)=($vec_num*16)+0xf0000 + set $vec_num++ + end +end + +# Test writability of RAM location +define bdm_test_ram_acc + echo testing ... + p /x $arg0 + set $ram_addr=(unsigned int)$arg0 + set $old_ram_val0=*(int*)$ram_addr + set $old_ram_val1=*(int*)($ram_addr+4) + set *(int*)($ram_addr+3)=0xff234567 + set *(int*)$ram_addr=0x12345678 + if *(int*)$ram_addr!=0x12345678 + printf "Error1 %08X\n",*(int*)$ram_addr + end + set *(char*)$ram_addr=0xab + if *(int*)$ram_addr!=0xab345678 + printf "Error2 %08X\n",*(int*)$ram_addr + end + set *(char*)($ram_addr+1)=0xcd + if *(int*)$ram_addr!=0xabcd5678 + printf "Error3 %08X\n",*(int*)$ram_addr + end + set *(char*)($ram_addr+3)=0x01 + if *(int*)$ram_addr!=0xabcd5601 + printf "Error4 %08X\n",*(int*)$ram_addr + end + set *(char*)($ram_addr+2)=0xef + if *(int*)$ram_addr!=0xabcdef01 + printf "Error5 %08X\n",*(int*)$ram_addr + end + if *(int*)$ram_addr!=0xabcdef01 + printf "Error5 %08X\n",*(int*)$ram_addr + end + if *(int*)($ram_addr+1)!=0xcdef0123 + printf "Error6 %08X\n",*(int*)$ram_addr + end + if *(int*)($ram_addr+2)!=0xef012345 + printf "Error7 %08X\n",*(int*)$ram_addr + end + if *(int*)($ram_addr+2)!=0xef012345 + printf "Error8 %08X\n",*(int*)$ram_addr + end + if *(int*)($ram_addr+3)!=0x01234567 + printf "Error9 %08X\n",*(int*)$ram_addr + end + set *(int*)$ram_addr=$old_ram_val0 + set *(int*)($ram_addr+4)=$old_ram_val1 +end + +# Read flash identification +define bdm_read_flash_id + set $flash_base=(int)$arg0&~0xffff + output /x $flash_base + echo \n + set *(char*)($flash_base+0x555*2+1)=0xf0 + set *(char*)($flash_base+0x555*2+1)=0xaa + set *(char*)($flash_base+0x2aa*2+1)=0x55 + set *(char*)($flash_base+0x555*2+1)=0x90 + p /x *(char*)($flash_base+0x00*2+1) + set *(char*)($flash_base+0x555*2+1)=0xf0 + set *(char*)($flash_base+0x555*2+1)=0xaa + set *(char*)($flash_base+0x2aa*2+1)=0x55 + set *(char*)($flash_base+0x555*2+1)=0x90 + p /x *(char*)($flash_base+0x01*2+1) +end + +define bdm_read_flash1_id + bdm_read_flash_id 0x800000 +end + +define bdm_read_flash2_id + bdm_read_flash_id 0x900000 +end + +define bdm_test_flash_write + set $flash_base=(int)$arg0 & ~0xffff + output /x $flash_base + echo \n + set *(char*)($flash_base+0x555*2+1)=0xf0 + set *(char*)($flash_base+0x555*2+1)=0xaa + set *(char*)($flash_base+0x2aa*2+1)=0x55 + set *(char*)($flash_base+0x555*2+1)=0xA0 + set *(char*)($arg0)=$arg1 +end + +define bdm_test_pwm0 + + #BIUMCR - BIU Module Configuration Register $YFF400 + set *(short*)0xfff400=*(short*)0xfff400&~0x8000 + #CPCR - CPSM Control Register $YFF408 + set *(short*)0xfff408=*(short*)0xfff408|8 + #PWM5SIC - PWM5 Status/Interrupt/Control Register $YFF428 + set *(short*)0xfff428=0x18 + #PWM5A1 - PWM5 Period Register $YFF42A + set *(short*)0xfff42a=512 + #PWM5B1 - PWM5 Pulse Width Register $YFF42C + set *(short*)0xfff42c=0 + + if $arg0==0 + set *(short*)0xf87000=0 + set $pwm_val=0 + else + if $arg0>0 + set *(char*)0xf87000=1 + set $pwm_val=$arg0 + else + set *(char*)0xf87000=2 + set $pwm_val=-($arg0) + end + end + #DDRQA + set *(short*)0xfff208=0x8000 + #PORTQA + set *(short*)0xfff206=~0x8000 + + #PWM5B1 - PWM5 Pulse Width Register $YFF42C + set *(short*)0xfff42c=$pwm_val + +end + +define bdm_test_usd_irc + set $usd_irc_d=0xf88000 + set $usd_irc_c=0xf88001 + if $arg0!=0 + # Load Gate + set *(unsigned char*)0xf88020=0 + # CMR + set *(unsigned char*)$usd_irc_c=0x38 + # IOR + set *(unsigned char*)$usd_irc_c=0x49 + # IDR + set *(unsigned char*)$usd_irc_c=0x61 + # RLD - Reset BP, BT CT CPT S + set *(unsigned char*)$usd_irc_c=0x05 + # DATA - PSC + set *(unsigned char*)$usd_irc_d=0x02 + # RLD - Reset BP, PR0 -> PSC + set *(unsigned char*)$usd_irc_c=0x1B + end + # RLD - Reset BP, CNTR -> OL + set *(unsigned char*)$usd_irc_c=0x11 + + set $usd_irc_val=((int)(*(unsigned char*)$usd_irc_d)) + set $usd_irc_val+=((int)(*(unsigned char*)$usd_irc_d))<<8 + set $usd_irc_val+=((int)(*(unsigned char*)$usd_irc_d))<<16 + print /x $usd_irc_val + +end + +define six + si + x /10i $pc +end + +bdm_hw_init + +#b main + +#run + diff --git a/m68k/.cvsignore b/m68k/.cvsignore new file mode 100644 index 0000000..3471d83 --- /dev/null +++ b/m68k/.cvsignore @@ -0,0 +1,8 @@ +autom4te.cache +configure +config.h.in +config.log +config.status +aclocal.m4 +Makefile.in +Makefile diff --git a/m68k/BUGS b/m68k/BUGS new file mode 100644 index 0000000..3cb95fb --- /dev/null +++ b/m68k/BUGS @@ -0,0 +1,62 @@ +BUGS +==== + +- Missing 5282 support (patch needed). + +- Duplicated debug output on windows. + +- PCI parallel ports with non-standard port-addresses not supported. + +- Probing of different access methods (driver, ioperm, bdmd) with + irritating error messages. + This one and the PCI parallel ports above would probably best be resolved + by a new naming sheme for the target devices. + +- In insight-5.3, when "Run" button is hit, no bdm_reset is executed. This + leads to the effect that _first_ "Run" works (since you can/should put + bdm_reset into the setup-and-load macro). But the _second_ "Run" will + fail since IRQs are left enabled and some registers are writeable only + once after reset. + +- Insight-6.0 don't work at all. + +- The target is hardwired to /dev/bdmcf0 in insight. + +- Parallel port on Elitegroup ECS K7S5A (sis735 chipset) motherboard seems not + to work. The port pins are active only for a couple milliseconds after an + edge of the strobe signal and set tri-state thereafter. The bdm adaptor + requires that the pins have valid signals all the time. Tri-stating the pins + result in loss of control over the adaptor/target. + +- Dell Pentium III machines seem to not work. Not really sure why but clearing + the parallel port register for the CF processors causes the parallel port to + either initialise or reset and not work. + +- Coldfire - support to detect version of the debug module for auto detection + of the PST lines has problems if a BDM pod is not connected to the target or + the target is not powered. + +- The 5407 BDM hardware does not implement the SSI bit and the driver tries to + use it. No idea why this bit was removed as it was just stupid. The work + arounds for the driver are complex and not yet implemented. + +- For m68k ELF systems you need to be careful about the binutils mix you use. + Binutils of versions 2.9.5.* will not work with gdb-4.18 or earilier. You + will get core dumps. Earilier version of gcc and binutils as used by the + ucLinux project have some problems. + + --------------------------- + +Reporting Them: + +If you've got any questions/remarks about any of this, please contact the BDM +project mailing list on the SourceForge web site: + + http://sourceforge.net/projects/bdm/ + +It is a good idea to turn on the debug and look at the output. Keep +the log as it might be useful for us to track the problem down. + +A patch is also welcome. + + --------------------------- diff --git a/m68k/COPYING b/m68k/COPYING new file mode 100644 index 0000000..d511905 --- /dev/null +++ b/m68k/COPYING @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + 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., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/m68k/ChangeLog b/m68k/ChangeLog new file mode 100644 index 0000000..e173a3e --- /dev/null +++ b/m68k/ChangeLog @@ -0,0 +1,1174 @@ +2008-09-25 Chris Johns + + * README: Add script documentation. Added extra notes on Windows + names and using udev on Linux. + + * utils/bdmreset.c, test/chk.c: Print a decimal verison + number. Add TBLCF support. + + * server/bdmServer.c: Correct the help. Minor formatting changes. + + * lib/bdmRemote.c: Correct the name parsing. Allow a device name + to not have a '/' to allow USB devices on remote machines to be + used. + + * lib/bdmIO.c: Add bdmInfo. Add bdmAppendConfiguration, + bdmReadConfiguration, bdmConfigSkipWhiteSpace, bdmConfigGet for + scipt support. Change bdmOpen to use 'dev' script entries. + + * lib/BDMlib.h: Add bdmInfo. Add bdmAppendConfiguration, + bdmReadConfiguration, bdmConfigSkipWhiteSpace, bdmConfigGet for + scipt support. + + * driver/ioperm/ioperm.c: Change fprintf calls to bdmInfo calls to + stop the server outputting text to the remote client. + + * driver/bdm-tblcf.c: Add support to partially search a device + name against the libusb list of devices for the first match. + +2008-09-19 Chris Johns + + * README: Updated to state FreeBSD is supported via "/dev/io". + + * config/bootstrap: Remove pushd/popd and use basic shell + variables. FreeBSD's /bin/sh is not bash. + + * driver/ioperm/ioperm.c: Add FreeBSD "/dev/io" support. Tested on + an AMD64 host running FreeBSD 7.0. + +2008-09-13 Chris Johns + + * driver/win/win-bdm.c: Fixed the timer. It was too long by a + factor of 10. Add the TBLCF interface to the port checking so it + is skipped when a parallel port is being used. + +2008-09-09 Chris Johns + + * driver/win/win-bdm.c: Fix the parallel port detect logic. Not + tested as much due to the low number of ports I have on Windows + machines. + + * flashlib/Makefile.am, flashlib/flash_filter.c: Search the prefix + path for plugins. This removes the needs to have a full path name + in a bdmctl script. + + * gdbserver/m68k-bdm-low.c: Print the name of the device being + opened. Helped see that gdb escapes the name on Windows USB + devices which have a '\' in the USB device name. Users needs to + add extra '\'s to the device name. + +2008-08-06 Chris Johns + + * config/bootstrap: Change the -foreign to --foreign option for + automake. + +2008-08-04 Chris Johns + + * flashlib/PLUGIN-MAPPING: New. Provides a mapping for the plugins + to the Coldlfire family. + + * flashlib/Makefile.am: Fix the plugin mappings. + + * flashlib/flashintelc3.c: Remove warning. + + * flashlib/m68k-bdm-compile-plugin: Fix CPU option. + + * utils/bdmctrl.c: Fix compile typo. + +2008-07-31 Matthew Riek + + * INSTALL: New. + + * config/bootstrap, config/config.guess, config/config.sub, + config/depcomp, config/install-sh, config/missing, + config/mkinstalldirs: Update by a newer autoconf. + + * flashlib/flashintelc3.c, flashlib/flashintelc3.h, + flashlib/m68k-bdm-compile-plugin: New. + + * configure.ac, flashlib/Makefile.am: Detect a m68k cross-compiler + and if found build the various plugins. + + * flashlib/README, flashlib/elf-utils.c, flashlib/elf-utils.h, + flashlib/flash29.c, flashlib/flash29.h, flashlib/flash_filter.c, + flashlib/flash_filter.h, flashlib/flashcfm.c, flashlib/flashcfm.h: + Changed elf-utils to iterate over program headers to get physical + addresses. Added flashlib variable support updated flashcfm to use + variables moved clock code from flashcfm into mcf52235.test. + + * flashlib/compile_flashcfm, flashlib/tcompile: Removed. + + * utils/Makefile.am, utils/README.bdmctrl, utils/bdmctrl.c, + utils/m68332.test, utils/mcf52235.test: Updated documentation. + + * utils/mcf5235.test, utils/mcf5329.test: New. + +2008-06-16 Chris Johns + + * packages/.cvsignore, packages/gpl.txt, packages/m68k-bdm.nsi: + New. + + * flashlib/elf-utils.h: Add elf_handle_init decl. + + * utils/Makefile.am: Add warnings flags. + + * bdmabstraction/BDMFlash.h, utils/bdmctrl.c, utils/bdmflash.c: + Fix warnings. + +2008-06-16 Chris Johns + + * utils/bdmctrl.c: Clean up the load verbose messages. + +2008-06-16 Matthew Riek + + * gdbserver/m68k-bdm-low.c: Add a bdm-sleep command to create + scripts that can wait for various hardware action to complete. + +2008-06-08 Chris Johns + + * libelf/COPYING.LIB, libelf/ChangeLog, libelf/INSTALL, + libelf/MANIFEST, libelf/Makefile.in, libelf/README, + libelf/VERSION, libelf/acconfig.h, libelf/aclocal.m4, + libelf/config.guess, libelf/config.h.in, libelf/config.sub, + libelf/configure, libelf/configure.in, libelf/install-sh, + libelf/libelf.pc.in, libelf/mkinstalldirs, libelf/stamp-h.in, + libelf/lib/32.fsize.c, libelf/lib/32.getehdr.c, + libelf/lib/32.getphdr.c, libelf/lib/32.getshdr.c, + libelf/lib/32.newehdr.c, libelf/lib/32.newphdr.c, + libelf/lib/32.xlatetof.c, libelf/lib/64.xlatetof.c, + libelf/lib/Makefile.in, libelf/lib/Makefile.w32, + libelf/lib/assert.c, libelf/lib/begin.c, libelf/lib/build.bat, + libelf/lib/byteswap.h, libelf/lib/checksum.c, libelf/lib/cntl.c, + libelf/lib/config.h.w32, libelf/lib/cook.c, libelf/lib/data.c, + libelf/lib/elf_repl.h, libelf/lib/end.c, libelf/lib/errmsg.c, + libelf/lib/errno.c, libelf/lib/errors.h, libelf/lib/ext_types.h, + libelf/lib/fill.c, libelf/lib/flag.c, libelf/lib/gelf.h, + libelf/lib/gelfehdr.c, libelf/lib/gelfphdr.c, + libelf/lib/gelfshdr.c, libelf/lib/gelftrans.c, + libelf/lib/getarhdr.c, libelf/lib/getarsym.c, + libelf/lib/getbase.c, libelf/lib/getdata.c, libelf/lib/getident.c, + libelf/lib/getscn.c, libelf/lib/hash.c, libelf/lib/input.c, + libelf/lib/kind.c, libelf/lib/libelf.def, libelf/lib/libelf.h, + libelf/lib/memset.c, libelf/lib/ndxscn.c, libelf/lib/newdata.c, + libelf/lib/newscn.c, libelf/lib/next.c, libelf/lib/nextscn.c, + libelf/lib/nlist.c, libelf/lib/nlist.h, libelf/lib/opt.delscn.c, + libelf/lib/private.h, libelf/lib/rand.c, libelf/lib/rawdata.c, + libelf/lib/rawfile.c, libelf/lib/strptr.c, libelf/lib/swap64.c, + libelf/lib/sys_elf.h.in, libelf/lib/sys_elf.h.w32, + libelf/lib/update.c, libelf/lib/verdef.h, + libelf/lib/verdef_32_tof.c, libelf/lib/verdef_32_tom.c, + libelf/lib/verdef_64_tof.c, libelf/lib/verdef_64_tom.c, + libelf/lib/verneed.h, libelf/lib/version.c, libelf/lib/x.elfext.c, + libelf/lib/x.movscn.c, libelf/lib/x.remscn.c, + libelf/po/Makefile.in, libelf/po/de.gmo, libelf/po/de.msg, + libelf/po/de.po, libelf/po/gmo2msg.c, libelf/po/libelf.pot, + libelf/po/stamp-po: Merge libelf into the BDM package. + + * configure.ac, utils/Makefile.am, utils/bdmctrl.c, + flashlib/Makefile.am, flashlib/bdmfilt.c, flashlib/bdmfilt.h, + flashlib/bdmflash.c, flashlib/bdmflash.h, flashlib/flash29.c, + flashlib/flash_filter.c, flashlib/flash_filter.h: Remove all BFD + references and change to ELF file support. + + * flashlib/elf-utils.c, flashlib/elf-utils.h: New. + + * driver/bdm.h, driver/bdm-tblcf.c: Add the TBLCF interface + number. + + * bdmabstraction/BDMTargetAddress.c: Add a long write call. + + * gdbserver/Makefile.am: Fix the XML to C regen rule. + +2008-06-08 Matthew Riek + + * flashlib/flashcfm.c, flashlib/flashcfm.h, + flashlib/compile_flashcfm, utils/mcf52235.test. + +2008-05-27 Chris Johns + + * gdbserver/m68k-bdm-low.c: The cbuf for register supply and + collect needs to be unsigned. The collect_register cbuf argument + was wrong. + + * gdbserver/regcache.c: Fix the registers_from_string and + registers_to_string to handle the data from GDB correctly. + +2008-05-27 Matt Riek + + * driver/bdm-tblcf.c: Terminate the link returned from + readlink with a nul character. + +2008-05-26 Chris Johns + + * gdbserver/m68k-cf5200-regs.c, gdbserver/m68k-cf52223-regs.c, + gdbserver/m68k-cf52223.xml, gdbserver/m68k-cf5235-regs.c, + gdbserver/m68k-cf5272-regs.c, gdbserver/m68k-cf5282-regs.c, + gdbserver/m68k-cf5307-regs.c, gdbserver/m68k-cfv4e-regs.c, + gdbserver/m68k-core-regs.c, gdbserver/m68k-cpu32-regs.c, + gdbserver/m68k-cpu32plus-regs.c: New. Moved the registers into + separate files. Support for the cf52223 (Debug B+) added. + + * driver/bdm-cf-pe.c: The 4ve is a Version C debug module. + + * gdbserver/m68k-cfv4e.xml: Fixed the register map. Matches the + V4E better. + + * gdbserver/regcache.c, gdbserver/regdef.h: Add registers flags to + control the types of registers that we need to support. + + * gdbserver/Makefile.am: Added new files. + + * gdbserver/m68k-bdm-low.c: Added support for the + cf52223. Added support for the register flags. Reworked the + hardware breakpoint and hardware watchpoint to support more than + one breakpoint. + +2008-05-15 Mark Giacobbe + + * gdbserver/m68k-cf5307.xml: New. + + * gdbserver/Makefile.am: Add m68k-cf5307.xml. + + * gdbserver/m68k-bdm-low.c: Add 5307 support. + +2008-05-15 Chris Johns + + * README: Fix the TBLCF documentation. + +2008-03-18 Chris Johns + + * README: Add the TBLCF documentation. + + * configure.ac: Add support to build the package on Darwin + (MacOS). + + * driver/bdm-tblcf.c: Move the usb_bdm_init function into a common + spot rather than have 2 copies. Add failure recovery incase it can + be made to work. Add symlink support for Linux's udev. + + * driver/ioperm/ioperm.c: Remove usb_bdm_init. Change the way the + name is handle to allow for the udev symlink support. + + * driver/win/win-bdm.c: Make the Windows TBLCF name just what + libusb returns. + +2008-03-06 Chris Johns + + * driver/bdm.c: Move the CPU32 and CF specific parts into separate + files and add TBLCF. Make all call happen via handlers. Move the + common bit bashing routines into common functions for use by the + CPU32 and CF driver parts. Add the swap code taken from the + library code. + + * driver/bdm.h: Change BDMioctl fields to unsigned long int. + + * driver/bdm-cf-pe.c: Moved from bdm.c. Fixed the system reg read + and write routines to detect a non-mapped register. + + * driver/bdm-cpu32: Moved from bdm.c. Fixed the system reg read + and write routines to detect a non-mapped register. + + * driver/bdm-tblcf.c: New. + + * driver/ioperm/ioperm.c, driver/win/win-bdm.c: Add USB support. + + * lib/bdmIO.c: Remove swap code. Moved to the driver as TBLCF + handles the swap. This is the simplest way to untangle this. + + * gdbserver/Makefile.am, lib/Makefile.am, server/Makefile.am, + test/Makefile.am, utils/Makefile.am: Add TBLCF and libusb support. + + * tblcf/.cvsignore, tblcf/Makefile.am, tblcf/commands.h, + tblcf/log.c, tblcf/log.h, tblcf/log_cmdline.c, + tblcf/log_cmdline.h, tblcf/srec.c, tblcf/srec.h, + tblcf/tblcf-show.c, tblcf/tblcf.c, tblcf/tblcf.h, + tblcf/tblcf_bt.c, tblcf/tblcf_bt.h, tblcf/tblcf_hwdesc.h, + tblcf/tblcf_unsec.c, tblcf/tblcf_usb.c, tblcf/tblcf_usb.h, + tblcf/version.h: New. Taken from the TBLCF project. + + * configure.ac, Makefile.am: Add TBLCF and libusb support. + +2008-02-14 Federico Ulivi + + * gdbserver/m68k-bdm-low.c: Patch to fix the register list for + cfv4e core. BDM now works for me with gdb 6.7.1 (targeted to m68k + architecture, of course). + +2008-01-10 Chris Johns + + * lib/bdmIO.c: Update byte swap test to work on x64 host + machines. + +2008-01-06 tom + + * driver/linux-2.6/bdm.c: It seems that linux kernel 2.6.19 + eliminates include/linux/config.h, include/linux/autoconf.h should + now be used. + +2007-12-10 Chris Johns + + * README: Add documentation about the README files. + +2007-12-10 Chris Johns + + * gdbserver/m68k-bdm-low.c (m68k_bdm_insert_breakpoint, + m68k_bdm_remove_breakpoint, m68k_bdm_insert_watchpoint, + m68k_bdm_remove_watchpoint, m68k_bdm_insert_point, + m68k_bdm_remove_point): Add extra info to the debug data to aid + debugging watchpoints. + +2007-12-07 Mick Davis + + * gdbserver/m68k-bdm-low.c (m68k_bdm_parse_reg_value): Fix the + parsing of arguments from the bdm-ctl-set command. + (m68k_bdm_cmd_help): Add bdm-reset help. + (m68k_bdm_commands): Add bdm-reset. + + * gdbserver/remote-utils.c, gdbserver/server.c, + gdbserver/server.h: Fix any remote protocol message which includes + a binary data part, such as when a value is written into target + memory. Previously, the top bit of any byte received was cleared + by a readchar function which enforced ASCII encoding. This fix + has been applied to gdb cvs, from where the code originated. I've + also included a buffer overflow check for the received message. + +2007-11-15 Chris Johns + + * gdbserver/m68k-bdm-low.c (m68k_bdm_create_inferior): Set + warning_prefix to show the errors in the debugger better when in + pipe mode. + + * gdbserver/server.h (warning_prefix): New. + + * gdbserver/remote-utils.c (socket_read, socket_write): Change the + read and write macros on Windows to have a specific read and write + to the real read and write on Windows is not hidden. This allows + the pipe mode to get at stdout. + (remote_open): On Windows set stdin and stdout to binary mode. + (remote_close): Only close if not piping. + (remote_write): Use write when piping and socket_write if using + TCP. + (remote_read): New. + (putpkt_binary): Provide a better error message. Use remote_read + rather than read. Remove the 'gdbserver' and let the warning + prefix be used. + (input_interrupt): Add the Windows warning to the comment. + (readchar): Use remote_read. Remove the 'gdbserver' and let the + warning prefix be used. + +2007-11-13 Chris Johns + + * gdbserver/server.c (main): Allow software breakpoints to the + backend. + + * gdbserver/m68k-bdm-low.c (M68K_BDM_BREAKPOINT_SIZE_MAX, + M68K_BDM_WP_TYPE_BREAK, struct m68k_bdm_break, + M68K_BDM_BREAKPOINT_BLOCK_SIZE, m68k_bdm_breakpoints, + m68k_bdm_num_breakpoints, m68k_bdm_grow_breakpoints): New. + (m68k_bdm_insert_breakpoint, m68k_bdm_remove_breakpoint): Add + software breakpoint support. + (m68k_bdm_insert_point, m68k_bdm_remove_point): Renamed from + m68k_bdm_insert_hardware_point and m68k_bdm_remove_hardware_point. + +2007-11-13 Chris Johns + + * m68k/gdbserver/m68k-bdm-low.c (m68k_bdm_fetch_registers): Check + the result code for the first of the double long transfers and + only proceed with the next one if the first is ok. + (m68k_bdm_store_registers): Reverse the byte order for the host to + the correct order for the target. Also handle the 64bit register + transfers. + * gdbserver/remote-utils.c (remote_open): Ignore the various + signals we could get when in pipe mode. + + * m68k/lib/BDMlib.h: Add bdmHostByteOrder. + + * m68k/lib/bdmIO.c (bdmHostByteOrder): New. + (bdmReadControlRegister, bdmReadDebugRegister, + bdmReadSystemRegister, bdmReadRegister, bdmWriteControlRegister, + bdmWriteControlRegister, bdmWriteSystemRegister, bdmWriteRegister, + bdmReadLongWord, bdmReadWord, bdmReadByte): Print in host byte + order. + +2007-11-08 Chris Johns + + * README, README.bdmgdbserver, gdbserver/Makefile.am: Change + bdmgdbserver to m68k-bdm-gdbserver as this is a better name when + this package is part of another package. + + * gdbserver/remote-utils.c: Formatting fixes. + + * lib/bdmRemote.c: Add prints if WinSock fails or no device is + located in the path. + +2007-11-06 Chris Johns + + * COPYING: The GPL license should be Version 2 not Version 3. + +2007-11-03 Chris Johns + + * .cvsignore: + Add config.h.in. A generated file. + + * config/.cvsignore: + Add ylwrap. A generated file. + + * README: + Updated with the GDB server status and remove the patching GDB + steps. + + * README.bdmgdbserver: + Added some documentation. + + * gdbserver/Makefile.am, gdbserver/remote-utils.c, + gdbserver/server.c: + Remove the CR in the Makefile.am. Clean up some standard GDB + server code so aid getting this code back into GDB. + +2007-11-03 Chris Johns + + * configure.ac: + Move to version 1.4.0 of the package. + Add header file checks for the gdbserver. + Make all parts dependent on libbfd be built only when the library + is detected. + Add support for the gdbserver. + + * config/bootstrap: + Updated to work with the automake version number greater than 9. + + * driver/bdm.c: + Changed the raw paramater in the read_sysref/write_sysreg with a + mode that allows mapped, control, and debug register access. + Added the debug register ioctl support. + + * driver/ioperm/ioperm, driver/win/win-bdm.c: + Direct all output to stderr. + + * gdbserver/.cvsignore, gdbserver/feature_to_c.sh, + gdbserver/gdb/signals.h, gdbserver/gdbserver-regs.xsl, + gdbserver/gdb-target.dtd, gdbserver/inferiors.c, + gdbserver/m68k-bdm-low.c, gdbserver/m68k-cf5200.xml, + gdbserver/m68k-cf5235.xml, gdbserver/m68k-cf5272.xml, + gdbserver/m68k-cf5282.xml, gdbserver/m68k-cfv4e.xml, + gdbserver/m68k-core.xml, gdbserver/m68k-fpu.xml, + gdbserver/Makefile.am, gdbserver/mem-break.c, + gdbserver/mem-break.h, gdbserver/move-if-change, + gdbserver/number-regs.xsl, gdbserver/regcache.c, + gdbserver/regcache.h, gdbserver/regdef.h, + gdbserver/remote-utils.c, gdbserver/server.c, gdbserver/server.h, + gdbserver/signals.c, gdbserver/sort-regs.xsl, gdbserver/target.c, + gdbserver/target.h, gdbserver/terminal.h, gdbserver/utils.c, + gdbserver/version.in, gdbserver/xinclude.dtd: + Add a GDB remote protocol server with pipe support. + + * lib/BDMlib.h: + Change bdmDebug to bdmPrint. + Added debug register support. + + * lib/bdmIO.c: + Change bdmDebug to bdmPrint. + Flush stderr after each print. + Added debug register support. + Initialise variables to keep valgrind happy. + + * lib/bdmRemote.c: + Change all printf to bdmPrint's. + + * server/xmalloc.c: + Change the STDLIB_H check. + + * test/chk.c, test/cpu32-check.c: + Use the correct Windows API call. + +2007-11-03 cjohns + + * COPYING: Add the GPL license to the package. + +2007-01-17 joewolf + + * flashlib/README, flashlib/flash29.c: Add some more flash chips. + + * utils/README.bdmctrl: Fix some typos. + +2006-11-20 ppisa + + * utils/bdmctrl.c: + Modification to allow BDMCTRL to be compiled even with latest BFD library. + + New versions of BFD library use bfd_mach_mcf_isa_{a,b}_xxx names + for targets instead of bfd_mach_mcf5200 etc. + +2006-02-22 codewiz + + * utils/Makefile.am: + Fix build for Darwin hosts (-static not supported and discouraged by Apple). + +2006-02-20 codewiz + + * config/bootstrap, README, configure.ac: + Autodetect ioperm() and kernel driver availability (for better Darwin support). + +2005-10-24 cjohns + + * driver/bdm.c: + Add support for the v4e core. This includes detecting version D + debug hardware, masking interrupts using the SR register when stepping, + invalidating the cache on steps and writes etc, issuing the FORCE_TA command + on NVC errors, and flush the pipeline when stopping. + Default is to use PST signals. + + * driver/bdm.h: New version number. + Add the BDM_FAULT_FORCED_TA error code. Debug version D has a FORCED_TA command to aid + BDm recovery. Return this error when it happens. + + * lib/bdmIO.c: Removed warnings when built with gcc 4.x. + Add the new BDM_FAULT_FORCED_TA error message. + + * server/bdmServer.c: Removed warnings when built with gcc 4.x + + * bdmabstraction/BDMFlash.c, bdmabstraction/BDMTargetAddress.c, bdmabstraction/bdmops.c: + Fixed includes for building in Windows with MinGW. + + * test/chk.c, test/cpu32-check.c: + Removed warnings when built with gcc 4.x + + * flashlib/bdmfilt.h, flashlib/bdmflash.h: + Add types missing on Windows. Builds with MinGW. + + * utils/bdmflash.c, utils/bdmmon.l: + Removed warnings when built with gcc 4.x + +2005-10-04 codewiz + + * bdmabstraction/Flash.c: + Add M29F400BB. (Patch by Robert McPherson ) + +2005-09-20 codewiz + + * driver/bdm.c: Remove duplicate comment. + +2005-07-29 codewiz + + * flashlib/flash29.c: + Add some new flash chips; Fix bug in programming algorithm (Patch + contributed by Andrea Tarani ) + +2005-03-17 codewiz + + * configure.ac: Update to latest auto tools. + +2004-12-05 codewiz + + * utils/bdmctrl.c, flashlib/flash_filter.c: + Replace bfd_get_section_size_before_reloc() with bdm_section_size() + as the former has been removed from binutils-2.15.94.x. + The new macro appears returns the very same value and also exists + in binutils 2.14.x, therefore this change should be backwards + compatible. + +2004-06-25 codewiz + + * flashlib/Makefile.am: + Add README and tcompile to the distribution archive. + +2004-06-06 codewiz + + * configure.ac: Upgrade as suggested by autoupdate-2.57. + +2004-06-01 codewiz + + * Makefile.am: + Simpler, more effective way to include dirs in the distribution. + +2004-06-01 cjohns + + * lib/bdmIO.c: debug_syslog: conditional on the host supporting syslog. + + * driver/win/win-bdm.c: PRINTF: removed. Now in bdmIO.c + +2004-05-31 cjohns + + * lib/bdmRemote.c, server/bdmServer.c: + Added the PST ioctl to the remote protocol. + + * lib/bdmIO.c: Typo from Bernardo's review. + +2004-05-30 cjohns + + * lib/bdmIO.c, driver/bdm.h: Typo fixes as Josef's review + +2004-05-29 codewiz + + * Makefile.am: + Use dist-hook to distribute local_scripts/, ../gdb/ and ../schematics/. + + * config/bootstrap: Enable all autoconf warnings. + +2004-05-16 cjohns + + * lib/bdmIO.c: Changed fd to bdm_fd to aid debugging. + Including syslog is conditional on host platform. Not all platforms support + syslog. + Add the PST and control register calls. + White space clean up. + + * lib/bdmRemote.c: + Added the contro/debug/PST ioctls to the translation table. + Minor formatting changes. + + * lib/BDMlib.h: Provided a prototype for the bdmDebug print call. + Add the control register and PST prototypes. + + * server/bdmServer.c: White space and minor formatting changes. + Added the contro/debug/PST ioctl calls to the translation table. + + * driver/bdm.c: + Added the control register access to allow a user to get + any control register. + + * driver/bdm.h: + Added the PST ioctl defines to allow the PST mode to be controlled from + user land. + Added the control and debug register ioctl defines. + + * driver/ioperm/ioperm.c: Whitespace clean up. Remove tailing spaces. + The bdm init code returns different error code if the driver is + already open or no hardware is found. This stops the kernel driver + or bdmd being tried to also find the hardware does not exist. + + * driver/win/win-bdm.c: The delay time is wrong. The result is the + BDM driver does not reset a target correctly. + + * README: Moved the /etc/services change to the common part of server + installation to document. + Added doco on testing the bdmd is answering. + +2004-05-14 codewiz + + * Makefile.am: + Add local_scripts files (reported by Massimiliano Cialdi). + + * configure.ac: Bump revision + +2004-04-27 joewolf + + * driver/bdm.c: - m68k/driver/bdm.c: + * Fix segfault caused by uninizialized pointer. + +2004-04-25 codewiz + + * configure.ac: Bump revision. + + * Makefile.am: Add OpenBSD driver to distribution. + + * driver/ioperm/ioperm.c, driver/linux-2.6/bdm.c: + Use LPT4 for PCI parallel port cards. + +2004-04-24 codewiz + + * driver/ChangeLog, driver/bdm.c: + Fix CPU32 with ICD cable. Contributed by Aaron J. Grier + +2004-04-18 codewiz + + * driver/openbsd/Makefile, driver/openbsd/README, + driver/openbsd/bdm-install.sh, driver/openbsd/openbsd-bdm.c, + driver/ChangeLog: + Add OpenBSD driver. + +2004-04-09 codewiz + + * config/bootstrap: Check for correct automake version. + +2004-04-06 joewolf + + * utils/README.bdmctrl, utils/bdmctrl.c: + - bdm/m68k/utils/README.bdmctrl, bdm/m68k/utils/m68332.test: + * Fix usage information. + * Fix description of bdmbtrl's non-option parameters. + +2004-03-30 codewiz + + * configure.ac: + Add backward-compatibility workaround for automake 1.4; Bump revision for new release. + + * Makefile.am: Fix embarassing omission in the distribution archives. + +2004-03-28 codewiz + + * utils/Makefile.am: + Include bdmctrl documentation and test script to distribution archives. + + * configure.ac: Bump revision for next release. + +2004-03-26 joewolf + + * BUGS: - m68k/BUGS: + * Updated. + + * utils/README.bdmctrl, utils/bdmctrl.c, utils/m68332.test, flashlib/tcompile: + - m68k/utils/bdmctrl.c: + * Add "open" command to specify device name. + * Remove device specification from command line. + * Add -c command line option to execute commands. + * Source non-option command line switches instead of interpreting them as a + command. + + - bdm/utils/README.bdmctrl, bdm/utils/m68332.test, bdm/flashlib/tcompile: + * Update to match new bdmctrl behavior. + +2004-03-25 joewolf + + * utils/README.bdmctrl, utils/bdmctrl.c: + - m68k/utils/README.bdmctrl, m68k/utils/bdmctrl.c: + * Add -h option to request command descriptions. + * Move command descriptions from README.bdmctrl to bdmctrl's -h option. + +2004-03-24 joewolf + + * flashlib/tcompile, utils/README.bdmctrl, utils/bdmctrl.c: + - crossgcc/bdm/m68k/utils/bdmctrl.c: + * Add command summary to the usage output. + * Add "random-patterns CNT" command and deprecate "patterns random CNT". + * Add "erase-wait" command and deprecate "erase BASE wait". + + - crossgcc/bdm/m68k/utils/README.bdmctrl: + * Sync up command descriptions to the format from usage output. + * Add description for "random-patterns" and "erase-wait" commands. + * Clarify difference in behavior when a command is given on command line. + * Clarify octal/hex number parsing. + * Add little description what the patterns are good for. + + - crossgcc/bdm/m68k/flashlib/tcompile: + * Change deprecated "erase BASE wait" to "erase-wait BASE" + +2004-03-21 codewiz + + * bdmabstraction/Flash.c: Add 39VF/LF160 chip. + + * configure.ac: Update package version. + + * Makefile.am: Add some new files to the distribution archives + + * lib/Makefile.am, flashlib/Makefile.am: + Install libBDM.a and libbdmflash.a in $(libdir). + +2004-01-21 joewolf + + * flashlib/flash29.c, flashlib/flash_filter.c, utils/bdmctrl.c: + - Fix return code from flash29_prog() when size%bus_width!=0. + - Fix return code in flash_filter:write_memory() when last chunk was + written partially. + +2004-01-20 codewiz + + * README.cvs: Hacker's documentation. + +2004-01-15 joewolf + + * flashlib/tcompile: Remove local configurations from tcompile script. + + * flashlib/flash_filter.c, flashlib/flash_filter.h, utils/bdmctrl.c: + Improve error checking in and diagnostic output in flashlib/bdmctrl. + +2004-01-14 joewolf + + * utils/Makefile.am: + - Enable bdmctrl to find BDMlib.h and bdm.h in source tree. + + * lib/bdmRemote.c: - Get port number from /etc/services. + +2004-01-12 codewiz + + * configure.ac: Release tweaks: + - generate distribution archives in .tar.gz, .tar.bz2 and .zip formats; + - change version from 2.0 to 20040112; + - change package name from bdm to m68k-bdm. + +2004-01-11 joewolf + + * driver/bdm.c, lib/bdmIO.c: - Clean up some debug output. + - Csaba Kormendy's fix for compile error when BDM_DEVICE_REMOTE is not set. + +2004-01-08 codewiz + + * configure.ac: Enable automake warnings. + + * bdmabstraction/Makefile.am, flashlib/Makefile.am, + lib/Makefile.am, server/Makefile.am, test/Makefile.am: + Fix warnings reported by automake about obsolete INCLUDE and CFLAGS variables. + + * utils/Makefile.am: + Avoid mixing up bdmflash headers with bdm_abstraction headers (breaks Cygwin builds). + + * config/ax_cflags_warn_all.m4: + autoconf macro to enable compiler warnings (imported from ac-archive). + + * utils/bdmmon.l: + Avoid duplicate definition of TRUE/FALSE. Remove trailing whitespace. + + * config/.cvsignore: Ignore automake provided 'compile' script. + + * configure.ac: Fix "configure --help" information for bdmmon. + (submitted by Csaba Kormendy ) + +2004-01-07 codewiz + + * bdmabstraction/Makefile.am: + Reoder includes to ensure local headers are always found first. + + * configure.ac: + Reorder subdirs and avoid double specification of flashlib/. + +2004-01-07 joewolf + + * flashlib/Makefile.am: + - Fix segfault in flash_filter.c caused by inclusion of wrong bfd.h. + +2004-01-07 codewiz + + * driver/win/win-bdm.c: + Apply patch to enable ICD cable for cygwin (Scott Newell ); + Remove trailing white-space. + + * utils/Makefile.am, README, configure.ac: + New configure options: --with-libbfd, --with-libiberty, --with-bfd-include-dir. + +2003-12-29 codewiz + + * bdmabstraction/.cvsignore, configure.ac, utils/.cvsignore, utils/Makefile.am: + Add bdmmon and bdmflash. + +2003-12-29 joewolf + + * utils/Makefile.am, utils/README.bdmctrl, utils/bdmctrl.c, configure.ac: + - Add host-only and target-assisted flash support (second try, first try was + aborted for some reason). + + * README, flashlib/Makefile.am, flashlib/README, + flashlib/flash29.c, flashlib/flash29.h, flashlib/flash_filter.c, + flashlib/flash_filter.h, flashlib/tcompile: + - Add host-only and target-assisted flash support. + +2003-12-29 codewiz + + * utils/bdmflash.c, utils/bdmmon.l: + Move bdmmon and bdmflash to m68k/utils. + + * bdmabstraction/BDMDriver.h, bdmabstraction/BDMFlash.c, + bdmabstraction/BDMFlash.h, bdmabstraction/BDMTargetAddress.c, + bdmabstraction/BDMTargetAddress.h, bdmabstraction/Debug.h, + bdmabstraction/Flash.c, bdmabstraction/Flash.h, + bdmabstraction/Makefile.am, bdmabstraction/bdmcf.h, + bdmabstraction/bdmops.c, bdmabstraction/bdmops.h: + Move tools/bdm_abstraction to m68k/bdmabstraction and autoconfiscate. + +2003-12-11 cjohns + + * driver/bdm.c: If a NVC is received clock some nops to see if the data + stream can be recovered. Also added some code to try and + detect the 17th bit which should be 0 and clock the extra + bits to realign the bit stream. The real cause of this type + of error is a bad pod or poor signal quality so the code + is not enabled by default. + +2003-12-02 joewolf + + * utils/bdmctrl.c, utils/README.bdmctrl: + - Add "step" command to bdmctrl. + +2003-11-30 joewolf + + * utils/bdmctrl.c: + - Delay pattern generation until they are really needed. Helps avoid noise. + +2003-11-26 codewiz + + * lib/Makefile.am: Include files required for source distribution. + + * flashlib/.cvsignore: Ignore generated files. + + * server/Makefile.in: Remove generated file. + +2003-11-26 joewolf + + * utils/bdmctrl.c: + - Make progress output of bdmctrl's load command a little more readable. + +2003-11-26 codewiz + + * server/.cvsignore, test/.cvsignore, utils/.cvsignore, + .cvsignore, lib/.cvsignore: + Ignore generated files. + + * Makefile.in, aclocal.m4, configure, flashlib/Makefile.in, + lib/Makefile.in, test/Makefile.in, utils/Makefile.in: + Remove generated files from CVS. + +2003-11-25 cjohns + + * driver/ioperm/ioperm.c: Fixed spelling mistakes. + +2003-11-25 joewolf + + * utils/README.bdmctrl, utils/bdmctrl.c: + - Add command "time" to bdmctrl. + - Make bdmctrl's progress outbut look better. + +2003-11-25 cjohns + + * driver/ioperm/ioperm.c: The delay is wrong by a factor or 10. + + * lib/bdmRemote.c: Fix the error in the remote open. + +2003-11-24 joewolf + + * utils/bdmctrl.c: - Output progress information while loading. + + * test/Makefile.in, test/chk.c: + - fix register number for address registers. + +2003-11-22 codewiz + + * .cvsignore, test/.cvsignore, utils/.cvsignore, lib/.cvsignore, + server/.cvsignore: + Ignore generated files. + + * server/.cvsignore: Ignore .deps dir. + +2003-11-15 cjohns + + * flashlib/Makefile.in, lib/Makefile.in, server/Makefile.in, + test/Makefile.in, utils/Makefile.in, Makefile.in, configure, + configure.ac: + Flash configure updated. + +2003-11-12 joewolf + + * utils/README.bdmctrl, utils/bdmctrl.c: + - Add warning for unknown architecture in bdmctrl's "load" command. + - minor bugfixes/extensions to bdmctrl and its README + +2003-11-10 ppisa + + * flashlib/Makefile.am, flashlib/Makefile.in, flashlib/bdmfilt.c, + flashlib/bdmfilt.h, flashlib/bdmflash.c, flashlib/bdmflash.h: + Initial step to add support for the FLASH programming in m68k tools branch. + The flash description structures will be probably rearranged in the near + future. + +2003-11-08 cjohns + + * Makefile.in, configure, lib/Makefile.in, server/Makefile.in, + test/Makefile.in, utils/Makefile.in: + Configure bootstrap. + +2003-11-07 joewolf + + * utils/README.bdmctrl, utils/bdmctrl.c: + - extend "dump-mem" command of bdmctrl to optionally write dumped memory + contents into a file. + + * README, configure.ac, utils/Makefile.am, driver/bdm.c: + - Add --enable-bdmctrl option to configure. Default is off. + +2003-11-06 joewolf + + * README: + - add a warning in the server installation section of the README. + + * utils/README.bdmctrl, utils/bdmctrl.c: + - Add (rudimentary) variable support to bdmctrl. + - Add commands "set", "read", "exit" to bdmctrl. + + * server/bdmServer.c, lib/bdmRemote.c: + - fix bdmWriteMemory() and bdmReadMemory() with large size. + + * server/bdmServer.c, lib/BDMlib.h, lib/bdmIO.c, + driver/ioperm/ioperm.c, driver/bdm.c: + - Fix problem with bdmSetDriverDebugFlag() when bdmd is + used. Remote diagnostics are sent to syslog now. + + * lib/Makefile.am, server/Makefile.am, test/Makefile.am, + utils/Makefile.am, configure.ac, Makefile.am: + - Remove overriding of CFLAGS by CFLAGS_BDM in autoconf. - add + evaluation of INCLUDES="-I /foo/bar" to autoconf. + +2003-11-03 joewolf + + * utils/bdmctrl.c: - fix two typos in bdmctrl.c. + - add echo command to bdmctrl.c. + +2003-10-28 joewolf + + * utils/README.bdmctrl, utils/bdmctrl.c, utils/m68332.test: + Add bdmctrl.c, its README and an example script for m68332. + +2003-09-21 codewiz + + * lib/BDMlib.h: Add missing prototype for bdmCheck(). + +2003-09-20 joewolf + + * driver/freebsd/freebsd-bdm.c: Fix more idc<->icd typos. + +2003-09-20 codewiz + + * driver/linux-2.6/.cvsignore, driver/linux-2.6/Makefile, + driver/linux-2.6/bdm.c, driver/linux-2.5/.cvsignore, + driver/linux-2.5/Makefile, driver/linux-2.5/bdm.c: Rename + linux-2.5 to linux-2.6. + + * driver/linux-2.5/bdm.c: Fix for 2.6.0-test5 + +2003-09-19 joewolf + + * driver/linux-2.5/bdm.c, driver/linux/linux-bdm.c: + Fix some gcc warnings. + + * README, driver/ioperm/ioperm.c, lib/bdmIO.c, lib/bdmRemote.c, + server/bdmServer.c, test/chk.c, test/cpu32-check.c: Fix some typos + and gcc warnings. + + * utils/bdmreset.c: Insert check for ICD interface. + + * driver/linux/Makefile, driver/linux/linux-bdm.c: + Adopted Pavels Makefile to m68k/driver/linux. + +2003-09-18 joewolf + + * README, test/README, test/chk.c, test/cpu32-check.c: + Fix some minor typos. + + * local_scripts/MAKEDEV, driver/ioperm/ioperm.c: + - Fix typos in MAKEDEV script. + - Add parsing for icd adaptor in ioperm_bdm_open(). + + * driver/ioperm/ioperm.c: + Fix argument type in ioctl() interface from ioperm to driver. + +2003-09-18 cjohns + + * lib/.cvsignore, lib/Makefile.in, server/.cvsignore, + server/Makefile.in, test/.cvsignore, test/Makefile.in, + utils/.cvsignore, utils/Makefile.in, .cvsignore, Makefile.in: + Makefile.in files are needed. Adjusted .cvsignore as well. + +2003-09-17 cjohns + + * .cvsignore, Makefile.am, aclocal.m4, config/bootstrap, + config/config.guess, config/config.sub, config/depcomp, + config/install-sh, config/missing, config/mkinstalldirs, + configure, configure.ac, lib/Makefile, lib/Makefile.am, + server/.cvsignore, server/Makefile, server/Makefile.am, + test/.cvsignore, test/Makefile, test/Makefile.am, + utils/.cvsignore, utils/Makefile, utils/Makefile.am: Autoconf and + automake support. + + * README: Updated with WIN32 and autotools info. + + * test/cpu32-check.c: + Changed interface to iface. It looks like winsock2.h has an + interface defined. + Add WIN32 sleep define. + + * test/chk.c: Add a hello message. + Display the version number is decimal rather than hex. + Add a WIN32 sleep define. + + * lib/bdmRemote.c: Removed extra white space at the end of lines. + Added WIN32 support for Winsock. This means sending by a single function + call bdmSocketSend. + + * lib/bdmIO.c: Include win-bdm.c when building WIN32 or Cygwin. + + * lib/.cvsignore: Ignores added. + + * driver/win/win-bdm.c: Moved the _IOWR and friend to bdm.h. + Add HZ if not defined. This happens on WIN32. + The nop is for GCC rather than just Cygwin. + + * driver/bdm.h: Added WIN32 support for _IO macros. + +2003-07-16 cjohns + + * README: Updated with I/O Perm support. + + * lib/bdmIO.c: Remote support is linked in rather than included. + Removed the atexit call to bdmClose. + Changed the open to not stat a file and support ioperm. + + * lib/Makefile: Support for the separate remote code. + + * lib/BDMlib.h: Added the GPL notice to the beginning. + + * lib/bdmRemote.c, lib/bdmRemote.h: + The remote protocol is now a separate file rather than + being included. + + * driver/linux/Makefile: + Add a check for kernel sources being installed. + + * driver/bdm.c: Only the print the debugFlag message when allowed. + + * server/bdmServer.c: Remove the unused cread local variable. + Add a call to bdmClose. The lack of a call will now not close the BDM driver + and so not reset the target. The target is not left running. + + * server/Makefile: relink if libBDM.a has changed. + + * server/.cvsignore: Ignore the bdmd server when present. + + * BUGS: Updated with the SF project for reporting bugs. + Added the 5407 problems. + Reformat with emacs. + + * driver/ioperm/ioperm.c: + IO perm support file to provide the support code for the BDM driver. This + is based on the Windows version but has support to try a driver and a local + BDM server if the ioperm call fails. + +2003-07-11 cjohns + + * lib/BDMlib.h, lib/Makefile, lib/ansidecl.h, lib/bdmBFD.c, + lib/bfd.h: Remove the bdmLoadImage call. This means the BFD + support and the hack of the local BFD headers can be removed. + +2003-06-28 cjohns + + * driver/win/win-bdm.c: + This version fixes the stat call problem on Windows. This helps + Insight run on Cygwin. + + * server/bdmServer.c: Close the server if the remote end disappears. + +2003-06-03 codewiz + + * utils/.cvsignore, driver/freebsd/.cvsignore: Ignore generated files. + +2003-06-02 codewiz + + * test/.cvsignore, driver/linux-2.5/.cvsignore: Ignore generated files. + + * server/Makefile, server/bdmServer.c, server/xmalloc.c, + test/ChangeLog, test/Makefile, test/README, + test/README.cpu32-check, test/chk.c, test/coldfire-trace, + test/cpu32-check.c, test/cpu32-memtest.list, test/sram-test.S, + utils/ChangeLog, utils/Makefile, utils/bdmreset.c, + driver/linux-2.5/bdm.c, driver/sco/Makefile, driver/sco/Master, + driver/sco/Node, driver/sco/README, driver/sco/Space.c, + driver/sco/System, driver/sco/sco.c, driver/win/ChangeLog, + driver/win/win-io.h, lib/BDMlib.h, lib/ChangeLog, lib/Makefile, + lib/ansidecl.h, lib/bdmBFD.c, lib/bdmIO.c, lib/bdmRemote.c, + lib/bfd.h, local_scripts/MAKEDEV, local_scripts/README, + local_scripts/build-it, local_scripts/makegdb68kbdm, + local_scripts/rtsetup, server/ChangeLog, driver/freebsd/ChangeLog, + driver/freebsd/Makefile, driver/freebsd/README, + driver/freebsd/bdm, driver/freebsd/bdm.8, + driver/freebsd/freebsd-bdm.c, driver/freebsd/unbdm, + driver/linux-2.5/Makefile, driver/linux/ChangeLog, + driver/linux/Makefile, driver/linux/linux-bdm.c, BUGS, README, + README.insight, driver/ChangeLog, driver/bdm.c, driver/bdm.h: + Import gdb-bdm-20020210 by Chris Johns. + diff --git a/m68k/INSTALL b/m68k/INSTALL new file mode 100644 index 0000000..5458714 --- /dev/null +++ b/m68k/INSTALL @@ -0,0 +1,234 @@ +Installation Instructions +************************* + +Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005, +2006 Free Software Foundation, Inc. + +This file is free documentation; the Free Software Foundation gives +unlimited permission to copy, distribute and modify it. + +Basic Installation +================== + +Briefly, the shell commands `./configure; make; make install' should +configure, build, and install this package. The following +more-detailed instructions are generic; see the `README' file for +instructions specific to this package. + + The `configure' shell script attempts to guess correct values for +various system-dependent variables used during compilation. It uses +those values to create a `Makefile' in each directory of the package. +It may also create one or more `.h' files containing system-dependent +definitions. Finally, it creates a shell script `config.status' that +you can run in the future to recreate the current configuration, and a +file `config.log' containing compiler output (useful mainly for +debugging `configure'). + + It can also use an optional file (typically called `config.cache' +and enabled with `--cache-file=config.cache' or simply `-C') that saves +the results of its tests to speed up reconfiguring. Caching is +disabled by default to prevent problems with accidental use of stale +cache files. + + If you need to do unusual things to compile the package, please try +to figure out how `configure' could check whether to do them, and mail +diffs or instructions to the address given in the `README' so they can +be considered for the next release. If you are using the cache, and at +some point `config.cache' contains results you don't want to keep, you +may remove or edit it. + + The file `configure.ac' (or `configure.in') is used to create +`configure' by a program called `autoconf'. You need `configure.ac' if +you want to change it or regenerate `configure' using a newer version +of `autoconf'. + +The simplest way to compile this package is: + + 1. `cd' to the directory containing the package's source code and type + `./configure' to configure the package for your system. + + Running `configure' might take a while. While running, it prints + some messages telling which features it is checking for. + + 2. Type `make' to compile the package. + + 3. Optionally, type `make check' to run any self-tests that come with + the package. + + 4. Type `make install' to install the programs and any data files and + documentation. + + 5. You can remove the program binaries and object files from the + source code directory by typing `make clean'. To also remove the + files that `configure' created (so you can compile the package for + a different kind of computer), type `make distclean'. There is + also a `make maintainer-clean' target, but that is intended mainly + for the package's developers. If you use it, you may have to get + all sorts of other programs in order to regenerate files that came + with the distribution. + +Compilers and Options +===================== + +Some systems require unusual options for compilation or linking that the +`configure' script does not know about. Run `./configure --help' for +details on some of the pertinent environment variables. + + You can give `configure' initial values for configuration parameters +by setting variables in the command line or in the environment. Here +is an example: + + ./configure CC=c99 CFLAGS=-g LIBS=-lposix + + *Note Defining Variables::, for more details. + +Compiling For Multiple Architectures +==================================== + +You can compile the package for more than one kind of computer at the +same time, by placing the object files for each architecture in their +own directory. To do this, you can use GNU `make'. `cd' to the +directory where you want the object files and executables to go and run +the `configure' script. `configure' automatically checks for the +source code in the directory that `configure' is in and in `..'. + + With a non-GNU `make', it is safer to compile the package for one +architecture at a time in the source code directory. After you have +installed the package for one architecture, use `make distclean' before +reconfiguring for another architecture. + +Installation Names +================== + +By default, `make install' installs the package's commands under +`/usr/local/bin', include files under `/usr/local/include', etc. You +can specify an installation prefix other than `/usr/local' by giving +`configure' the option `--prefix=PREFIX'. + + You can specify separate installation prefixes for +architecture-specific files and architecture-independent files. If you +pass the option `--exec-prefix=PREFIX' to `configure', the package uses +PREFIX as the prefix for installing programs and libraries. +Documentation and other data files still use the regular prefix. + + In addition, if you use an unusual directory layout you can give +options like `--bindir=DIR' to specify different values for particular +kinds of files. Run `configure --help' for a list of the directories +you can set and what kinds of files go in them. + + If the package supports it, you can cause programs to be installed +with an extra prefix or suffix on their names by giving `configure' the +option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. + +Optional Features +================= + +Some packages pay attention to `--enable-FEATURE' options to +`configure', where FEATURE indicates an optional part of the package. +They may also pay attention to `--with-PACKAGE' options, where PACKAGE +is something like `gnu-as' or `x' (for the X Window System). The +`README' should mention any `--enable-' and `--with-' options that the +package recognizes. + + For packages that use the X Window System, `configure' can usually +find the X include and library files automatically, but if it doesn't, +you can use the `configure' options `--x-includes=DIR' and +`--x-libraries=DIR' to specify their locations. + +Specifying the System Type +========================== + +There may be some features `configure' cannot figure out automatically, +but needs to determine by the type of machine the package will run on. +Usually, assuming the package is built to be run on the _same_ +architectures, `configure' can figure that out, but if it prints a +message saying it cannot guess the machine type, give it the +`--build=TYPE' option. TYPE can either be a short name for the system +type, such as `sun4', or a canonical name which has the form: + + CPU-COMPANY-SYSTEM + +where SYSTEM can have one of these forms: + + OS KERNEL-OS + + See the file `config.sub' for the possible values of each field. If +`config.sub' isn't included in this package, then this package doesn't +need to know the machine type. + + If you are _building_ compiler tools for cross-compiling, you should +use the option `--target=TYPE' to select the type of system they will +produce code for. + + If you want to _use_ a cross compiler, that generates code for a +platform different from the build platform, you should specify the +"host" platform (i.e., that on which the generated programs will +eventually be run) with `--host=TYPE'. + +Sharing Defaults +================ + +If you want to set default values for `configure' scripts to share, you +can create a site shell script called `config.site' that gives default +values for variables like `CC', `cache_file', and `prefix'. +`configure' looks for `PREFIX/share/config.site' if it exists, then +`PREFIX/etc/config.site' if it exists. Or, you can set the +`CONFIG_SITE' environment variable to the location of the site script. +A warning: not all `configure' scripts look for a site script. + +Defining Variables +================== + +Variables not defined in a site shell script can be set in the +environment passed to `configure'. However, some packages may run +configure again during the build, and the customized values of these +variables may be lost. In order to avoid this problem, you should set +them in the `configure' command line, using `VAR=value'. For example: + + ./configure CC=/usr/local2/bin/gcc + +causes the specified `gcc' to be used as the C compiler (unless it is +overridden in the site shell script). + +Unfortunately, this technique does not work for `CONFIG_SHELL' due to +an Autoconf bug. Until the bug is fixed you can use this workaround: + + CONFIG_SHELL=/bin/bash /bin/bash ./configure CONFIG_SHELL=/bin/bash + +`configure' Invocation +====================== + +`configure' recognizes the following options to control how it operates. + +`--help' +`-h' + Print a summary of the options to `configure', and exit. + +`--version' +`-V' + Print the version of Autoconf used to generate the `configure' + script, and exit. + +`--cache-file=FILE' + Enable the cache: use and save the results of the tests in FILE, + traditionally `config.cache'. FILE defaults to `/dev/null' to + disable caching. + +`--config-cache' +`-C' + Alias for `--cache-file=config.cache'. + +`--quiet' +`--silent' +`-q' + Do not print messages saying which checks are being made. To + suppress all normal output, redirect it to `/dev/null' (any error + messages will still be shown). + +`--srcdir=DIR' + Look for the package's source code in directory DIR. Usually + `configure' can determine that directory automatically. + +`configure' also accepts some other, not widely useful, options. Run +`configure --help' for more details. + diff --git a/m68k/Makefile.am b/m68k/Makefile.am new file mode 100644 index 0000000..771ad92 --- /dev/null +++ b/m68k/Makefile.am @@ -0,0 +1,57 @@ +## +## $Id: Makefile.am,v 1.8 2004/06/01 02:02:25 codewiz Exp $ +## +## This file is part of a free BDM package +## +## 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. +## + +CFLAGS = @CFLAGS@ + +SUBDIRS = @BDM_SUBDIRS@ + +EXTRA_DIST = \ + README.insight \ + BUGS \ + config/bootstrap \ + driver/freebsd/bdm \ + driver/freebsd/bdm.8 \ + driver/freebsd/freebsd-bdm.c \ + driver/freebsd/Makefile \ + driver/freebsd/README \ + driver/freebsd/setdef0.c \ + driver/freebsd/setdef1.c \ + driver/freebsd/unbdm \ + driver/freebsd/bus_if.h \ + driver/freebsd/device_if.h \ + driver/freebsd/isa_if.h \ + driver/freebsd/setdefs.h \ + driver/openbsd/Makefile \ + driver/openbsd/README \ + driver/openbsd/bdm-install.sh \ + driver/openbsd/openbsd-bdm.c \ + driver/linux/linux-bdm.c \ + driver/linux/Makefile \ + driver/linux-2.6/bdm.c \ + driver/linux-2.6/Makefile \ + driver/sco/Makefile \ + driver/sco/Master \ + driver/sco/Node \ + driver/sco/README \ + driver/sco/sco.c \ + driver/sco/Space.c \ + driver/sco/System \ + driver/win/win-bdm.c \ + driver/win/win-io.h + +dist-hook: + cp -R -p $(srcdir)/local_scripts $(distdir) + rm -r -f `find $(distdir)/local_scripts -name CVS` + cp -R -p $(srcdir)/../gdb $(distdir) + rm -r -f `find $(distdir)/gdb -name CVS` + cp -R -p $(srcdir)/../schematics $(distdir) + rm -r -f `find $(distdir)/schematics -name CVS` + diff --git a/m68k/Makefile.in b/m68k/Makefile.in new file mode 100644 index 0000000..e0fdb2d --- /dev/null +++ b/m68k/Makefile.in @@ -0,0 +1,666 @@ +# Makefile.in generated by automake 1.10 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +subdir = . +DIST_COMMON = README $(am__configure_deps) $(srcdir)/Makefile.am \ + $(srcdir)/Makefile.in $(srcdir)/config.h.in \ + $(top_srcdir)/configure COPYING ChangeLog INSTALL \ + config/compile config/config.guess config/config.sub \ + config/depcomp config/install-sh config/missing \ + config/mkinstalldirs config/ylwrap +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \ + configure.lineno config.status.lineno +mkinstalldirs = $(SHELL) $(top_srcdir)/config/mkinstalldirs +CONFIG_HEADER = config.h +CONFIG_CLEAN_FILES = +SOURCES = +DIST_SOURCES = +RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \ + html-recursive info-recursive install-data-recursive \ + install-dvi-recursive install-exec-recursive \ + install-html-recursive install-info-recursive \ + install-pdf-recursive install-ps-recursive install-recursive \ + installcheck-recursive installdirs-recursive pdf-recursive \ + ps-recursive uninstall-recursive +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive +ETAGS = etags +CTAGS = ctags +DIST_SUBDIRS = $(SUBDIRS) +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +distdir = $(PACKAGE)-$(VERSION) +top_distdir = $(distdir) +am__remove_distdir = \ + { test ! -d $(distdir) \ + || { find $(distdir) -type d ! -perm -200 -exec chmod u+w {} ';' \ + && rm -fr $(distdir); }; } +DIST_ARCHIVES = $(distdir).tar.gz $(distdir).tar.bz2 $(distdir).zip +GZIP_ENV = --best +distuninstallcheck_listfiles = find . -type f -print +distcleancheck_listfiles = find . -type f -print +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AR = @AR@ +AS = @AS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BDM_SUBDIRS = @BDM_SUBDIRS@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FLASH_PLUGIN_GCC = @FLASH_PLUGIN_GCC@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBUSB_INCLUDE_DIR = @LIBUSB_INCLUDE_DIR@ +LIBUSB_LIB_DIR = @LIBUSB_LIB_DIR@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +RANLIB = @RANLIB@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +flash_plugin_cc = @flash_plugin_cc@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +subdirs = @subdirs@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +SUBDIRS = @BDM_SUBDIRS@ +EXTRA_DIST = \ + README.insight \ + BUGS \ + config/bootstrap \ + driver/freebsd/bdm \ + driver/freebsd/bdm.8 \ + driver/freebsd/freebsd-bdm.c \ + driver/freebsd/Makefile \ + driver/freebsd/README \ + driver/freebsd/setdef0.c \ + driver/freebsd/setdef1.c \ + driver/freebsd/unbdm \ + driver/freebsd/bus_if.h \ + driver/freebsd/device_if.h \ + driver/freebsd/isa_if.h \ + driver/freebsd/setdefs.h \ + driver/openbsd/Makefile \ + driver/openbsd/README \ + driver/openbsd/bdm-install.sh \ + driver/openbsd/openbsd-bdm.c \ + driver/linux/linux-bdm.c \ + driver/linux/Makefile \ + driver/linux-2.6/bdm.c \ + driver/linux-2.6/Makefile \ + driver/sco/Makefile \ + driver/sco/Master \ + driver/sco/Node \ + driver/sco/README \ + driver/sco/sco.c \ + driver/sco/Space.c \ + driver/sco/System \ + driver/win/win-bdm.c \ + driver/win/win-io.h + +all: config.h + $(MAKE) $(AM_MAKEFLAGS) all-recursive + +.SUFFIXES: +am--refresh: + @: +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + echo ' cd $(srcdir) && $(AUTOMAKE) --foreign '; \ + cd $(srcdir) && $(AUTOMAKE) --foreign \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign Makefile'; \ + cd $(top_srcdir) && \ + $(AUTOMAKE) --foreign Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + echo ' $(SHELL) ./config.status'; \ + $(SHELL) ./config.status;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + $(SHELL) ./config.status --recheck + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(srcdir) && $(AUTOCONF) +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS) + +config.h: stamp-h1 + @if test ! -f $@; then \ + rm -f stamp-h1; \ + $(MAKE) $(AM_MAKEFLAGS) stamp-h1; \ + else :; fi + +stamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status + @rm -f stamp-h1 + cd $(top_builddir) && $(SHELL) ./config.status config.h +$(srcdir)/config.h.in: $(am__configure_deps) + cd $(top_srcdir) && $(AUTOHEADER) + rm -f stamp-h1 + touch $@ + +distclean-hdr: + -rm -f config.h stamp-h1 + +# This directory's subdirectories are mostly independent; you can cd +# into them and run `make' without going through this Makefile. +# To change the values of `make' variables: instead of editing Makefiles, +# (1) if the variable is set in `config.status', edit `config.status' +# (which will cause the Makefiles to be regenerated when you run `make'); +# (2) otherwise, pass the desired values on the `make' command line. +$(RECURSIVE_TARGETS): + @failcom='exit 1'; \ + for f in x $$MAKEFLAGS; do \ + case $$f in \ + *=* | --[!k]*);; \ + *k*) failcom='fail=yes';; \ + esac; \ + done; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +$(RECURSIVE_CLEAN_TARGETS): + @failcom='exit 1'; \ + for f in x $$MAKEFLAGS; do \ + case $$f in \ + *=* | --[!k]*);; \ + *k*) failcom='fail=yes';; \ + esac; \ + done; \ + dot_seen=no; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + rev=''; for subdir in $$list; do \ + if test "$$subdir" = "."; then :; else \ + rev="$$subdir $$rev"; \ + fi; \ + done; \ + rev="$$rev ."; \ + target=`echo $@ | sed s/-recursive//`; \ + for subdir in $$rev; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done && test -z "$$fail" +tags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ + done +ctags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \ + done + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: tags-recursive $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + tags="$$tags $$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique; \ + fi +ctags: CTAGS +CTAGS: ctags-recursive $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(CTAGS_ARGS)$$tags$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && cd $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) $$here + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + $(am__remove_distdir) + test -d $(distdir) || mkdir $(distdir) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done + list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test -d "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ + || exit 1; \ + distdir=`$(am__cd) $(distdir) && pwd`; \ + top_distdir=`$(am__cd) $(top_distdir) && pwd`; \ + (cd $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$top_distdir" \ + distdir="$$distdir/$$subdir" \ + am__remove_distdir=: \ + am__skip_length_check=: \ + distdir) \ + || exit 1; \ + fi; \ + done + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$(top_distdir)" distdir="$(distdir)" \ + dist-hook + -find $(distdir) -type d ! -perm -777 -exec chmod a+rwx {} \; -o \ + ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \ + ! -type d ! -perm -400 -exec chmod a+r {} \; -o \ + ! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \ + || chmod -R a+r $(distdir) +dist-gzip: distdir + tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz + $(am__remove_distdir) +dist-bzip2: distdir + tardir=$(distdir) && $(am__tar) | bzip2 -9 -c >$(distdir).tar.bz2 + $(am__remove_distdir) + +dist-tarZ: distdir + tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z + $(am__remove_distdir) + +dist-shar: distdir + shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz + $(am__remove_distdir) +dist-zip: distdir + -rm -f $(distdir).zip + zip -rq $(distdir).zip $(distdir) + $(am__remove_distdir) + +dist dist-all: distdir + tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz + tardir=$(distdir) && $(am__tar) | bzip2 -9 -c >$(distdir).tar.bz2 + -rm -f $(distdir).zip + zip -rq $(distdir).zip $(distdir) + $(am__remove_distdir) + +# This target untars the dist file and tries a VPATH configuration. Then +# it guarantees that the distribution is self-contained by making another +# tarfile. +distcheck: dist + case '$(DIST_ARCHIVES)' in \ + *.tar.gz*) \ + GZIP=$(GZIP_ENV) gunzip -c $(distdir).tar.gz | $(am__untar) ;;\ + *.tar.bz2*) \ + bunzip2 -c $(distdir).tar.bz2 | $(am__untar) ;;\ + *.tar.Z*) \ + uncompress -c $(distdir).tar.Z | $(am__untar) ;;\ + *.shar.gz*) \ + GZIP=$(GZIP_ENV) gunzip -c $(distdir).shar.gz | unshar ;;\ + *.zip*) \ + unzip $(distdir).zip ;;\ + esac + chmod -R a-w $(distdir); chmod a+w $(distdir) + mkdir $(distdir)/_build + mkdir $(distdir)/_inst + chmod a-w $(distdir) + dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \ + && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \ + && cd $(distdir)/_build \ + && ../configure --srcdir=.. --prefix="$$dc_install_base" \ + $(DISTCHECK_CONFIGURE_FLAGS) \ + && $(MAKE) $(AM_MAKEFLAGS) \ + && $(MAKE) $(AM_MAKEFLAGS) dvi \ + && $(MAKE) $(AM_MAKEFLAGS) check \ + && $(MAKE) $(AM_MAKEFLAGS) install \ + && $(MAKE) $(AM_MAKEFLAGS) installcheck \ + && $(MAKE) $(AM_MAKEFLAGS) uninstall \ + && $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \ + distuninstallcheck \ + && chmod -R a-w "$$dc_install_base" \ + && ({ \ + (cd ../.. && umask 077 && mkdir "$$dc_destdir") \ + && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \ + && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \ + && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \ + distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \ + } || { rm -rf "$$dc_destdir"; exit 1; }) \ + && rm -rf "$$dc_destdir" \ + && $(MAKE) $(AM_MAKEFLAGS) dist \ + && rm -rf $(DIST_ARCHIVES) \ + && $(MAKE) $(AM_MAKEFLAGS) distcleancheck + $(am__remove_distdir) + @(echo "$(distdir) archives ready for distribution: "; \ + list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \ + sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x' +distuninstallcheck: + @cd $(distuninstallcheck_dir) \ + && test `$(distuninstallcheck_listfiles) | wc -l` -le 1 \ + || { echo "ERROR: files left after uninstall:" ; \ + if test -n "$(DESTDIR)"; then \ + echo " (check DESTDIR support)"; \ + fi ; \ + $(distuninstallcheck_listfiles) ; \ + exit 1; } >&2 +distcleancheck: distclean + @if test '$(srcdir)' = . ; then \ + echo "ERROR: distcleancheck can only run from a VPATH build" ; \ + exit 1 ; \ + fi + @test `$(distcleancheck_listfiles) | wc -l` -eq 0 \ + || { echo "ERROR: files left in build directory after distclean:" ; \ + $(distcleancheck_listfiles) ; \ + exit 1; } >&2 +check-am: all-am +check: check-recursive +all-am: Makefile config.h +installdirs: installdirs-recursive +installdirs-am: +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-recursive + +clean-am: clean-generic mostlyclean-am + +distclean: distclean-recursive + -rm -f $(am__CONFIG_DISTCLEAN_FILES) + -rm -f Makefile +distclean-am: clean-am distclean-generic distclean-hdr distclean-tags + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +info: info-recursive + +info-am: + +install-data-am: + +install-dvi: install-dvi-recursive + +install-exec-am: + +install-html: install-html-recursive + +install-info: install-info-recursive + +install-man: + +install-pdf: install-pdf-recursive + +install-ps: install-ps-recursive + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -f $(am__CONFIG_DISTCLEAN_FILES) + -rm -rf $(top_srcdir)/autom4te.cache + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-generic + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +uninstall-am: + +.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) install-am \ + install-strip + +.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \ + all all-am am--refresh check check-am clean clean-generic \ + ctags ctags-recursive dist dist-all dist-bzip2 dist-gzip \ + dist-hook dist-shar dist-tarZ dist-zip distcheck distclean \ + distclean-generic distclean-hdr distclean-tags distcleancheck \ + distdir distuninstallcheck dvi dvi-am html html-am info \ + info-am install install-am install-data install-data-am \ + install-dvi install-dvi-am install-exec install-exec-am \ + install-html install-html-am install-info install-info-am \ + install-man install-pdf install-pdf-am install-ps \ + install-ps-am install-strip installcheck installcheck-am \ + installdirs installdirs-am maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-generic pdf \ + pdf-am ps ps-am tags tags-recursive uninstall uninstall-am + + +dist-hook: + cp -R -p $(srcdir)/local_scripts $(distdir) + rm -r -f `find $(distdir)/local_scripts -name CVS` + cp -R -p $(srcdir)/../gdb $(distdir) + rm -r -f `find $(distdir)/gdb -name CVS` + cp -R -p $(srcdir)/../schematics $(distdir) + rm -r -f `find $(distdir)/schematics -name CVS` +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/m68k/README b/m68k/README new file mode 100644 index 0000000..da1b258 --- /dev/null +++ b/m68k/README @@ -0,0 +1,909 @@ + + BDM GDB DRIVER AND LIBRARY PACKAGE + ================================== + +INTRODUCTION +============ + +This package contains everything you need to know to be able to run GDB on +Linux, FreeBSD, SCO Unix, and Windows and control a Motorola CPU32+ (68360) or +Coldfire (V2/V3/V4) target through a standard PC parallel port or via a USB +pod. + + o The CPU32 interfaces supported are PD and the IDC interface. GDB + should now operate with the CPU32 processor without error. + + o The Coldfire interface is the TBLCF USB pod or P&E parallel port type + interface. + + o You can build Insight if you apply the Insight patch. See the + Insight README in this directory. + + o For WindowsNT or Window2000 you will need the GiveIO package. You + are best to search the net for the GiveIO (giveio.sys) package. You + will also need the INSTDRV.EXE file that is also available on the net. + GiveIO has been test on Windows 2000 and Windows XP. + + o For Unix users the library is built with I/O perm support by + default. The same library allows an application to directly + access the hardware or use an installed BDM kernel driver. On FreeBSD + this the "/dev/io" support. + + I/O Permission is a means of getting at the parallel port hardware + without the need for a kernel driver. This BDM package still provides + support to build a kernel driver, but you do not need to if you want to + avoid kernel drivers. Some people wish to use kernel drivers and some do + not. + + If you wish to learn more about I/O Perm support please refer to the + section at the end of the file. + + You can disable I/O perm support by editing the Makefile. It is hoped + autoconf support in the future will provide a better way to handle this. + + o To support the TBLCF UDB pod you will need the libusb package. For Windows + this means the LibUSB-Win32 package. + + o Support for an initialisation script called '.m68kbdminit'. See the + section on Initialisation Scripts. + +The subdirectories contain: + + config + Autotools support files. + + driver + Source for a Linux, SCO, FreeBSD, I/O Perm, and Windows BDM device + driver module. + + gdbPatches + Move to outside this tree. Please refer to the Sourceforge + project for the patches. + + gdbScripts + Example GDB command scripts that show how to initialize and run + a Motorola 68360 system using standard GDB commands. + + gdbserver + A GDB Remote protocol server. Needs GDB 6.7 or later. + + lib + User-level library routines for accessing the BDM device driver. + + flashlib + Library for flash support. This library currently supports host-only + and host-assisted operation modes of 29Fxxx and 49Fxxx chips in + any combination of bus_width=[1|2|4] and chip_width=[1|2|4]. It is + already prepared for target-only operation mode and addition of different + flash algorithms. + + local_scripts + Scripts to run on the host machine the driver is being installed + on. + + server + The BDM server. This is a daemon which interfaces to the local BDM + driver remotely. The BDM library can be built to support local and remote, + just local or just remote access. + + tblcf + The TBLCF code from Daniel Malik. It include the various tools for managing + the pod. + + test + Programs to test the BDM library and driver routines. + + utils + contains some utilities which might be useful. + +README Files +============ + +There are 4 README files which document the BDM package. They are: + + o README + This is the top level README file and the one you are currently readling. + + o README.cvs + If you use the code from CVS you should read this file. It explains how + to bootstrap the package to create the configure script and Makefiles. + + o README.bdmgdbserver + This file documents the BDM GDB Server. It explains why you should use + the BDM GDB Server to interface to GDB and how to build GDB. + + o README.insight + This is an old README and may be useful to anyone still wanting to + use Insight as a GUI interface to GDB. A current Insight with a current + GDB should work with the BDM GDB Server. + +WINDOWS +======= + +Windows is supported on Windows 98, Windows 2000 and Windows XP. It may run on +other version of Windows, but the ones listed have been tested. Windows 2000, +Windows XP and beyond need to the GiveIO driver to gain direct access to the +parallel port hardware if you are using a parallel port pod. A USB pod need the +libusb software for Windows. + +You can download the GiveIO package from the net plus you will need the +INSTDRV.EXE program. To install GiveIO place the 'giveio.sys' and INSTDRV.EXE +in a directory and log in as an Administrator or equivalent then: + + c:\tmp> insdrv givio c:\tmp\giveio.sys + +The package builds under Cygwin and MinGW. + +The MinGW support provides you with a version that directly accesses the +Windows APIs and does not need a Cygwin DLL. To build with MinGW you need to +get the MinGW and MSYS packages from the MinGW web site: + + http://www.mingw.org/ + +The MinGW package provides the compiler and MSYS provides a shell capable of +running the configure script. + +To build the TBLCF USB pod support you need to obtain the LibUsb-Win32 package +from: + + http://libusb-win32.sourceforge.net/ + +Click the Downloads link and move the Sourceforge download page then select the +libusb-win32-device-bin package. I have tested with the 0.1.12 version. Unpack +the tar file to a directory on your machine ready to use. Make sure you do not +have any spaces in the path. Spaces cause problems with the autoconf test for +the libusb library. + +QUICK START +=========== + +You have unpacked the package. Next to the top of the package create an empty +directory and enter it, configure the package, make, then install. + + $ tar xzf bdm-xx.tar.gz + $ mkdir build + $ cd build + $ ../gdb-bdm-xxx/m68k/configure + $ make + $ make install + +Note: this process by default creates an IOPERM type parallel BDM driver and a +TBLCF USB driver. If you wish to build a Linux kernel driver please follow the +INSTALLATION directions. + +INSTALLATION +============ + +The Makefiles in all the subdirectories are set up to install their +results in /usr/{bin,lib,.....}. + +On FreeBSD remember to use `gmake' rather than `make'. + +Notes: + + 1. For Windows move to Step 2 as the driver is built into the library. You + may also need to add `CC=gcc' to make's command line. + + 2. For I/O Permission or USB users move to step 2 as the driver is built + into the library. + + 3. Driver users will still have a library with I/O perm support unless the + default of the library Makefile is manually changed. + + 4. You can specify a different `prefix' for the installation directory by + running all the `make install' commands described below as: + + $ make prefix=/some/directory install + +Step 1 -- Compile and install the BDM device driver + + If you do not wish to use a driver and just want the I/O perm support move to + Step 2. + + Make sure the kernel source code is installed under the /usr/src path. + + Support for more than Linux has been added. You must enter the OS specific + directory then enter the make command. We assume Linux for the remainder of + this file. + + If your Linux kernel has been configured for module versions you must + uncomment the #MODVERSIONS=-DMODVERSIONS line in driver/linux Makefile. If + the kernel is configured for module versions and you fail to uncomment this + line the driver will install and work properly, but depmod will complain + about unresolved symbols. + + For Coldfire users the driver now looks for the debug module version and will + use the PST signals if it detects a version 1 debug module. The debug version + 1 is found on the 5307. + + Disable the TBLCF code with the configure option '--disable-tblcf'. + + # cd driver/linux + # make all install + + You may get a bunch of error messages like: + In file included from /usr/include/linux/fs.h:277, + from linux-bdm.c:63: + /usr/include/linux/hpfs_fs_i.h:5: parse error before `ino_t' + /usr/include/linux/hpfs_fs_i.h:5: warning: no semicolon at \ + end of struct or union + /usr/include/linux/hpfs_fs_i.h:12: parse error before `:' + + If this happens, try adding `-I /usr/include' to the beginning of the CFLAGS + definition in the Makefile in driver/linux. + + A script is provided in `local_scripts' called MAKEDEV which create the + special files needed for the CPU32 and Coldfire. + + To make the special files by hand you can enter: + + # mknod /dev/bdmcpu320 c 34 0 + ^^ ^ + | | + | +--Minor device number (see below). + | + +--This value must match the + BDM_MAJOR_NUMBER in driver/bdm.h + + To have the module module loaded by kerneld when needed + adding to /etc/conf.modules the line: + + alias char-major-34 bdm + + To automaticially load the driver into the kernel every time + you reboot you can add the line: + + # /sbin/insmod bdm + + to your startup script, such as /etc/rc.d/rc.local. + + You will need to create the device names. The local script MAKEDEV can do + this for you: + + # ./local_scripts/MAKEDEV + +Step 2 -- Compile and install the library and user programs + + The package provides a configure script that you use to build the + package. All testing I have performed is not to build in the source tree. For + the default configuration just run the configure script: + + $ mkdir build + $ cd build + $ ../gdb-bdm-xx/m68k/configure + + You will need to change the 'gdb-bdm-xx' to the name of the directory in the + version of the package you have downloaded. + + On Windows if building the TBLCF driver you need to provide the location of + the libusb package. The details to download and obtain the libusb package for + Windows is detail above. Provide the path to the top of the libusb package: + + $ ../gdb-bdm-xx/m68k/configure \ + --with-usblib-dir="c:/work/libusb-win32-device-bin-0.1.12.1" + + The above command is run inside the MSYS shell. + + Once the package has configured itself you can make it: + + $ make + + To install you may need to obtain the appropriate permissions. Once you have: + + $ make install + + The library can be built to access a BDM driver locally via the kernel's + driver interface, remotely via a TCP/IP socket interfacei, or with direct + hardware access via the ioperm system call. You can have a library which + supports all or a mix of interfaces. This allows you to build the + library and therefore gdb on a host which does not support the driver + interface. + + On Windows 2000 install the GiveIO driver. This is detailed in the WINDOWS + section earlier. To install the USB pod on Windows refer the TBLCF Pod + section later. + + The package supports a number of configuration options over and above the + standard configure options such as '--prefix'. These are: + + --enable-debug: Turn on compiler debug information + On by default. + + --enable-remote: Turn on the remote protocol and build it into + the library. On by default. + + --enable-ioperm: Turn on direct IOPERM hardware access. Enabled + if the OS provides the ioperm() system call. + + --enable-driver: Turn on driver access from the library. Enabled + by default on systems that support it. + + --enable-server: Turn on building the BDM server. On by default. + + --enable-flashlib: Turn on building of the flashlib. + + --enable-bdmctrl: Turn on building of the bdmctrl utility. Since there + might be problems to locate bfd.h/libbfd.a which + know how to handle target object files, building + the bdmctrl utility is disabled unless you have + specified the configure options --with-libbfd, + --with-libiberty and --with-bfd-include-dir. + + --enable-tblcf: Turn on building the TBLCF support. On by default. + On Windows the --with-usblib-dir can be used to + provide the location of the unpacked Win32 libusb + package. + + --with-libusb-dir Path, with no spaces to the libusb library if the + library is not installed in the default location. + + To turn off an option use '--disable-*' where '*' is one of the above. + + Some host settings automatically disable some options: + + Linux : All default settings. + Cygwin: All default settings. + MinGW : Server is not built. + + The prefix defaults to the platform specific default. Please refer to your + documentation for this default setting or just try and see what happens. + + Note, the BDM library is now installed under the package directory of 'bdm' + under the prefix. For example a prefix of '/usr/local' as found on Linux + results in the library being under '/usr/local/lib/bdm/libBDM.a'. + + The BDM package also supports cross-compiling. For example you can build + for a mingw32 host on a Linux machine if you have a MinGW cross-compiler + and runtime installed: + + $ ../gdb-bdm-xx/m68k/configure --host=ming32 \ + --build=`./gdb-bdm-xx/m68k/config/config.guess` + +Step 3 -- Installing the Server + + You only need the BDM server if you intend to use the ioperm method of + accessing the parallel port, or you wish to support remote access. If you + wish to use a driver and your access is local to your development machine + then this step may be skipped. + + Before using the server, please make sure you understand the implications + of such a setup. You probably want to restrict access to the bdmd port + to trusted machines. + + The BDM server allows a lab to contain your target hardware and you can + access it from your development machine. The BDM server can support clients + on different platforms. This means a Linux server can be accessed from MacOS + or Windows clients. + + The server runs from the xinetd or inetd daemon, and installs into + the 'sbin' directory under the configure prefix when building the user + programs in Step 2 above. + + You need to edit the /etc/services file to add the port number bdmd + uses. Add this line at the bottom of the /etc/services file: + + bdm 6543/tcp # BDM server + + The BDM remote library will check /etc/services to see if a port is + provided. If not found the remote library will default to 6543. + + It is recommended you add the entry to /etc/services and you check + the client and server match. + + For inetd users such as FreeBSD: + + You need to edit the /etc/inetd.conf file. Add this line at the end of + /etc/inetd.conf: + + bdm stream tcp nowait root /usr/local/sbin/bdmd bdmd + + You can specify any user including root. If you are wishing to use the + ioperm support then the user must be root. + + For xinetd users as root install the follow in a file called: + + /etc/xinetd.d/bdm + + service bdm + { + socket_type = stream + port = 6543 + wait = no + user = root + server = /usr/sbin/bdmd + server_args = -n + log_on_failure += USERID + disable = no + } + + then get xinetd to reload its configuration. + + To test the bdmd server open a shell on the machine bdmd has been installed + and condigured. At the shell prompt run telnet as follows: + + $ telnet localhost bdm + Trying 127.0.0.1... + Connected to localhost. + Escape character is '^]'. + >> helo + HELO 2 ted BDM server 1.0.0 ready. + >> quit + Connection closed by foreign host. + $ + + The lines marked '>>' you type and press enter. Once the connected to + localhost appears enter 'helo' and enter. The server should respond with + version etc. To exit enter 'quit' then enter. + + If is not working you are best to check your system log (/var/log/messages) + to locate the reason xinetd is not starting the bdmd server. To debug an + xinetd setup, as root do: + + # kill -SIGUSR1 $(pidof xinetd) + # less /var/run/xinetd.dump + + The look for the BDM entry and check entry is correct. Here is an + example: + + Service = bdm + State = Active + Service configuration: bdm + id = bdm + flags = IPv4 + socket_type = stream + Protocol (name,number) = (tcp,6) + port = 6543 + Groups = no + Bind = All addresses. + Server = /usr/sbin/bdmd + Server argv = bdmd -n + Only from: All sites + No access: No blocked sites + Logging to syslog. Facility = authpriv, level = info + Log_on_success flags = HOST PID + Log_on_failure flags = HOST USERID + running servers = 1 + retry servers = 0 + attempts = 0 + service fd = 5 + +Step 4 -- (Optional) Testing the driver. + + It a good idea to build and run the test program called `bdm-chk' for + Coldfire processors and 'bdm-cpu32-chk' for CPU32 processors. This will show + the library built correctly, the driver loads and functions, and your + hardware is connected correctly and functioning. + + You will need to select the correct device for the Coldfire. The example + below is for the CPU32 interface on LPT1. To test a CPU32 processor do: + + $ cd test + $ ./bdm-chk /dev/bdmcpu320 + + To test a Coldfire processor do: + + $ ./bdm-chk /dev/bdmcf0 + + Note, the number at the end of the device path is the parallel + port number your pod hardware is connected too. The device nodes + start from 0, while the standard PC LPT ports number from 1. This + means '/dev/bdmcf0' will look for a Coldfire processor on LPT1. + + For a TBLCF USB pod on Linux you need to set up udev to create a symlink. + The section 'TBLCF USB Support' details how to set up udev. The TBLCF tools + tblcf-show returns the following for a single pod connected to a Linux box: + + $ ./tblcf-show + TBLCF Turbo BDM Light ColdFire Show + + Found 1 device(s) + 1: 001-012 + + There is one pod and the name is '01-012' and udev links this to + /dev/tblcf3. To run check using this pod: + + $ ./bdm-chk /dev/tblcf3 + + Note, the name will change on Linux if you disconnect the pod and reconnect + it. If want to lock a name down you can use udev. + + To test using a BDM server on a remote host call 'foo': + + $ /bdm-chk foo:/dev/bdmcpu320 + + Note, do not use the MSYS rxtv shell to test from. It currently transforms + program arguments and the device path used in these example becomes + something very different. + +Step 5 -- Patch your GDB distribution +Step 6 -- Compile and install the cross-GDB with BDM support + + These step have been removed. We do not need to patch GDB any more. Use the + m68k-bdm-gdbserver executable with GDB built from the FSF sources. + + Please refer to README.bdmgdbserver for instructions on using the BDM GDB + Server. + +Step 7 -- (Optional) Install the GDB scripts + + $ cd gdbScripts + $ make install + + You will have to change the scripts to match your CPU32(+) hardware. + +Step 8 -- Build a BDM interface + + See the Schematics directory for an example circuit. + +Step 7 -- Try it out + + This is left as an exercise for the reader..... + +INITIALISATION SCRIPTS +====================== + +The M68K BDM package supports initialisation scripts. The scripts are all +called '.m68kbdminit' and read from 3 locations during the bdmOpen call. The +locations are: + + 1. The current directory ($PWD) + 2. The user's home directory as specified by the "HOME" environment + variable. + 3. A user define location as specified by the "M68K_BDM_INIT" environment + variable. + +The files are plain text files and are read into a character array on after +another. The '#' is a comment character and line continuation using the '\' at +the end of a line is supported. + +The configurations supported are: + + dev: + "dev user-name device-name" + + A line starting with 'dev' followed by white space defines a device mapping + or renaming. The user-name is the name a user may use to reference a + device. The device-name is the name required by the hardware to access the + device. This can be used to map a difficult USB device name that libusb uses + to a simpler user friendly name. This helps users because the naming of USB + devices vary between host platforms. The device mapping also helps + configuration control of debugging scripts. A common script can reference a + name and each user in a team can place the actual device they use in the a + user specific file in their home directory. + +TBLCF USB SUPPORT +================= + +The TBLCF is the Turbo BDM Light Coldfire UDB Pod created by Daniel Malik back +in 2006. This is a GPL design for both hardware and software. It uses a small +microcontrolller and firmware in the pod and the open source libusb code to +provide the low level USB support on various hosts. + +The supported hosts are Linux, FreeBSD, and Windows. The specifics of the hosts +make the set up different for each. The scripts support helps user isolate +their host specifics. USB device names are helped by the 'dev' entry in the +M68K BDM script files. These entries allow you to make a simpler entry for a +more complex name. Use the' tblcf-show tool' to dump the names of the USB +devices you need to pass to the BDM software. On Linux you may wish to use read +the Linux section and use the udev interface. + +The USB support in the BDM package checks the device name against the devices +detected by libusb. Linux is an exception where special code is present to +handle udev created sym-links. The code will partial match the device node +against the libusb detected devices. For example if the libusb device node +found on Windows is 'bus-0-\\.\libusb0-0002-0x0425-0x1001' then you could use +'0002-0x0425-0x1001' to use the device. + +If you are a CPU32 user and would like to look at supporting the CPU32 +processor with this pod please contact the BDM mailing list. + +Linux +----- + +The USB pod is simple to support on Linux. Just plug it and check the kernel +messages: + + $ dmesg | tail + usb 1-1.2: new low speed USB device using ehci_hcd and address 12 + usb 1-1.2: config 1 interface 0 altsetting 0 endpoint 0x82 is Bulk; ... + usb 1-1.2: config 1 interface 0 altsetting 0 endpoint 0x2 is Bulk; ... + usb 1-1.2: configuration #1 chosen from 1 choice + usb 1-1.2: New USB device found, idVendor=0425, idProduct=1001 + usb 1-1.2: New USB device strings: Mfr=1, Product=2, SerialNumber=2 + usb 1-1.2: Product: Turbo BDM Light ColdFire v0.4 + usb 1-1.2: Manufacturer: Freescale + usb 1-1.2: SerialNumber: Turbo BDM Light ColdFire v0.4 + +You can see the pod has connected with address 12. Run the 'tblcf-show' command +to list the names of the pods as seen by libusb. If you disconnect the pod or +power cycle the pod or system the address of the pod can change. For example a +disconnect then reconnect moves the address onto the next number on my +system. This make it difficult to create scripts that take care of this. + +The solution is to use udev. This is a user land system present on current +Linux systems that responds to and manages hot plug kernel events. The +Wikipedia page on udev (http://en.wikipedia.org/wiki/Udev) provide a nice +overview of udev. + +Create a udev rule for the TBLCF pod to create a node in the 'dev' +directory. You can customise the node name used to suite your specific +needs. For me I have a single pod on my local Fedora Core 8 workstation and so +a basic setup is all that is needed: + + # cat /etc/udev/rules.d/91-tlbcf.rules + SUBSYSTEM=="usb" ATTR{manufacturer}=="Freescale" \ + ATTR{idVendor}=="0425" ATTR{idProduct}=="1001" SYMLINK+="tblcf%n" + + Note: there is a single line in the actual file. + +When I plug in my pod udev creates '/dev/tblcf3'. This is: + + # ls -las /dev/tblcf3 + 0 lrwxrwxrwx 1 root root 15 2008-03-06 14:59 /dev/tblcf3 -> bus/usb/001/012 + +The USB support for Linux in the BDM package checks if the device node is a +sym-link. If it is the link path is read and checked to see if the prefix is +'bus/usb'. If it is the device is assumed to be a USB device and the trailing +part of the path is the device name returned by libusb. The USB driver will +attempt to open the device. This may fail if the user does not have +permission. In this case the bdmd server on the local host is used. This is +similar to the I/O Permission support. + +With udev you can create device nodes with any name that suites. You can also +add more attribute checks to create a specific node. This allows for the +creation of nodes that match the function the pod is performing. In my example +above the number in the dev file is based on the USB port on the work station. + +The udev configuration required varys for different types of Linux. Please let +me know of a configuration for your version of Linux and I will add it to the +list. + +Windows +------- + +Plugging the pod into a Windows machine brings up the standard Hardware found +installer dialog box. I have only done this when an Administrator and I suspect +you will need to be an Administrator because driver files are installed into +the Windows directory. + +You need to have the LibUsb-Win32 package unpacked some where on your +machine. Typically you will have done this to build the BDM software and the +package links the libusb library. The BDM package has a axbdm.inf file and you +navigate the Hardware installer to say you have a disk then browse to select +the axbdm.inf file. The installer will then start to install the drivers and if +it cannot find the files it needs it will ask for them. This time navigate to +the location of the LibUsb-Win32 files and select the ones asked for by the +dialog box. + +I created the axbdm.inf file for the AxBDM pod from Axiom I have. The +LibUsb-Win32 package contains a program called inf-installer.exe. To use this +program with the pod connected to the computer, run the program then select the +pod and fill in the fields. + +Once finished you can run the testlibusb-win.exe and it will show the TBLCF pod +in the list of devices. + +Run the tblcf-show program to get a list of detected pods. The returned name is +not pretty but it seems to be unique to pod in a specific USB port. You need to +use this name when using the BDM software: + + > chk-bdm bus-0-\\.\libusb0-0002-0x0425-0x1001 + +It is not a nice name but this is what libusb returns. You can take this name +and place in a .m68kbdminit file to make more user friendly: + + dev bus-0-\\.\libusb0-0002-0x0425-0x1001 usb1 + +On Windows you may need to add a HOME environment variable. You can do this +using the Control Panel's System entry. Open the System entry, select the +Advanced tab, then the Environment Variables button and add to "User Variables" +a "HOME" entry thats points to your home directory. On Windows this is +typically your "My Documents" directory. Once set you can create a .m68kbdminit +file in that directory and the M68K BDM tools will read that file when opening +a BDM device. + +When using GDB you need to escape the '\' character. The above device name in +gdb and gdb scripts becomes: + + bus-0-\\\\.\\libusb0-0002-0x0425-0x1001 + +I/O PERM SUPPORT +================ + +The I/O Permission support is based around the 'ioperm' system call on Linux +and the "/dev/io" I/O port access on FreeBSD. The calls allows a root executed +program direct access to the I/O ports of a PC. Unix programs such as X windows +use this call to gain control of the video card I/O ports without the need for +a driver. The term "ioperm" refers to the ioperm call on Linux and the +"/dev/io" interface on FreeBSD. + +The support for the ioperm call has been added to the BDM package because it: + + 1. Allows a user to build a BDM application without installing kernel + sources. + + 2. The BDM driver is included in the user land application rather than + the kernel. A kernel upgrade or change does not require the building + of the BDM driver. + + 3. Binary programs can be created and distributed removing the need for + users to build a driver to use them. + + 4. Stops the kernel jitter seen when downloading. + +The library that BDM applications link to by default now contains the ioperm +call as well as the BDM driver code. If you link the default library to GDB it +will contain the ioperm call. Having an application such as GDB make an ioperm +call will fail unless GDB is executing as root. The ioperm call requires the +program making the call be executing as root and executing GDB as root is not +recommended and is actively discouraged. + +The remote protocol that is also built by default into the BDM library provides +an easy means to have GDB executing as a user and the BDM server executing as +root. The BDM server being root can make the ioperm call and gain direct +control of the parallel ports. + +To use the ioperm call make sure you install the BDM server. See Step 3 of the +INSTALLATION procedure above. + +The ioperm support performs the following when opening the BDM port: + + 1. Issue the ioperm call. If it passes the direct I/O accessing of the + parallel port is performed. + + 2. If the ioperm call fails, the kernel driver open is attempted. If + is succeeds the kernel driver is used. + + 3. If the driver call fails an attempt to connect to a local BDM + server is performed. Therefore if ioperm and driver opens fail the + following check command: + + $ ./chk /dev/bdmcf0 + + is transformed into the equivalent command line command of: + + $ ./chk localhost:/dev/bdmcf0 + + where we are attempting to open LPT1 for a Coldfire target. The + device entry at the end should be changed to suite your specific + parallel port and processor. + +A side effect of the current I/O perm implementation is the simulation of +device nodes under the '/dev' tree. This design is copied from the Windows +version of the BDM package. The Windows build is a kind of I/O perm driver +where the GiveIO driver provides the Windows application direct access to the +parallel port rather than the ioperm system call. The simulation of BDM device +nodes under the '/dev' directory is used to keep the documentation consisent, +and to allow GDB scripts or BDM programs a common way to operate on different +platforms. The simulation means you will not find device nodes under a '/dev' +tree. This can be confusing for experienced Unix users accustomed to finding +device nodes in the '/dev' directory. + +The I/O perm interface has about the same performance as the kernel +module. This is based on limited testing. The kernel module should be a little +faster for most block read/write operations. This is mostly due to the kernel +being blocked while the bit bashing occurs. If you perform a large number of +small BDM requests the performance will about the same for the ioperm direct +accesses and the kernel driver. + +The Library +=========== + +The library provides a higher level interface to the driver without requiring +you to make low level Linux driver calls. + +The library interface consists of two parts: + + 1) The driver interface, and + 2) The remote protocol. + +The driver interface make Unix driver calls via the open, close, read, write +and ioctl system calls. + +The library also contains the remote protocol that talks to the BDM +server. This protocol is not the GDB remote protocol. It operates at a much +lower level than the GDB remote protocol and is designed to support a server +operating from xinetd or inetd. It also allows flash programming tools built +with the BDM library to work remotely. + +The library does not contain the download support anymore. The need to contain +a specific BFD header file is broken. The GDB patch contains the code to +perform a download to target. + +Windows 9x,NT,2000 +================== + +The library will build the driver in one pass. There is no driver needed for +Windows 9x. This should allow GDB to be built. The Cygwin or MinGW packages are +needed to build the library. + +I have tested the package on Windows 98, Windows 2000 and Windows XP using +MinGW. This is cross-compiled from Linux and also compiled under MinGW on +Windows XP. + +Cygwin should build and work, how-ever at the time of updating this file I +could get Cygwin installed and working to test. + +Setting the minor device number +=============================== + +The minor device number (the second number in the mknod command) specifies +the parallel port to which the BDM interface is connected and the type of +the target CPU. The least signficant two bits of the minor device +number specify the parallel port and the remaining bits specify the target +CPU type: + + 7 6 5 4 3 2 1 0 ++----+----+----+----+----+----+----+----+ +| | | | | | | | | ++----+----+----+----+----+----+----+----+ +\ / \ / + \ / \ / + \ / \ / + ------------+----------- -+- + | | + | | + | +-- These two bits select the parallel + | port to which the BDM interface is + | connected: 00 - LPT1 + | 01 - LPT2 + | 10 - LPT3 + | + +-- These six bits select the target CPU type: + 000000 - CPU32+ (PD adaptor) + 000001 - Coldfire + 000010 - CPU32+ (ICD adaptor) + +Examples +======== +1. Target processor is a Motorola MC68360 (CPU32+) connected to LPT1. + Minor device number is 0. + +2. Target processor is a Motorola MC68360 (CPU32+) connected to LPT2. + Minor device number is 1. + +3. Target processor is a Motorola MC5206(e) or MCF5307 (Coldfire) connected + to LPT1. Minor device number is 4. + +ACKNOWLEDGEMENTS +================ + +Thanks very much to Motorola for making the parallel port BDM +interface circuit freely available and to M. Schraut and G. Magin +for providing the Linux driver and gdb modifications that got this +all started. + +For the Coldfire additions I would like thank Eric for the clean +driver frame work, and David L Jenkins +(David.l.jenkins@btinternet.com) for the orginal post to the Coldfire +mailing list (ColdFire@WildRice.com) with the pin out and functions +for the P&E interface. It is what started me doing this and a really +great help. David Fiddes must be thanked for the testing and 5307 +reset bug. I would also like to thank Dave Morgan of Plessey Asia +Pacific for the use of some test equipment which helped. + +Thanks to David McCullough (davidm@stallion.oz.au) for the SCO +support. + +ICD fixes from Alexander Aganichev . + +ICD performace fixed from Keith Outwater . + +NT and GiveIO support to Rick Haubenstricker . + +Thanks to Sue Cozart and Joe Circello for answering question about +the Coldfire's BDM hardware. + +Additional thanks to Freescale for their continued support. + +Thanks to Axiom Manufacturing for their support in adding the TBLCF support. + +WHERE TO GET HELP +================= + +If you've got any questions about any of this, please contact the BDM project +mailing list on the SourceForge web site: + + http://sourceforge.net/projects/bdm/ + +We like to hear any success stories, as well as suggestions for improvements. diff --git a/m68k/README.bdmgdbserver b/m68k/README.bdmgdbserver new file mode 100644 index 0000000..8938c1c --- /dev/null +++ b/m68k/README.bdmgdbserver @@ -0,0 +1,282 @@ +M68K BDM GDB Server + Chris Johns + 3 Nov 2007 + + The 'gdbserver' directory contains a GDB Remote protocol server which provides + BDM support for GDB for a range of Coldfire and CPU32 processors. The server + called 'm68k-bdm-gdbserver' will have been installed when you installed the + M68K BDM package. Make sure the installed server executable's path is in your + environment's path variable. + + The BDM GDB server support Linux and Windows using GDB's socket or pipe + interfaces. The socket interface is the standard way GDB talks to a GDB remote + server. The pipe mode is also supported. With the pipe mode GDB spawns the BDM + GDB server and pipe the remote protocol to the new process. + + The BDM GDB Server support the BDM library's direct or remote protocol mode of + operation. If you use the BDM library remote protocol the actual hardware will + be 2 processes away from GDB. + + The GDB with the BDM GDB Server will break existing GDB scripts. All the + features that the patched version had have been carried over to the BDM GDB + Server with the added advantage of no patch to maintain plus a means to add + support for new Coldfire processors simply with out the need to upgrade GDB. + +GDB Patched verses GDB Remote + + The old patched GDB and the newer GDB using the remote protocol will break + existing BDM GDB scripts. All the features present in the patched GDB are + present how-ever the commands to access the features have changed. There was + no way to avoid this. + + The BDM GDB Server using a remote GDB has many advantages. The advantages are: + + - No need to patch GDB. + - BDM fixes and updates with out the need to update GDB. + - Simpler means of adding support for new Coldfire processors. + + The hardware break and watch points are supported. + + The registers shown by the standard 'info reg' command is now restricted to + registers that are in normal use with-in a program. For example the 5235 + processor shows: + + (gdb) info reg + d0 0xcf206080 -819961728 + d1 0x15001080 352325760 + d2 0x19 25 + d3 0x3f6afffc 1063976956 + d4 0xffffedce -4658 + d5 0xff77af57 -8933545 + d6 0x5e0658c7 1577474247 + d7 0xf9f3dcff -101458689 + a0 0x0 0x0 + a1 0xffe254d4 0xffe254d4 + a2 0x79a7dae5 0x79a7dae5 + a3 0xf75e4dbf 0xf75e4dbf + a4 0x637a 0x637a + a5 0xf3df7b7f 0xf3df7b7f + fp 0x627a 0x627a + sp 0x627a 0x627a + ps 0x2704 9988 + pc 0xffe254de 0xffe254de + macsr 0x0 0 + mask 0xffffff9b -101 + acc0 0xef3b7df8 -281313800 + acc1 0xe50bdd7a -452207238 + acc2 0x3b7df47b 998110331 + acc3 0xdbb7cff8 -608710664 + accext01 0x3b7df87c 998111356 + accext32 0xc1e2f47b -1042090885 + + The full list of available registers are: + + (gdb) info all-registers + d0 0xcf206080 -819961728 + d1 0x15001080 352325760 + d2 0x19 25 + d3 0x3f6afffc 1063976956 + d4 0xffffedce -4658 + d5 0xff77af57 -8933545 + d6 0x5e0658c7 1577474247 + d7 0xf9f3dcff -101458689 + a0 0x0 0x0 + a1 0xffe254d4 0xffe254d4 + a2 0x79a7dae5 0x79a7dae5 + a3 0xf75e4dbf 0xf75e4dbf + a4 0x637a 0x637a + a5 0xf3df7b7f 0xf3df7b7f + fp 0x627a 0x627a + sp 0x627a 0x627a + ps 0x2704 9988 + pc 0xffe254de 0xffe254de + vbr 0x3f8 1016 + cacr 0x0 0 + acr0 0x16ed4064 384647268 + acr1 0xf1bd2080 -239263616 + rambar 0x20000020 536870944 + othera7 0xedfafefb -302317829 + csr 0x1000000 16777216 + xcsr 0x8400000 138412032 + aatr 0x5 5 + tdr 0x40000000 1073741824 + pbr 0x0 0 + pbmr 0x0 0 + abhr 0x0 0 + ablr 0x0 0 + dbr 0x0 0 + dbmr 0x0 0 + macsr 0x0 0 + mask 0xffffff9b -101 + acc0 0xef3b7df8 -281313800 + acc1 0xe50bdd7a -452207238 + acc2 0x3b7df47b 998110331 + acc3 0xdbb7cff8 -608710664 + accext01 0x3b7df87c 998111356 + accext32 0xc1e2f47b -1042090885 + + The special BDM command are available. These are accessed using the GDB + 'monitor' command. To get a list of available commands connect to the target + then issue 'monitor bdm-help'. + + Note: At this point in time some commands are missing. They will be added. + +Building GDB + + The BDM GDB Server requires GDB 6.7 or later built for a m68k-elf or similar + target. The standard FSF sources are the only sources the BDM GDB Server is + tested with. You do not need to patch GDB but you will need to insure the + 'expat' XML library is installed and GDB's configure script detecteds it + correctly. Build and install GDB the normal way. For example: + + $ tar jxf gdb-6.7.1.tar.bz2 + $ mkdir localhost + $ cd localhost + $ ../gdb-6.7.1/configure + $ make all install + +Connecting with GDB + + Connect your pod to the PC and to your target hardware then power on the + hardware. This example session is with the Axman 5235 board and using the + remote target's pipe interface. + + Test you BDM hardware and software configuration by running one of the test + programs in the M68K BDM package. + + Start GDB and obtain the standard GDB prompt. + + $ m68k-elf-gdb + GNU gdb 6.7 + Copyright (C) 2007 Free Software Foundation, Inc. + License GPLv3+: GNU GPL version 3 or later + This is free software: you are free to change and redistribute it. + There is NO WARRANTY, to the extent permitted by law. Type "show copying" + and "show warranty" for details. + This GDB was configured as "--host=i686-pc-linux-gnu --target=m68k-elf". + (gdb) + + Connect to the target: + + (gdb) target remote | m68k-bdm-gdbserver pipe /dev/bdmcf0 + Remote debugging using | m68k-bdm-gdbserver pipe /dev/bdmcf0 + trying kernel driver: /dev/bdmcf0 + trying bdm server: localhost:/dev/bdmcf0 + m68k-bdm: detected MCF5235 + m68k-bdm: architecture CF5235 connected to /dev/bdmcf0 + m68k-bdm: Coldfire debug module version is 0 (5206(e)/5235/5272/5282) + Process /dev/bdmcf0 created; pid = 0 + Remote debugging using pipe + 0xffe254e2 in ?? () + (gdb) + + The 'target remote |' command tells GDB to use the remote protocol via the + pipe interface. GDB will then use the remainder of the command line to invoke + the BDM GDB Server. The command line used is the simplest one that can be + used. It is: + + m68k-bdm-gdbserver pipe /dev/bdmcf0 + + The 'm68k-bdm-gdbserver' is required to be in your environment's path. You can also + use a full path. The first parameter is the type of communications the GDB + server is to use. In this case if the 'pipe' interface. It could be a + socket and we will cover this later. + + The BDM GDB Server can accept other command line options. They are: + + m68k-bdm-gdbserver -vVhDd -t