Tue Oct 29 16:56:01 1996 Geoffrey Noer <noer@cygnus.com>
[deliverable/binutils-gdb.git] / gdb / remote-wiggler.c
1 /* Remote target communications for the Macraigor Systems BDM Wiggler
2 Copyright 1996 Free Software Foundation, Inc.
3
4 This file is part of GDB.
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
19
20 #include "defs.h"
21 #include "gdbcore.h"
22 #include "gdb_string.h"
23 #include <fcntl.h>
24 #include "frame.h"
25 #include "inferior.h"
26 #include "bfd.h"
27 #include "symfile.h"
28 #include "target.h"
29 #include "wait.h"
30 #include "gdbcmd.h"
31 #include "objfiles.h"
32 #include "gdb-stabs.h"
33
34 #include "dcache.h"
35
36 #ifdef USG
37 #include <sys/types.h>
38 #endif
39
40 #include <signal.h>
41 #include "serial.h"
42
43 /* Wiggler serial protocol definitions */
44
45 #define DLE 020 /* Quote char */
46 #define SYN 026 /* Start of packet */
47 #define RAW_SYN ((026 << 8) | 026) /* get_quoted_char found a naked SYN */
48
49 /* Status flags */
50
51 #define WIGGLER_FLAG_RESET 0x01 /* Target is being reset */
52 #define WIGGLER_FLAG_STOPPED 0x02 /* Target is halted */
53 #define WIGGLER_FLAG_BDM 0x04 /* Target is in BDM */
54 #define WIGGLER_FLAG_PWF 0x08 /* Power failed */
55 #define WIGGLER_FLAG_CABLE_DISC 0x10 /* BDM cable disconnected */
56
57 #define WIGGLER_AYT 0x0 /* Are you there? */
58 #define WIGGLER_GET_VERSION 0x1 /* Get Version */
59 #define WIGGLER_SET_BAUD_RATE 0x2 /* Set Baud Rate */
60 #define WIGGLER_INIT 0x10 /* Initialize Wiggler */
61 #define WIGGLER_SET_SPEED 0x11 /* Set Speed */
62 #define WIGGLER_GET_STATUS_MASK 0x12 /* Get Status Mask */
63 #define WIGGLER_GET_CTRS 0x13 /* Get Error Counters */
64 #define WIGGLER_SET_FUNC_CODE 0x14 /* Set Function Code */
65 #define WIGGLER_SET_CTL_FLAGS 0x15 /* Set Control Flags */
66 #define WIGGLER_SET_BUF_ADDR 0x16 /* Set Register Buffer Address */
67 #define WIGGLER_RUN 0x20 /* Run Target from PC */
68 #define WIGGLER_RUN_ADDR 0x21 /* Run Target from Specified Address */
69 #define WIGGLER_STOP 0x22 /* Stop Target */
70 #define WIGGLER_RESET_RUN 0x23 /* Reset Target and Run */
71 #define WIGGLER_RESET 0x24 /* Reset Target and Halt */
72 #define WIGGLER_STEP 0x25 /* Single step */
73 #define WIGGLER_READ_REGS 0x30 /* Read Registers */
74 #define WIGGLER_WRITE_REGS 0x31 /* Write Registers */
75 #define WIGGLER_READ_MEM 0x32 /* Read Memory */
76 #define WIGGLER_WRITE_MEM 0x33 /* Write Memory */
77 #define WIGGLER_FILL_MEM 0x34 /* Fill Memory */
78 #define WIGGLER_MOVE_MEM 0x35 /* Move Memory */
79
80 #define WIGGLER_READ_INT_MEM 0x80 /* Read Internal Memory */
81 #define WIGGLER_WRITE_INT_MEM 0x81 /* Write Internal Memory */
82 #define WIGGLER_JUMP 0x82 /* Jump to Subroutine */
83
84 #define WIGGLER_ERASE_FLASH 0x90 /* Erase flash memory */
85 #define WIGGLER_PROGRAM_FLASH 0x91 /* Write flash memory */
86 #define WIGGLER_EXIT_MON 0x93 /* Exit the flash programming monitor */
87 #define WIGGLER_ENTER_MON 0x94 /* Enter the flash programming monitor */
88
89 #define WIGGLER_SET_STATUS 0x0a /* Set status */
90 #define WIGGLER_FLAG_STOP 0x0 /* Stop the target, enter BDM */
91 #define WIGGLER_FLAG_START 0x01 /* Start the target at PC */
92 #define WIGGLER_FLAG_RETURN_STATUS 0x04 /* Return async status */
93
94 /* Stuff that should be in tm-xxx files. */
95 #if 1
96 #define BDM_NUM_REGS 24
97 #define BDM_REGMAP 0, 1, 2, 3, 4, 5, 6, 7, /* d0 -> d7 */ \
98 8, 9, 10, 11, 12, 13, 14, 15, /* a0 -> a7 */ \
99 18, 16, /* ps, pc */ \
100 -1, -1, -1, -1, -1, -1, -1, -1, /* fp0 -> fp7 */ \
101 -1, -1, -1, -1, -1 /* fpcontrol, fpstatus, fpiaddr, fpcode, fpflags */
102 #define BDM_BREAKPOINT 0x4a, 0xfa /* BGND insn */
103 #else
104 #define BDM_NUM_REGS 24
105 #define BDM_REGMAP 8, 9, 10, 11, 12, 13, 14, 15, /* d0 -> d7 */ \
106 16, 17, 18, 19, 20, 21, 22, 23, /* a0 -> a7 */ \
107 4, 0, /* ps, pc */ \
108 -1, -1, -1, -1, -1, -1, -1, -1, /* fp0 -> fp7 */ \
109 -1, -1, -1, -1, -1 /* fpcontrol, fpstatus, fpiaddr, fpcode, fpflags */
110 #define WIGGLER_POLL
111 #endif
112
113 /* Prototypes for local functions */
114
115 static void wiggler_stop PARAMS ((void));
116
117 static void put_packet PARAMS ((unsigned char *packet, int pktlen));
118 static unsigned char * get_packet PARAMS ((int cmd, int *pktlen, int timeout));
119
120 static int wiggler_write_bytes PARAMS ((CORE_ADDR memaddr,
121 char *myaddr, int len));
122
123 static int wiggler_read_bytes PARAMS ((CORE_ADDR memaddr,
124 char *myaddr, int len));
125
126 static void wiggler_files_info PARAMS ((struct target_ops *ignore));
127
128 static int wiggler_xfer_memory PARAMS ((CORE_ADDR memaddr, char *myaddr,
129 int len, int should_write,
130 struct target_ops *target));
131
132 static void wiggler_prepare_to_store PARAMS ((void));
133
134 static void wiggler_fetch_registers PARAMS ((int regno));
135
136 static void wiggler_resume PARAMS ((int pid, int step,
137 enum target_signal siggnal));
138
139 static int wiggler_start_remote PARAMS ((char *dummy));
140
141 static void wiggler_open PARAMS ((char *name, int from_tty));
142
143 static void wiggler_close PARAMS ((int quitting));
144
145 static void wiggler_store_registers PARAMS ((int regno));
146
147 static void wiggler_mourn PARAMS ((void));
148
149 static int readchar PARAMS ((int timeout));
150
151 static void reset_packet PARAMS ((void));
152
153 static void output_packet PARAMS ((void));
154
155 static int get_quoted_char PARAMS ((int timeout));
156
157 static void put_quoted_char PARAMS ((int c));
158
159 static int wiggler_wait PARAMS ((int pid, struct target_waitstatus *status));
160
161 static void wiggler_kill PARAMS ((void));
162
163 static void wiggler_detach PARAMS ((char *args, int from_tty));
164
165 static void wiggler_interrupt PARAMS ((int signo));
166
167 static void wiggler_interrupt_twice PARAMS ((int signo));
168
169 static void interrupt_query PARAMS ((void));
170
171 static unsigned char * do_command PARAMS ((int cmd, int *statusp, int *lenp));
172
173 static unsigned char * read_bdm_registers PARAMS ((int first_bdm_regno,
174 int last_bdm_regno,
175 int *numregs));
176
177 extern struct target_ops wiggler_ops; /* Forward decl */
178
179 static int last_run_status;
180
181 /* This was 5 seconds, which is a long time to sit and wait.
182 Unless this is going though some terminal server or multiplexer or
183 other form of hairy serial connection, I would think 2 seconds would
184 be plenty. */
185
186 /* Changed to allow option to set timeout value.
187 was static int remote_timeout = 2; */
188 extern int remote_timeout;
189
190 /* Descriptor for I/O to remote machine. Initialize it to NULL so that
191 wiggler_open knows that we don't have a file open when the program
192 starts. */
193 serial_t wiggler_desc = NULL;
194 \f
195 static void
196 wiggler_error (s, error_code)
197 char *s;
198 int error_code;
199 {
200 char buf[100];
201
202 fputs_filtered (s, gdb_stderr);
203 fputs_filtered (" ", gdb_stderr);
204
205 switch (error_code)
206 {
207 case 0x1: s = "Unknown fault"; break;
208 case 0x2: s = "Power failed"; break;
209 case 0x3: s = "Cable disconnected"; break;
210 case 0x4: s = "Couldn't enter BDM"; break;
211 case 0x5: s = "Target stuck in reset"; break;
212 case 0x6: s = "Port not configured"; break;
213 case 0x7: s = "Write verify failed"; break;
214 case 0x11: s = "Bus error"; break;
215 case 0x12: s = "Checksum error"; break;
216 case 0x13: s = "Illegal command"; break;
217 case 0x14: s = "Parameter error"; break;
218 case 0x15: s = "Internal error"; break;
219 case 0x16: s = "Register buffer error"; break;
220 case 0x80: s = "Flash erase error"; break;
221 default:
222 sprintf (buf, "Unknown error code %d", error_code);
223 s = buf;
224 }
225
226 error (s);
227 }
228
229 /* Return nonzero if the thread TH is still alive on the remote system. */
230
231 static int
232 wiggler_thread_alive (th)
233 int th;
234 {
235 return 1;
236 }
237 \f
238 /* Clean up connection to a remote debugger. */
239
240 /* ARGSUSED */
241 static void
242 wiggler_close (quitting)
243 int quitting;
244 {
245 if (wiggler_desc)
246 SERIAL_CLOSE (wiggler_desc);
247 wiggler_desc = NULL;
248 }
249
250 /* Stub for catch_errors. */
251
252 static int
253 wiggler_start_remote (dummy)
254 char *dummy;
255 {
256 unsigned char buf[10], *p;
257 int pktlen;
258 int status;
259 int error_code;
260 int speed;
261
262 immediate_quit = 1; /* Allow user to interrupt it */
263
264 SERIAL_SEND_BREAK (wiggler_desc); /* Wake up the wiggler */
265
266 do_command (WIGGLER_AYT, &status, &pktlen);
267
268 p = do_command (WIGGLER_GET_VERSION, &status, &pktlen);
269
270 printf_unfiltered ("[Wiggler version %x.%x, capability 0x%x]\n",
271 p[0], p[1], (p[2] << 16) | p[3]);
272
273 #if 1
274 speed = 80; /* Divide clock by 4000 */
275
276 buf[0] = WIGGLER_INIT;
277 buf[1] = speed >> 8;
278 buf[2] = speed & 0xff;
279 buf[3] = 0; /* CPU32 for now */
280 put_packet (buf, 4); /* Init Wiggler params */
281 p = get_packet (buf[0], &pktlen, remote_timeout);
282
283 if (pktlen < 2)
284 error ("Truncated response packet from Wiggler");
285
286 status = p[1];
287 error_code = p[2];
288
289 if (error_code != 0)
290 wiggler_error ("WIGGLER_INIT:", error_code);
291 #endif
292
293 #if 0
294 /* Reset the target */
295
296 do_command (WIGGLER_RESET_RUN, &status, &pktlen);
297 /* do_command (WIGGLER_RESET, &status, &pktlen);*/
298 #endif
299
300 /* If processor is still running, stop it. */
301
302 if (!(status & WIGGLER_FLAG_BDM))
303 wiggler_stop ();
304
305 #if 1
306 buf[0] = WIGGLER_SET_CTL_FLAGS;
307 buf[1] = 0;
308 buf[2] = 1; /* Asynchronously return status when target stops */
309 put_packet (buf, 3);
310
311 p = get_packet (buf[0], &pktlen, remote_timeout);
312
313 if (pktlen < 2)
314 error ("Truncated response packet from Wiggler");
315
316 status = p[1];
317 error_code = p[2];
318
319 if (error_code != 0)
320 wiggler_error ("WIGGLER_SET_CTL_FLAGS:", error_code);
321 #endif
322
323 immediate_quit = 0;
324
325 /* This is really the job of start_remote however, that makes an assumption
326 that the target is about to print out a status message of some sort. That
327 doesn't happen here (in fact, it may not be possible to get the monitor to
328 send the appropriate packet). */
329
330 flush_cached_frames ();
331 registers_changed ();
332 stop_pc = read_pc ();
333 set_current_frame (create_new_frame (read_fp (), stop_pc));
334 select_frame (get_current_frame (), 0);
335 print_stack_frame (selected_frame, -1, 1);
336
337 return 1;
338 }
339
340 /* Open a connection to a remote debugger.
341 NAME is the filename used for communication. */
342
343 static DCACHE *wiggler_dcache;
344
345 static void
346 wiggler_open (name, from_tty)
347 char *name;
348 int from_tty;
349 {
350 if (name == 0)
351 error ("To open a Wiggler connection, you need to specify what serial\n\
352 device the Wiggler is attached to (e.g. /dev/ttya).");
353
354 target_preopen (from_tty);
355
356 unpush_target (&wiggler_ops);
357
358 wiggler_dcache = dcache_init (wiggler_read_bytes, wiggler_write_bytes);
359
360 wiggler_desc = SERIAL_OPEN (name);
361 if (!wiggler_desc)
362 perror_with_name (name);
363
364 if (baud_rate != -1)
365 {
366 if (SERIAL_SETBAUDRATE (wiggler_desc, baud_rate))
367 {
368 SERIAL_CLOSE (wiggler_desc);
369 perror_with_name (name);
370 }
371 }
372
373 SERIAL_RAW (wiggler_desc);
374
375 /* If there is something sitting in the buffer we might take it as a
376 response to a command, which would be bad. */
377 SERIAL_FLUSH_INPUT (wiggler_desc);
378
379 if (from_tty)
380 {
381 puts_filtered ("Remote target wiggler connected to ");
382 puts_filtered (name);
383 puts_filtered ("\n");
384 }
385 push_target (&wiggler_ops); /* Switch to using remote target now */
386
387 /* Without this, some commands which require an active target (such as kill)
388 won't work. This variable serves (at least) double duty as both the pid
389 of the target process (if it has such), and as a flag indicating that a
390 target is active. These functions should be split out into seperate
391 variables, especially since GDB will someday have a notion of debugging
392 several processes. */
393
394 inferior_pid = 42000;
395 /* Start the remote connection; if error (0), discard this target.
396 In particular, if the user quits, be sure to discard it
397 (we'd be in an inconsistent state otherwise). */
398 if (!catch_errors (wiggler_start_remote, (char *)0,
399 "Couldn't establish connection to remote target\n", RETURN_MASK_ALL))
400 pop_target();
401 }
402
403 /* This takes a program previously attached to and detaches it. After
404 this is done, GDB can be used to debug some other program. We
405 better not have left any breakpoints in the target program or it'll
406 die when it hits one. */
407
408 static void
409 wiggler_detach (args, from_tty)
410 char *args;
411 int from_tty;
412 {
413 if (args)
414 error ("Argument given to \"detach\" when remotely debugging.");
415
416 pop_target ();
417 if (from_tty)
418 puts_filtered ("Ending remote debugging.\n");
419 }
420 \f
421 /* Tell the remote machine to resume. */
422
423 static void
424 wiggler_resume (pid, step, siggnal)
425 int pid, step;
426 enum target_signal siggnal;
427 {
428 int pktlen;
429
430 dcache_flush (wiggler_dcache);
431
432 if (step)
433 do_command (WIGGLER_STEP, &last_run_status, &pktlen);
434 else
435 do_command (WIGGLER_RUN, &last_run_status, &pktlen);
436 }
437 \f
438 static void
439 wiggler_stop ()
440 {
441 int status;
442 int pktlen;
443
444 do_command (WIGGLER_STOP, &status, &pktlen);
445
446 if (!(status & WIGGLER_FLAG_BDM))
447 error ("Can't stop target via BDM");
448 }
449
450 static volatile int wiggler_interrupt_flag;
451
452 /* Send ^C to target to halt it. Target will respond, and send us a
453 packet. */
454
455 static void
456 wiggler_interrupt (signo)
457 int signo;
458 {
459 /* If this doesn't work, try more severe steps. */
460 signal (signo, wiggler_interrupt_twice);
461
462 if (remote_debug)
463 printf_unfiltered ("wiggler_interrupt called\n");
464
465 {
466 char buf[1];
467
468 wiggler_stop ();
469 buf[0] = WIGGLER_AYT;
470 put_packet (buf, 1);
471 wiggler_interrupt_flag = 1;
472 }
473 }
474
475 static void (*ofunc)();
476
477 /* The user typed ^C twice. */
478 static void
479 wiggler_interrupt_twice (signo)
480 int signo;
481 {
482 signal (signo, ofunc);
483
484 interrupt_query ();
485
486 signal (signo, wiggler_interrupt);
487 }
488
489 /* Ask the user what to do when an interrupt is received. */
490
491 static void
492 interrupt_query ()
493 {
494 target_terminal_ours ();
495
496 if (query ("Interrupted while waiting for the program.\n\
497 Give up (and stop debugging it)? "))
498 {
499 target_mourn_inferior ();
500 return_to_top_level (RETURN_QUIT);
501 }
502
503 target_terminal_inferior ();
504 }
505
506 /* If nonzero, ignore the next kill. */
507 static int kill_kludge;
508
509 /* Wait until the remote machine stops, then return,
510 storing status in STATUS just as `wait' would.
511 Returns "pid" (though it's not clear what, if anything, that
512 means in the case of this target). */
513
514 static int
515 wiggler_wait (pid, target_status)
516 int pid;
517 struct target_waitstatus *target_status;
518 {
519 unsigned char *p;
520 int error_code, status;
521 int pktlen;
522
523 wiggler_interrupt_flag = 0;
524
525 target_status->kind = TARGET_WAITKIND_STOPPED;
526 target_status->value.sig = TARGET_SIGNAL_TRAP;
527
528 /* Target may already be stopped by the time we get here. */
529
530 if (!(last_run_status & WIGGLER_FLAG_BDM))
531 {
532 ofunc = (void (*)()) signal (SIGINT, wiggler_interrupt);
533
534 p = get_packet (WIGGLER_AYT, &pktlen, -1);
535
536 signal (SIGINT, ofunc);
537
538 if (pktlen < 2)
539 error ("Truncated response packet from Wiggler");
540
541 status = p[1];
542 error_code = p[2];
543
544 if (error_code != 0)
545 wiggler_error ("target_wait:", error_code);
546
547 if (status & WIGGLER_FLAG_PWF)
548 error ("Wiggler lost VCC at BDM interface.");
549 else if (status & WIGGLER_FLAG_CABLE_DISC)
550 error ("BDM cable appears to have been disconnected.");
551
552 if (!(status & WIGGLER_FLAG_BDM))
553 error ("Wiggler woke up, but wasn't stopped: 0x%x", status);
554
555 if (wiggler_interrupt_flag)
556 target_status->value.sig = TARGET_SIGNAL_INT;
557 }
558
559 /* This test figures out if we just executed a BGND insn, and if it's one of
560 our breakpoints. If so, then we back up PC. N.B. When a BGND insn is
561 executed, the PC points at the loc just after the insn (ie: it's always
562 two bytes *after* the BGND). So, it's not sufficient to just see if PC-2
563 is a BGND insn because we could have gotten there via a jump. We dis-
564 ambiguate this case by examining the ATEMP register (which is only
565 accessible from BDM). This will tell us if we entered BDM because we
566 executed a BGND insn. */
567
568 if (breakpoint_inserted_here_p (read_pc () - 2)) /* One of our breakpoints? */
569 { /* Yes, see if we actually executed it */
570 #if 0 /* Temporarily disabled until atemp reading is fixed. */
571 int atemp;
572 int numregs;
573
574 p = read_bdm_registers (23, 23, &numregs);
575 atemp = extract_unsigned_integer (p, 4);
576
577 if (atemp == 1) /* And, did we hit a breakpoint insn? */
578 #endif
579 write_pc (read_pc () - 2); /* Yes, then back up PC */
580 }
581
582 return inferior_pid;
583 }
584
585 /* Read the remote registers into the block REGS. */
586 /* Currently we just read all the registers, so we don't use regno. */
587 /* ARGSUSED */
588
589 static unsigned char *
590 read_bdm_registers (first_bdm_regno, last_bdm_regno, numregs)
591 int first_bdm_regno;
592 int last_bdm_regno;
593 int *numregs;
594 {
595 unsigned char buf[10];
596 int i;
597 unsigned char *p;
598 unsigned char *regs;
599 int error_code, status;
600 int pktlen;
601
602 buf[0] = WIGGLER_READ_REGS;
603 buf[1] = first_bdm_regno >> 8;
604 buf[2] = first_bdm_regno & 0xff;
605 buf[3] = last_bdm_regno >> 8;
606 buf[4] = last_bdm_regno & 0xff;
607
608 put_packet (buf, 5);
609 p = get_packet (WIGGLER_READ_REGS, &pktlen, remote_timeout);
610
611 if (pktlen < 5)
612 error ("Truncated response packet from Wiggler");
613
614 status = p[1];
615 error_code = p[2];
616
617 if (error_code != 0)
618 wiggler_error ("read_bdm_registers:", error_code);
619
620 i = p[3];
621 if (i == 0)
622 i = 256;
623
624 if (i > pktlen - 4
625 || ((i & 3) != 0))
626 error ("Register block size bad: %d", i);
627
628 *numregs = i / 4;
629
630 regs = p + 4;
631
632 return regs;
633 }
634
635 static void
636 dump_all_bdm_regs ()
637 {
638 unsigned char *regs;
639 int numregs;
640 int i;
641
642 regs = read_bdm_registers (0, BDM_NUM_REGS - 1, &numregs);
643
644 printf_unfiltered ("rpc = 0x%x ",
645 (int)extract_unsigned_integer (regs, 4));
646 regs += 4;
647 printf_unfiltered ("usp = 0x%x ",
648 (int)extract_unsigned_integer (regs, 4));
649 regs += 4;
650 printf_unfiltered ("ssp = 0x%x ",
651 (int)extract_unsigned_integer (regs, 4));
652 regs += 4;
653 printf_unfiltered ("vbr = 0x%x ",
654 (int)extract_unsigned_integer (regs, 4));
655 regs += 4;
656 printf_unfiltered ("sr = 0x%x ",
657 (int)extract_unsigned_integer (regs, 4));
658 regs += 4;
659 printf_unfiltered ("sfc = 0x%x ",
660 (int)extract_unsigned_integer (regs, 4));
661 regs += 4;
662 printf_unfiltered ("dfc = 0x%x ",
663 (int)extract_unsigned_integer (regs, 4));
664 regs += 4;
665 printf_unfiltered ("atemp = 0x%x ",
666 (int)extract_unsigned_integer (regs, 4));
667 regs += 4;
668 printf_unfiltered ("\n");
669
670 for (i = 0; i <= 7; i++)
671 printf_unfiltered ("d%i = 0x%x ", i,
672 (int)extract_unsigned_integer (regs + i * 4, 4));
673 regs += 8 * 4;
674 printf_unfiltered ("\n");
675
676 for (i = 0; i <= 7; i++)
677 printf_unfiltered ("a%i = 0x%x ", i,
678 (int)extract_unsigned_integer (regs + i * 4, 4));
679 printf_unfiltered ("\n");
680 }
681
682 static int bdm_regmap[] = {BDM_REGMAP};
683
684 /* Read the remote registers into the block REGS. */
685 /* Currently we just read all the registers, so we don't use regno. */
686 /* ARGSUSED */
687 static void
688 wiggler_fetch_registers (regno)
689 int regno;
690 {
691 int i;
692 unsigned char *regs;
693 int first_regno, last_regno;
694 int first_bdm_regno, last_bdm_regno;
695 int numregs;
696
697 if (regno == -1)
698 {
699 first_regno = 0;
700 last_regno = NUM_REGS - 1;
701
702 first_bdm_regno = 0;
703 last_bdm_regno = BDM_NUM_REGS - 1;
704 }
705 else
706 {
707 first_regno = regno;
708 last_regno = regno;
709
710 first_bdm_regno = bdm_regmap [regno];
711 last_bdm_regno = bdm_regmap [regno];
712 }
713
714 if (first_bdm_regno == -1)
715 {
716 supply_register (first_regno, NULL);
717 return; /* Unsupported register */
718 }
719
720 regs = read_bdm_registers (first_bdm_regno, last_bdm_regno, &numregs);
721
722 for (i = first_regno; i <= last_regno; i++)
723 {
724 int bdm_regno, regoffset;
725
726 bdm_regno = bdm_regmap [i];
727 if (bdm_regno != -1)
728 {
729 regoffset = bdm_regno - first_bdm_regno;
730
731 if (regoffset >= numregs)
732 continue;
733
734 supply_register (i, regs + 4 * regoffset);
735 }
736 else
737 supply_register (i, NULL); /* Unsupported register */
738 }
739 }
740
741 static void
742 wiggler_prepare_to_store ()
743 {
744 }
745
746 /* Store register REGNO, or all registers if REGNO == -1, from the contents
747 of REGISTERS. FIXME: ignores errors. */
748
749 static void
750 wiggler_store_registers (regno)
751 int regno;
752 {
753 unsigned char buf[10 + 256];
754 int i;
755 unsigned char *p;
756 int error_code, status;
757 int pktlen;
758 int first_regno, last_regno;
759 int first_bdm_regno, last_bdm_regno;
760
761 if (regno == -1)
762 {
763 first_regno = 0;
764 last_regno = NUM_REGS - 1;
765
766 first_bdm_regno = 0;
767 last_bdm_regno = BDM_NUM_REGS - 1;
768 }
769 else
770 {
771 first_regno = regno;
772 last_regno = regno;
773
774 first_bdm_regno = bdm_regmap [regno];
775 last_bdm_regno = bdm_regmap [regno];
776 }
777
778 if (first_bdm_regno == -1)
779 return; /* Unsupported register */
780
781 buf[0] = WIGGLER_WRITE_REGS;
782 buf[3] = 4;
783
784 for (i = first_regno; i <= last_regno; i++)
785 {
786 int bdm_regno;
787
788 bdm_regno = bdm_regmap [i];
789
790 buf[1] = bdm_regno >> 8;
791 buf[2] = bdm_regno & 0xff;
792
793 memcpy (&buf[4], &registers[REGISTER_BYTE (i)], 4);
794 put_packet (buf, 4 + 4);
795 p = get_packet (WIGGLER_WRITE_REGS, &pktlen, remote_timeout);
796
797 if (pktlen < 3)
798 error ("Truncated response packet from Wiggler");
799
800 status = p[1];
801 error_code = p[2];
802
803 if (error_code != 0)
804 wiggler_error ("wiggler_store_registers:", error_code);
805 }
806 }
807 \f
808 /* Write memory data directly to the remote machine.
809 This does not inform the data cache; the data cache uses this.
810 MEMADDR is the address in the remote memory space.
811 MYADDR is the address of the buffer in our space.
812 LEN is the number of bytes.
813
814 Returns number of bytes transferred, or 0 for error. */
815
816 static int
817 wiggler_write_bytes (memaddr, myaddr, len)
818 CORE_ADDR memaddr;
819 char *myaddr;
820 int len;
821 {
822 char buf[256 + 10];
823 unsigned char *p;
824 int origlen;
825
826 origlen = len;
827
828 buf[0] = WIGGLER_WRITE_MEM;
829 buf[5] = 1; /* Write as bytes */
830 buf[6] = 0; /* Don't verify */
831
832 while (len > 0)
833 {
834 int numbytes;
835 int pktlen;
836 int status, error_code;
837
838 numbytes = min (len, 256 - 8);
839
840 buf[1] = memaddr >> 24;
841 buf[2] = memaddr >> 16;
842 buf[3] = memaddr >> 8;
843 buf[4] = memaddr;
844
845 buf[7] = numbytes;
846
847 memcpy (&buf[8], myaddr, numbytes);
848 put_packet (buf, 8 + numbytes);
849 p = get_packet (WIGGLER_WRITE_MEM, &pktlen, remote_timeout);
850 if (pktlen < 3)
851 error ("Truncated response packet from Wiggler");
852
853 status = p[1];
854 error_code = p[2];
855
856 if (error_code == 0x11) /* Got a bus error? */
857 {
858 CORE_ADDR error_address;
859
860 error_address = p[3] << 24;
861 error_address |= p[4] << 16;
862 error_address |= p[5] << 8;
863 error_address |= p[6];
864 numbytes = error_address - memaddr;
865
866 len -= numbytes;
867
868 errno = EIO;
869
870 break;
871 }
872 else if (error_code != 0)
873 wiggler_error ("wiggler_write_bytes:", error_code);
874
875 len -= numbytes;
876 memaddr += numbytes;
877 myaddr += numbytes;
878 }
879
880 return origlen - len;
881 }
882
883 /* Read memory data directly from the remote machine.
884 This does not use the data cache; the data cache uses this.
885 MEMADDR is the address in the remote memory space.
886 MYADDR is the address of the buffer in our space.
887 LEN is the number of bytes.
888
889 Returns number of bytes transferred, or 0 for error. */
890
891 static int
892 wiggler_read_bytes (memaddr, myaddr, len)
893 CORE_ADDR memaddr;
894 char *myaddr;
895 int len;
896 {
897 char buf[256 + 10];
898 unsigned char *p;
899 int origlen;
900
901 origlen = len;
902
903 buf[0] = WIGGLER_READ_MEM;
904 buf[5] = 1; /* Read as bytes */
905
906 while (len > 0)
907 {
908 int numbytes;
909 int pktlen;
910 int status, error_code;
911
912 numbytes = min (len, 256 - 7);
913
914 buf[1] = memaddr >> 24;
915 buf[2] = memaddr >> 16;
916 buf[3] = memaddr >> 8;
917 buf[4] = memaddr;
918
919 buf[6] = numbytes;
920
921 put_packet (buf, 7);
922 p = get_packet (WIGGLER_READ_MEM, &pktlen, remote_timeout);
923 if (pktlen < 4)
924 error ("Truncated response packet from Wiggler");
925
926 status = p[1];
927 error_code = p[2];
928
929 if (error_code == 0x11) /* Got a bus error? */
930 {
931 CORE_ADDR error_address;
932
933 error_address = p[3] << 24;
934 error_address |= p[4] << 16;
935 error_address |= p[5] << 8;
936 error_address |= p[6];
937 numbytes = error_address - memaddr;
938
939 len -= numbytes;
940
941 errno = EIO;
942
943 break;
944 }
945 else if (error_code != 0)
946 wiggler_error ("wiggler_read_bytes:", error_code);
947
948 memcpy (myaddr, &p[4], numbytes);
949
950 len -= numbytes;
951 memaddr += numbytes;
952 myaddr += numbytes;
953 }
954
955 return origlen - len;
956 }
957 \f
958 /* Read or write LEN bytes from inferior memory at MEMADDR, transferring
959 to or from debugger address MYADDR. Write to inferior if SHOULD_WRITE is
960 nonzero. Returns length of data written or read; 0 for error. */
961
962 /* ARGSUSED */
963 static int
964 wiggler_xfer_memory (memaddr, myaddr, len, should_write, target)
965 CORE_ADDR memaddr;
966 char *myaddr;
967 int len;
968 int should_write;
969 struct target_ops *target; /* ignored */
970 {
971 return dcache_xfer_memory (wiggler_dcache, memaddr, myaddr, len, should_write);
972 }
973 \f
974 static void
975 wiggler_files_info (ignore)
976 struct target_ops *ignore;
977 {
978 puts_filtered ("Debugging a target over a serial line.\n");
979 }
980 \f
981 /* Stuff for dealing with the packets which are part of this protocol.
982 See comment at top of file for details. */
983
984 /* Read a single character from the remote side, handling wierd errors. */
985
986 static int
987 readchar (timeout)
988 int timeout;
989 {
990 int ch;
991
992 ch = SERIAL_READCHAR (wiggler_desc, timeout);
993
994 switch (ch)
995 {
996 case SERIAL_EOF:
997 error ("Remote connection closed");
998 case SERIAL_ERROR:
999 perror_with_name ("Remote communication error");
1000 case SERIAL_TIMEOUT:
1001 default:
1002 return ch;
1003 }
1004 }
1005
1006 #if 0
1007 /* Read a character from the data stream, dequoting as necessary. SYN is
1008 treated special. Any SYNs appearing in the data stream are returned as the
1009 distinct value RAW_SYN (which has a value > 8 bits and therefore cannot be
1010 mistaken for real data). */
1011
1012 static int
1013 get_quoted_char (timeout)
1014 int timeout;
1015 {
1016 int ch;
1017
1018 ch = readchar (timeout);
1019
1020 switch (ch)
1021 {
1022 case SERIAL_TIMEOUT:
1023 error ("Timeout in mid-packet, aborting");
1024 case SYN:
1025 return RAW_SYN;
1026 case DLE:
1027 ch = readchar (timeout);
1028 if (ch == SYN)
1029 return RAW_SYN;
1030 return ch & ~0100;
1031 default:
1032 return ch;
1033 }
1034 }
1035
1036 static unsigned char pkt[256 * 2 + 10], *pktp; /* Worst case */
1037
1038 static void
1039 reset_packet ()
1040 {
1041 pktp = pkt;
1042 }
1043
1044 static void
1045 output_packet ()
1046 {
1047 if (SERIAL_WRITE (wiggler_desc, pkt, pktp - pkt))
1048 perror_with_name ("output_packet: write failed");
1049
1050 reset_packet ();
1051 }
1052
1053 /* Output a quoted character. SYNs and DLEs are quoted. Everything else goes
1054 through untouched. */
1055
1056 static void
1057 put_quoted_char (c)
1058 int c;
1059 {
1060 switch (c)
1061 {
1062 case SYN:
1063 case DLE:
1064 *pktp++ = DLE;
1065 c |= 0100;
1066 }
1067
1068 *pktp++ = c;
1069 }
1070
1071 /* Send a packet to the Wiggler. The packet framed by a SYN character, a byte
1072 count and a checksum. The byte count only counts the number of bytes
1073 between the count and the checksum. A count of zero actually means 256.
1074 Any SYNs within the packet (including the checksum and count) must be
1075 quoted. The quote character must be quoted as well. Quoting is done by
1076 replacing the character with the two-character sequence DLE, {char} | 0100.
1077 Note that the quoting mechanism has no effect on the byte count.
1078 */
1079
1080 static void
1081 stu_put_packet (buf, len)
1082 unsigned char *buf;
1083 int len;
1084 {
1085 unsigned char checksum;
1086 unsigned char c;
1087
1088 if (len == 0 || len > 256)
1089 abort (); /* Can't represent 0 length packet */
1090
1091 reset_packet ();
1092
1093 checksum = 0;
1094
1095 put_quoted_char (RAW_SYN);
1096
1097 c = len;
1098
1099 do
1100 {
1101 checksum += c;
1102
1103 put_quoted_char (c);
1104
1105 c = *buf++;
1106 }
1107 while (len-- > 0);
1108
1109 put_quoted_char (-checksum & 0xff);
1110
1111 output_packet ();
1112 }
1113
1114 #else
1115
1116 /* Send a packet to the Wiggler. The packet framed by a SYN character, a byte
1117 count and a checksum. The byte count only counts the number of bytes
1118 between the count and the checksum. A count of zero actually means 256.
1119 Any SYNs within the packet (including the checksum and count) must be
1120 quoted. The quote character must be quoted as well. Quoting is done by
1121 replacing the character with the two-character sequence DLE, {char} | 0100.
1122 Note that the quoting mechanism has no effect on the byte count.
1123 */
1124
1125 static void
1126 put_packet (buf, len)
1127 unsigned char *buf;
1128 int len;
1129 {
1130 unsigned char checksum;
1131 unsigned char c;
1132 unsigned char *packet, *packet_ptr;
1133
1134 packet = alloca (len + 1 + 1); /* packet + SYN + checksum */
1135 packet_ptr = packet;
1136
1137 checksum = 0;
1138
1139 *packet_ptr++ = 0x55;
1140
1141 while (len-- > 0)
1142 {
1143 c = *buf++;
1144
1145 checksum += c;
1146 *packet_ptr++ = c;
1147 }
1148
1149 *packet_ptr++ = -checksum;
1150 if (SERIAL_WRITE (wiggler_desc, packet, packet_ptr - packet))
1151 perror_with_name ("output_packet: write failed");
1152 }
1153 #endif
1154
1155 #if 0
1156 /* Get a packet from the Wiggler. Timeout is only enforced for the first byte
1157 of the packet. Subsequent bytes are expected to arrive in time <=
1158 remote_timeout. Returns a pointer to a static buffer containing the payload
1159 of the packet. *LENP contains the length of the packet.
1160 */
1161
1162 static unsigned char *
1163 stu_get_packet (cmd, lenp, timeout)
1164 unsigned char cmd;
1165 int *lenp;
1166 {
1167 int ch;
1168 int len;
1169 static unsigned char buf[256 + 10], *p;
1170 unsigned char checksum;
1171
1172 find_packet:
1173
1174 ch = get_quoted_char (timeout);
1175
1176 if (ch < 0)
1177 error ("get_packet (readchar): %d", ch);
1178
1179 if (ch != RAW_SYN)
1180 goto find_packet;
1181
1182 found_syn: /* Found the start of a packet */
1183
1184 p = buf;
1185 checksum = 0;
1186
1187 len = get_quoted_char (remote_timeout);
1188
1189 if (len == RAW_SYN)
1190 goto found_syn;
1191
1192 checksum += len;
1193
1194 if (len == 0)
1195 len = 256;
1196
1197 len++; /* Include checksum */
1198
1199 while (len-- > 0)
1200 {
1201 ch = get_quoted_char (remote_timeout);
1202 if (ch == RAW_SYN)
1203 goto found_syn;
1204
1205 *p++ = ch;
1206 checksum += ch;
1207 }
1208
1209 if (checksum != 0)
1210 goto find_packet;
1211
1212 if (cmd != buf[0])
1213 error ("Response phase error. Got 0x%x, expected 0x%x", buf[0], cmd);
1214
1215 *lenp = p - buf - 1;
1216 return buf;
1217 }
1218
1219 #else
1220
1221 /* Get a packet from the Wiggler. Timeout is only enforced for the first byte
1222 of the packet. Subsequent bytes are expected to arrive in time <=
1223 remote_timeout. Returns a pointer to a static buffer containing the payload
1224 of the packet. *LENP contains the length of the packet.
1225 */
1226
1227 static unsigned char *
1228 get_packet (cmd, lenp, timeout)
1229 int cmd;
1230 int *lenp;
1231 {
1232 int ch;
1233 int len;
1234 int i;
1235 static unsigned char packet[512];
1236 unsigned char *packet_ptr;
1237 unsigned char checksum;
1238
1239 find_packet:
1240
1241 ch = readchar (timeout);
1242
1243 if (ch < 0)
1244 error ("get_packet (readchar): %d", ch);
1245
1246 if (ch != 0x55)
1247 goto find_packet;
1248
1249 /* Found the start of a packet */
1250
1251 packet_ptr = packet;
1252 checksum = 0;
1253
1254 /* Read command char. That sort of tells us how long the packet is. */
1255
1256 ch = readchar (timeout);
1257
1258 if (ch < 0)
1259 error ("get_packet (readchar): %d", ch);
1260
1261 *packet_ptr++ = ch;
1262 checksum += ch;
1263
1264 /* Get status. */
1265
1266 ch = readchar (timeout);
1267
1268 if (ch < 0)
1269 error ("get_packet (readchar): %d", ch);
1270 *packet_ptr++ = ch;
1271 checksum += ch;
1272
1273 /* Get error code. */
1274
1275 ch = readchar (timeout);
1276
1277 if (ch < 0)
1278 error ("get_packet (readchar): %d", ch);
1279 *packet_ptr++ = ch;
1280 checksum += ch;
1281
1282 switch (ch) /* Figure out length of packet */
1283 {
1284 case 0x7: /* Write verify error? */
1285 len = 8; /* write address, value read back */
1286 break;
1287 case 0x11: /* Bus error? */
1288 /* write address, read flag */
1289 case 0x15: /* Internal error */
1290 len = 5; /* error code, vector */
1291 break;
1292 default: /* Error w/no params */
1293 len = 0;
1294 case 0x0: /* Normal result */
1295 switch (packet[0])
1296 {
1297 case WIGGLER_AYT: /* Are You There? */
1298 case WIGGLER_SET_BAUD_RATE: /* Set Baud Rate */
1299 case WIGGLER_INIT: /* Initialize wiggler */
1300 case WIGGLER_SET_SPEED: /* Set Speed */
1301 case WIGGLER_SET_FUNC_CODE: /* Set Function Code */
1302 case WIGGLER_SET_CTL_FLAGS: /* Set Control Flags */
1303 case WIGGLER_SET_BUF_ADDR: /* Set Register Buffer Address */
1304 case WIGGLER_RUN: /* Run Target from PC */
1305 case WIGGLER_RUN_ADDR: /* Run Target from Specified Address */
1306 case WIGGLER_STOP: /* Stop Target */
1307 case WIGGLER_RESET_RUN: /* Reset Target and Run */
1308 case WIGGLER_RESET: /* Reset Target and Halt */
1309 case WIGGLER_STEP: /* Single Step */
1310 case WIGGLER_WRITE_REGS: /* Write Register */
1311 case WIGGLER_WRITE_MEM: /* Write Memory */
1312 case WIGGLER_FILL_MEM: /* Fill Memory */
1313 case WIGGLER_MOVE_MEM: /* Move Memory */
1314 case WIGGLER_WRITE_INT_MEM: /* Write Internal Memory */
1315 case WIGGLER_JUMP: /* Jump to Subroutine */
1316 case WIGGLER_ERASE_FLASH: /* Erase flash memory */
1317 case WIGGLER_PROGRAM_FLASH: /* Write flash memory */
1318 case WIGGLER_EXIT_MON: /* Exit the flash programming monitor */
1319 case WIGGLER_ENTER_MON: /* Enter the flash programming monitor */
1320 len = 0;
1321 break;
1322 case WIGGLER_GET_VERSION: /* Get Version */
1323 len = 4;
1324 break;
1325 case WIGGLER_GET_STATUS_MASK: /* Get Status Mask */
1326 len = 1;
1327 break;
1328 case WIGGLER_GET_CTRS: /* Get Error Counters */
1329 case WIGGLER_READ_REGS: /* Read Register */
1330 case WIGGLER_READ_MEM: /* Read Memory */
1331 case WIGGLER_READ_INT_MEM: /* Read Internal Memory */
1332 len = 257;
1333 break;
1334 default:
1335 fprintf_filtered (gdb_stderr, "Unknown packet type 0x%x\n", ch);
1336 goto find_packet;
1337 }
1338 }
1339
1340 if (len == 257) /* Byte stream? */
1341 { /* Yes, byte streams contain the length */
1342 ch = readchar (timeout);
1343
1344 if (ch < 0)
1345 error ("get_packet (readchar): %d", ch);
1346 *packet_ptr++ = ch;
1347 checksum += ch;
1348 len = ch;
1349 if (len == 0)
1350 len = 256;
1351 }
1352
1353 while (len-- >= 0) /* Do rest of packet and checksum */
1354 {
1355 ch = readchar (timeout);
1356
1357 if (ch < 0)
1358 error ("get_packet (readchar): %d", ch);
1359 *packet_ptr++ = ch;
1360 checksum += ch;
1361 }
1362
1363 if (checksum != 0)
1364 goto find_packet;
1365
1366 if (cmd != -1 && cmd != packet[0])
1367 error ("Response phase error. Got 0x%x, expected 0x%x", packet[0], cmd);
1368
1369 *lenp = packet_ptr - packet - 1; /* Subtract checksum byte */
1370 return packet;
1371 }
1372 #endif
1373
1374 /* Execute a simple (one-byte) command. Returns a pointer to the data
1375 following the error code. */
1376
1377 static unsigned char *
1378 do_command (cmd, statusp, lenp)
1379 int cmd;
1380 int *statusp;
1381 int *lenp;
1382 {
1383 unsigned char buf[100], *p;
1384 int status, error_code;
1385 char errbuf[100];
1386
1387 buf[0] = cmd;
1388 put_packet (buf, 1); /* Send command */
1389 p = get_packet (*buf, lenp, remote_timeout);
1390
1391 if (*lenp < 3)
1392 error ("Truncated response packet from Wiggler");
1393
1394 status = p[1];
1395 error_code = p[2];
1396
1397 if (error_code != 0)
1398 {
1399 sprintf (errbuf, "do_command (0x%x):", cmd);
1400 wiggler_error (errbuf, error_code);
1401 }
1402
1403 if (status & WIGGLER_FLAG_PWF)
1404 error ("Wiggler can't detect VCC at BDM interface.");
1405 else if (status & WIGGLER_FLAG_CABLE_DISC)
1406 error ("BDM cable appears to be disconnected.");
1407
1408 *statusp = status;
1409
1410 return p + 3;
1411 }
1412 \f
1413 static void
1414 wiggler_kill ()
1415 {
1416 /* For some mysterious reason, wait_for_inferior calls kill instead of
1417 mourn after it gets TARGET_WAITKIND_SIGNALLED. Work around it. */
1418 if (kill_kludge)
1419 {
1420 kill_kludge = 0;
1421 target_mourn_inferior ();
1422 return;
1423 }
1424
1425 /* Don't wait for it to die. I'm not really sure it matters whether
1426 we do or not. */
1427 target_mourn_inferior ();
1428 }
1429
1430 static void
1431 wiggler_mourn ()
1432 {
1433 unpush_target (&wiggler_ops);
1434 generic_mourn_inferior ();
1435 }
1436
1437 /* All we actually do is set the PC to the start address of exec_bfd, and start
1438 the program at that point. */
1439
1440 static void
1441 wiggler_create_inferior (exec_file, args, env)
1442 char *exec_file;
1443 char *args;
1444 char **env;
1445 {
1446 if (args && (*args != '\000'))
1447 error ("Args are not supported by BDM.");
1448
1449 clear_proceed_status ();
1450 proceed (bfd_get_start_address (exec_bfd), TARGET_SIGNAL_0, 0);
1451 }
1452
1453 static void
1454 wiggler_load (args, from_tty)
1455 char *args;
1456 int from_tty;
1457 {
1458 generic_load (args, from_tty);
1459
1460 inferior_pid = 0;
1461
1462 /* This is necessary because many things were based on the PC at the time that
1463 we attached to the monitor, which is no longer valid now that we have loaded
1464 new code (and just changed the PC). Another way to do this might be to call
1465 normal_stop, except that the stack may not be valid, and things would get
1466 horribly confused... */
1467
1468 clear_symtab_users ();
1469 }
1470
1471 /* BDM (at least on CPU32) uses a different breakpoint */
1472
1473 static int
1474 wiggler_insert_breakpoint (addr, contents_cache)
1475 CORE_ADDR addr;
1476 char *contents_cache;
1477 {
1478 static char break_insn[] = {BDM_BREAKPOINT};
1479 int val;
1480
1481 val = target_read_memory (addr, contents_cache, sizeof break_insn);
1482
1483 if (val == 0)
1484 val = target_write_memory (addr, break_insn, sizeof break_insn);
1485
1486 return val;
1487 }
1488
1489 static void
1490 bdm_command (args, from_tty)
1491 char *args;
1492 int from_tty;
1493 {
1494 error ("bdm command must be followed by `reset'");
1495 }
1496
1497 static void
1498 bdm_reset_command (args, from_tty)
1499 char *args;
1500 int from_tty;
1501 {
1502 int status, pktlen;
1503
1504 if (!wiggler_desc)
1505 error ("Not connected to wiggler.");
1506
1507 do_command (WIGGLER_RESET, &status, &pktlen);
1508 dcache_flush (wiggler_dcache);
1509 registers_changed ();
1510 }
1511
1512 static void
1513 bdm_restart_command (args, from_tty)
1514 char *args;
1515 int from_tty;
1516 {
1517 int status, pktlen;
1518
1519 if (!wiggler_desc)
1520 error ("Not connected to wiggler.");
1521
1522 do_command (WIGGLER_RESET_RUN, &status, &pktlen);
1523 last_run_status = status;
1524 clear_proceed_status ();
1525 wait_for_inferior ();
1526 normal_stop ();
1527 }
1528
1529 static int
1530 flash_xfer_memory (memaddr, myaddr, len, should_write, target)
1531 CORE_ADDR memaddr;
1532 char *myaddr;
1533 int len;
1534 int should_write;
1535 struct target_ops *target; /* ignored */
1536 {
1537 char buf[256 + 10];
1538 unsigned char *p;
1539 int origlen;
1540
1541 if (!should_write)
1542 abort ();
1543
1544 origlen = len;
1545
1546 buf[0] = WIGGLER_PROGRAM_FLASH;
1547
1548 while (len > 0)
1549 {
1550 int numbytes;
1551 int pktlen;
1552 int status, error_code;
1553
1554 numbytes = min (len, 256 - 6);
1555
1556 buf[1] = memaddr >> 24;
1557 buf[2] = memaddr >> 16;
1558 buf[3] = memaddr >> 8;
1559 buf[4] = memaddr;
1560
1561 buf[5] = numbytes;
1562
1563 memcpy (&buf[6], myaddr, numbytes);
1564 put_packet (buf, 6 + numbytes);
1565 p = get_packet (WIGGLER_PROGRAM_FLASH, &pktlen, remote_timeout);
1566 if (pktlen < 3)
1567 error ("Truncated response packet from Wiggler");
1568
1569 status = p[1];
1570 error_code = p[2];
1571
1572 if (error_code != 0)
1573 wiggler_error ("flash_xfer_memory:", error_code);
1574
1575 len -= numbytes;
1576 memaddr += numbytes;
1577 myaddr += numbytes;
1578 }
1579
1580 return origlen - len;
1581 }
1582
1583 static void
1584 bdm_update_flash_command (args, from_tty)
1585 char *args;
1586 int from_tty;
1587 {
1588 int status, pktlen;
1589 struct cleanup *old_chain;
1590
1591 if (!wiggler_desc)
1592 error ("Not connected to wiggler.");
1593
1594 if (!args)
1595 error ("Must specify file containing new Wiggler code.");
1596
1597 /* old_chain = make_cleanup (flash_cleanup, 0);*/
1598
1599 do_command (WIGGLER_ENTER_MON, &status, &pktlen);
1600
1601 do_command (WIGGLER_ERASE_FLASH, &status, &pktlen);
1602
1603 wiggler_ops.to_xfer_memory = flash_xfer_memory;
1604
1605 generic_load (args, from_tty);
1606
1607 wiggler_ops.to_xfer_memory = wiggler_xfer_memory;
1608
1609 do_command (WIGGLER_EXIT_MON, &status, &pktlen);
1610
1611 /* discard_cleanups (old_chain);*/
1612 }
1613 \f
1614 /* Define the target subroutine names */
1615
1616 struct target_ops wiggler_ops = {
1617 "wiggler", /* to_shortname */
1618 "", /* to_longname */
1619 "", /* to_doc */
1620 wiggler_open, /* to_open */
1621 wiggler_close, /* to_close */
1622 NULL, /* to_attach */
1623 wiggler_detach, /* to_detach */
1624 wiggler_resume, /* to_resume */
1625 wiggler_wait, /* to_wait */
1626 wiggler_fetch_registers, /* to_fetch_registers */
1627 wiggler_store_registers, /* to_store_registers */
1628 wiggler_prepare_to_store, /* to_prepare_to_store */
1629 wiggler_xfer_memory, /* to_xfer_memory */
1630 wiggler_files_info, /* to_files_info */
1631 wiggler_insert_breakpoint, /* to_insert_breakpoint */
1632 memory_remove_breakpoint, /* to_remove_breakpoint */
1633 NULL, /* to_terminal_init */
1634 NULL, /* to_terminal_inferior */
1635 NULL, /* to_terminal_ours_for_output */
1636 NULL, /* to_terminal_ours */
1637 NULL, /* to_terminal_info */
1638 wiggler_kill, /* to_kill */
1639 wiggler_load, /* to_load */
1640 NULL, /* to_lookup_symbol */
1641 wiggler_create_inferior, /* to_create_inferior */
1642 wiggler_mourn, /* to_mourn_inferior */
1643 0, /* to_can_run */
1644 0, /* to_notice_signals */
1645 wiggler_thread_alive, /* to_thread_alive */
1646 0, /* to_stop */
1647 process_stratum, /* to_stratum */
1648 NULL, /* to_next */
1649 1, /* to_has_all_memory */
1650 1, /* to_has_memory */
1651 1, /* to_has_stack */
1652 1, /* to_has_registers */
1653 1, /* to_has_execution */
1654 NULL, /* sections */
1655 NULL, /* sections_end */
1656 OPS_MAGIC /* to_magic */
1657 };
1658
1659 void
1660 _initialize_remote_wiggler ()
1661 {
1662 extern struct cmd_list_element *cmdlist;
1663 static struct cmd_list_element *bdm_cmd_list = NULL;
1664
1665 add_target (&wiggler_ops);
1666
1667 add_show_from_set (add_set_cmd ("remotetimeout", no_class,
1668 var_integer, (char *)&remote_timeout,
1669 "Set timeout value for remote read.\n", &setlist),
1670 &showlist);
1671
1672 add_prefix_cmd ("bdm", class_obscure, bdm_command, "", &bdm_cmd_list, "bdm ",
1673 0, &cmdlist);
1674
1675 add_cmd ("reset", class_obscure, bdm_reset_command, "", &bdm_cmd_list);
1676 add_cmd ("restart", class_obscure, bdm_restart_command, "", &bdm_cmd_list);
1677 add_cmd ("update-flash", class_obscure, bdm_update_flash_command, "", &bdm_cmd_list);
1678 }
This page took 0.074024 seconds and 4 git commands to generate.