Commit | Line | Data |
---|---|---|
249abc98 KH |
1 | /* Remote target communications for serial-line targets in custom GDB protocol |
2 | Copyright 1988, 1991, 1992, 1993, 1994 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ | |
19 | ||
20 | #include "defs.h" | |
21 | #include <string.h> | |
22 | #include <fcntl.h> | |
23 | #include "frame.h" | |
24 | #include "inferior.h" | |
25 | #include "bfd.h" | |
26 | #include "symfile.h" | |
27 | #include "target.h" | |
28 | #include "wait.h" | |
29 | #include "terminal.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 | /* Prototypes for local functions */ | |
44 | ||
45 | static int | |
46 | arc_write_bytes PARAMS ((CORE_ADDR memaddr, unsigned char *myaddr, int len)); | |
47 | ||
48 | static int | |
49 | arc_read_bytes PARAMS ((CORE_ADDR memaddr, unsigned char *myaddr, int len)); | |
50 | ||
51 | static void | |
52 | arc_files_info PARAMS ((struct target_ops *ignore)); | |
53 | ||
54 | static int | |
55 | arc_xfer_memory PARAMS ((CORE_ADDR memaddr, char *myaddr, int len, | |
56 | int should_write, struct target_ops *target)); | |
57 | ||
58 | static void | |
59 | arc_xfer_cntlreg PARAMS ((int rw, unsigned char *data)); | |
60 | ||
61 | static void | |
62 | arc_prepare_to_store PARAMS ((void)); | |
63 | ||
64 | static void | |
65 | arc_fetch_registers PARAMS ((int regno)); | |
66 | ||
67 | static void | |
68 | arc_resume PARAMS ((int pid, int step, enum target_signal siggnal)); | |
69 | ||
70 | static int | |
71 | arc_start_remote PARAMS ((char *dummy)); | |
72 | ||
73 | static void | |
74 | arc_open PARAMS ((char *name, int from_tty)); | |
75 | ||
76 | static void | |
77 | arc_close PARAMS ((int quitting)); | |
78 | ||
79 | static void | |
80 | arc_store_registers PARAMS ((int regno)); | |
81 | ||
82 | static void | |
83 | getpkt PARAMS ((char *buf, int len)); | |
84 | ||
85 | static int | |
86 | putpkt PARAMS ((char *buf, int len)); | |
87 | ||
88 | static int arc_wait PARAMS ((int pid, struct target_waitstatus *status)); | |
89 | ||
90 | static void | |
91 | arc_detach PARAMS ((char *args, int from_tty)); | |
92 | ||
93 | static void | |
94 | arc_interrupt PARAMS ((int signo)); | |
95 | ||
96 | static void | |
97 | arc_interrupt_twice PARAMS ((int signo)); | |
98 | ||
99 | static void | |
100 | interrupt_query PARAMS ((void)); | |
101 | ||
102 | extern struct target_ops arc_ops; /* Forward decl */ | |
103 | ||
104 | static int aux_reg_map[3][30] = AUX_REG_MAP; | |
105 | ||
106 | /* This was 5 seconds, which is a long time to sit and wait. | |
107 | Unless this is going though some terminal server or multiplexer or | |
108 | other form of hairy serial connection, I would think 2 seconds would | |
109 | be plenty. */ | |
110 | static int remote_timeout = 2; | |
111 | ||
112 | #if 0 | |
113 | int icache; | |
114 | #endif | |
115 | ||
116 | /* Descriptor for I/O to remote machine. Initialize it to NULL so that | |
117 | arc_open knows that we don't have a file open when the program | |
118 | starts. */ | |
119 | static serial_t arc_desc = NULL; | |
120 | ||
121 | #define AUDIO_PROCESSOR 0 | |
122 | #define GRAPHIC_PROCESSOR 1 | |
123 | #define HOST_PROCESSOR 2 | |
124 | static unsigned char cntl_reg_halt_bit[3] = { 0x08, 0x10, 0x20 }; | |
125 | static unsigned char cntl_reg_step_bit[3] = { 0x01, 0x02, 0x04 }; | |
126 | ||
127 | static int curr_processor = HOST_PROCESSOR; | |
128 | static unsigned char cntl_reg = 0; | |
129 | static unsigned int status_reg = 0; | |
130 | ||
131 | #define PBUFSIZ 32 | |
132 | #define MAXBUFBYTES 32 | |
133 | ||
134 | \f | |
135 | /* Clean up connection to a remote debugger. */ | |
136 | ||
137 | /* ARGSUSED */ | |
138 | static void | |
139 | arc_close (quitting) | |
140 | int quitting; | |
141 | { | |
142 | if (arc_desc) | |
143 | SERIAL_CLOSE (arc_desc); | |
144 | arc_desc = NULL; | |
145 | } | |
146 | ||
147 | static int | |
148 | arc_start_remote (dummy) | |
149 | char *dummy; | |
150 | { | |
151 | immediate_quit = 1; /* Allow user to interrupt it */ | |
152 | arc_xfer_cntlreg (1, &cntl_reg); | |
153 | immediate_quit = 0; | |
154 | ||
155 | start_remote (); /* Initialize gdb process mechanisms */ | |
156 | return 1; | |
157 | } | |
158 | ||
159 | /* Open a connection to a remote debugger. | |
160 | NAME is the filename used for communication. */ | |
161 | ||
162 | static DCACHE *remote_dcache; | |
163 | ||
164 | static void | |
165 | arc_open (name, from_tty) | |
166 | char *name; | |
167 | int from_tty; | |
168 | { | |
169 | if (name == 0) | |
170 | error ( | |
171 | "To open a arc debug connection, you need to specify what parallel\n\ | |
172 | device is attached to the remote system."); | |
173 | ||
174 | target_preopen (from_tty); | |
175 | ||
176 | unpush_target (&arc_ops); | |
177 | ||
178 | remote_dcache = dcache_init (arc_read_bytes, arc_write_bytes); | |
179 | ||
180 | arc_desc = SERIAL_OPEN (name); | |
181 | if (!arc_desc) | |
182 | perror_with_name (name); | |
183 | ||
184 | /* If there is something sitting in the buffer we might take it as a | |
185 | response to a command, which would be bad. */ | |
186 | SERIAL_FLUSH_INPUT (arc_desc); | |
187 | ||
188 | if (from_tty) | |
189 | { | |
190 | puts_filtered ("Remote debugging using "); | |
191 | puts_filtered (name); | |
192 | puts_filtered ("\n"); | |
193 | } | |
194 | push_target (&arc_ops); /* Switch to using remote target now */ | |
195 | ||
196 | /* Without this, some commands which require an active target (such as kill) | |
197 | won't work. This variable serves (at least) double duty as both the pid | |
198 | of the target process (if it has such), and as a flag indicating that a | |
199 | target is active. These functions should be split out into seperate | |
200 | variables, especially since GDB will someday have a notion of debugging | |
201 | several processes. */ | |
202 | ||
203 | inferior_pid = 42000; | |
204 | ||
205 | /* Start the remote connection; if error (0), discard this target. | |
206 | In particular, if the user quits, be sure to discard it | |
207 | (we'd be in an inconsistent state otherwise). */ | |
208 | if (!catch_errors (arc_start_remote, (char *)0, | |
209 | "Couldn't establish connection to remote target\n", RETURN_MASK_ALL)) | |
210 | pop_target(); | |
211 | } | |
212 | ||
213 | /* arc_detach() | |
214 | takes a program previously attached to and detaches it. | |
215 | We better not have left any breakpoints | |
216 | in the program or it'll die when it hits one. | |
217 | Close the open connection to the remote debugger. | |
218 | Use this when you want to detach and do something else | |
219 | with your gdb. */ | |
220 | ||
221 | static void | |
222 | arc_detach (args, from_tty) | |
223 | char *args; | |
224 | int from_tty; | |
225 | { | |
226 | if (args) | |
227 | error ("Argument given to \"detach\" when remotely debugging."); | |
228 | ||
229 | pop_target (); | |
230 | if (from_tty) | |
231 | puts_filtered ("Ending remote debugging.\n"); | |
232 | } | |
233 | ||
234 | /* arc_set_addrreg | |
235 | set addr reg from debug system. */ | |
236 | ||
237 | static void | |
238 | arc_set_addrreg (addr) | |
239 | unsigned int addr; | |
240 | { | |
241 | unsigned char buf[6] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0}; | |
242 | ||
243 | buf[0] = 0x0; | |
244 | buf[4] = addr & 0xff; | |
245 | buf[3] = (addr >> 8) & 0xff; | |
246 | buf[2] = (addr >> 16) & 0xff; | |
247 | buf[1] = (addr >> 24) & 0xff; | |
248 | ||
249 | putpkt (buf, 5); | |
250 | } | |
251 | ||
252 | /* arc_xfer_datareg | |
253 | read or write data reg from debug system. */ | |
254 | ||
255 | static void | |
256 | arc_xfer_datareg (rw, aux, incr, data) | |
257 | int rw; | |
258 | int aux; | |
259 | int incr; | |
260 | unsigned int *data; | |
261 | { | |
262 | unsigned char buf1[6] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0}; | |
263 | unsigned char buf2[5]; | |
264 | unsigned int tmp; | |
265 | ||
266 | /* read or write data */ | |
267 | buf1[0] = (aux ? 0x81 : 0x41); | |
268 | if (incr) | |
269 | buf1[0] += 0x20; | |
270 | if (rw) /* read */ | |
271 | { | |
272 | buf1[0] += 0x10; | |
273 | putpkt (buf1, 1); | |
274 | getpkt (buf2, 4); | |
275 | *data = *(int *)buf2; | |
276 | } | |
277 | else | |
278 | { | |
279 | tmp = *data; | |
280 | buf1[4] = tmp & 0xff; | |
281 | buf1[3] = (tmp >> 8) & 0xff; | |
282 | buf1[2] = (tmp >> 16) & 0xff; | |
283 | buf1[1] = (tmp >> 24) & 0xff; | |
284 | putpkt (buf1, 5); | |
285 | } | |
286 | } | |
287 | ||
288 | /* arc_xfer_cntlreg | |
289 | read or write control reg from debug system. */ | |
290 | ||
291 | static void | |
292 | arc_xfer_cntlreg (rw, data) | |
293 | int rw; | |
294 | unsigned char *data; | |
295 | { | |
296 | unsigned char buf[3] = {0x0, 0x0, 0x0}; | |
297 | ||
298 | if (rw) | |
299 | { | |
300 | buf[0] = 0x12; | |
301 | putpkt (buf, 1); | |
302 | getpkt (data, 1); | |
303 | } | |
304 | else | |
305 | { | |
306 | buf[0] = 0x02; | |
307 | buf[1] = *data; | |
308 | putpkt (buf, 2); | |
309 | } | |
310 | } | |
311 | ||
312 | /* arc_xfer_reg | |
313 | read or write a reg to arc processors. */ | |
314 | ||
315 | static void | |
316 | arc_xfer_reg (processor, rw, aux, regnum, data) | |
317 | int processor; | |
318 | int rw; | |
319 | int aux; | |
320 | int regnum; | |
321 | unsigned int *data; | |
322 | { | |
323 | unsigned int tmp; | |
324 | ||
325 | if (processor == HOST_PROCESSOR) | |
326 | { | |
327 | /* write addr (regnum) */ | |
328 | arc_set_addrreg (regnum); | |
329 | arc_xfer_datareg (rw, aux, 0, data); | |
330 | } | |
331 | else | |
332 | { | |
333 | /* write addr register (aux r14) */ | |
334 | arc_set_addrreg (0xe); | |
335 | tmp = aux ? (regnum | 0x80000000) : regnum; | |
336 | arc_xfer_datareg (0, 1, 0, tmp); | |
337 | ||
338 | /* read/write from data reg (aux reg 15/16) */ | |
339 | arc_set_addrreg (processor == AUDIO_PROCESSOR ? 0x10 : 0xf); | |
340 | arc_xfer_datareg (rw, 1, 0, data); | |
341 | } | |
342 | } | |
343 | ||
344 | \f | |
345 | /* Tell the remote machine to resume. */ | |
346 | ||
347 | static enum target_signal last_sent_signal = TARGET_SIGNAL_0; | |
348 | int last_sent_step; | |
349 | ||
350 | static void | |
351 | arc_resume (pid, step, siggnal) | |
352 | int pid, step; | |
353 | enum target_signal siggnal; | |
354 | { | |
355 | unsigned int tmp; | |
356 | ||
357 | dcache_flush (remote_dcache); | |
358 | ||
359 | last_sent_signal = siggnal; | |
360 | last_sent_step = step; | |
361 | ||
362 | /* don't know how to handle signal in ARC *** | |
363 | if (siggnal != TARGET_SIGNAL_0) | |
364 | { | |
365 | buf[0] = step ? 'S' : 'C'; | |
366 | buf[1] = tohex (((int)siggnal >> 4) & 0xf); | |
367 | buf[2] = tohex ((int)siggnal & 0xf); | |
368 | buf[3] = '\0'; | |
369 | } | |
370 | */ | |
371 | ||
372 | if (step) | |
373 | { | |
374 | /* write the step bit in control reg of debug system */ | |
375 | unsigned char tmp_char = cntl_reg | cntl_reg_step_bit[curr_processor]; | |
376 | arc_xfer_cntlreg (0, &tmp_char); | |
377 | } | |
378 | else | |
379 | { | |
380 | /* clear the halt bit in the status register */ | |
381 | tmp = status_reg | 0x02000000; | |
382 | arc_xfer_reg (curr_processor, 0, 1, 0, &tmp); | |
383 | } | |
384 | } | |
385 | ||
386 | \f | |
387 | static void (*ofunc)(); | |
388 | ||
389 | /* Send to target to halt it. */ | |
390 | static void | |
391 | arc_interrupt (signo) | |
392 | int signo; | |
393 | { | |
394 | unsigned char buf[3] = {0x02, 0x0, 0x0}; | |
395 | /* If this doesn't work, try more severe steps. */ | |
396 | signal (signo, arc_interrupt_twice); | |
397 | ||
398 | if (remote_debug) | |
399 | printf_unfiltered ("arc_interrupt called\n"); | |
400 | ||
401 | if (cntl_reg & cntl_reg_halt_bit[curr_processor]) | |
402 | return; | |
403 | ||
404 | buf[1] = cntl_reg | cntl_reg_halt_bit[curr_processor]; | |
405 | putpkt (buf, 2); | |
406 | return; | |
407 | } | |
408 | ||
409 | /* The user typed ^C twice. */ | |
410 | static void | |
411 | arc_interrupt_twice (signo) | |
412 | int signo; | |
413 | { | |
414 | signal (signo, ofunc); | |
415 | ||
416 | interrupt_query (); | |
417 | ||
418 | signal (signo, arc_interrupt); | |
419 | } | |
420 | ||
421 | /* Ask the user what to do when an interrupt is received. */ | |
422 | ||
423 | static void | |
424 | interrupt_query () | |
425 | { | |
426 | target_terminal_ours (); | |
427 | ||
428 | if (query ("Interrupted while waiting for the program.\n\ | |
429 | Give up (and stop debugging it)? ")) | |
430 | { | |
431 | target_mourn_inferior (); | |
432 | return_to_top_level (RETURN_QUIT); | |
433 | } | |
434 | ||
435 | target_terminal_inferior (); | |
436 | } | |
437 | ||
438 | /* If nonzero, ignore the next kill. */ | |
439 | int kill_kludge; | |
440 | ||
441 | /* Wait until the remote machine stops, then return, | |
442 | storing status in STATUS just as `wait' would. | |
443 | Returns "pid" (though it's not clear what, if anything, that | |
444 | means in the case of this target). */ | |
445 | ||
446 | static int | |
447 | arc_wait (pid, status) | |
448 | int pid; | |
449 | struct target_waitstatus *status; | |
450 | { | |
451 | unsigned char buf[PBUFSIZ]; | |
452 | int thread_num = -1; | |
453 | ||
454 | status->kind = TARGET_WAITKIND_EXITED; | |
455 | status->value.integer = 0; | |
456 | ||
457 | while (1) | |
458 | { | |
459 | unsigned char *p; | |
460 | ||
461 | ofunc = (void (*)()) signal (SIGINT, arc_interrupt); | |
462 | arc_xfer_cntlreg (1, &cntl_reg); | |
463 | signal (SIGINT, ofunc); | |
464 | if (cntl_reg & cntl_reg_halt_bit[curr_processor]) | |
465 | break; | |
466 | status->kind = TARGET_WAITKIND_STOPPED; | |
467 | } | |
468 | arc_xfer_reg (curr_processor, 1, 1, 0, &status_reg); | |
469 | ||
470 | return inferior_pid; | |
471 | } | |
472 | ||
473 | /* Number of bytes of registers this implements. */ | |
474 | static int register_bytes_found; | |
475 | ||
476 | /* Read the remote registers into the block REGS. */ | |
477 | /* Currently we just read all the registers, so we don't use regno. */ | |
478 | ||
479 | static void | |
480 | arc_fetch_registers (regno) | |
481 | int regno; | |
482 | { | |
483 | int i; | |
484 | char regs[REGISTER_BYTES]; | |
485 | ||
486 | /* Unimplemented registers read as all bits zero. */ | |
487 | memset (regs, 0, REGISTER_BYTES); | |
488 | ||
489 | /* get core register */ | |
490 | arc_set_addrreg (0); | |
491 | for (i = 0; i < AUX_BEG_REGNUM; i++) | |
492 | { | |
493 | if (curr_processor == HOST_PROCESSOR) | |
494 | arc_xfer_datareg (1, 0, 1, ®s[REGISTER_BYTE(i)]); | |
495 | else | |
496 | arc_xfer_reg (curr_processor, 1, 0, regno, ®s[REGISTER_BYTE(i)]); | |
497 | } | |
498 | ||
499 | /* get aux register */ | |
500 | for (i = AUX_BEG_REGNUM; i < AUX_END_REGNUM; i++) | |
501 | { | |
502 | int auxregnum = aux_reg_map[curr_processor][i-AUX_BEG_REGNUM+1]; | |
503 | if (auxregnum == -1) | |
504 | continue; | |
505 | arc_xfer_reg (curr_processor, 1, 1, auxregnum, ®s[REGISTER_BYTE(i)]); | |
506 | } | |
507 | /* copy from status register to pc */ | |
508 | for (i = 1; i <= 3; i++) | |
509 | registers[REGISTER_BYTE (PC_REGNUM)+i] = | |
510 | registers[REGISTER_BYTE (STA_REGNUM)+i]; | |
511 | ||
512 | /* | |
513 | if (i != register_bytes_found) | |
514 | { | |
515 | register_bytes_found = i; | |
516 | if (!REGISTER_BYTES_OK (i)) | |
517 | warning ("Remote reply is too short: %s", buf); | |
518 | } | |
519 | */ | |
520 | ||
521 | for (i = 0; i < NUM_REGS; i++) | |
522 | supply_register (i, ®s[REGISTER_BYTE(i)]); | |
523 | } | |
524 | ||
525 | /* Prepare to store registers. Since we may send them all, | |
526 | we have to read out the ones we don't want to change first. */ | |
527 | ||
528 | static void | |
529 | arc_prepare_to_store () | |
530 | { | |
531 | /* Make sure the entire registers array is valid. */ | |
532 | read_register_bytes (0, (char *)NULL, REGISTER_BYTES); | |
533 | } | |
534 | ||
535 | /* Store register REGNO, or all registers if REGNO == -1, from the contents | |
536 | of REGISTERS. FIXME: ignores errors. */ | |
537 | ||
538 | static void | |
539 | arc_store_registers (regno) | |
540 | int regno; | |
541 | { | |
542 | int i; | |
543 | char *regp; | |
544 | ||
545 | /* Try storing a single register. */ | |
546 | if (regno >= 0) | |
547 | { | |
548 | int isaux = (regno >= AUX_BEG_REGNUM ? 1 : 0); | |
549 | ||
550 | regp = ®isters[REGISTER_BYTE (regno)]; | |
551 | arc_xfer_reg (curr_processor, 0, isaux, regno, regp); | |
552 | } | |
553 | ||
554 | /* store core regs */ | |
555 | arc_set_addrreg (0); | |
556 | for (i = 0; i < AUX_BEG_REGNUM; i++) | |
557 | { | |
558 | regp = ®isters[REGISTER_BYTE (i)]; | |
559 | if (curr_processor == HOST_PROCESSOR) | |
560 | arc_xfer_datareg (0, 0, 1, regp); | |
561 | else | |
562 | arc_xfer_reg (curr_processor, 0, 0, regno, regp); | |
563 | } | |
564 | ||
565 | /* store aux regs */ | |
566 | /* copy pc back to status register */ | |
567 | for (i = 1; i <= 3; i++) | |
568 | registers[REGISTER_BYTE (STA_REGNUM)+i] = | |
569 | registers[REGISTER_BYTE (PC_REGNUM)+i]; | |
570 | for (i = AUX_BEG_REGNUM; i <= AUX_END_REGNUM; i++) | |
571 | { | |
572 | int auxregnum = aux_reg_map[curr_processor][i-AUX_BEG_REGNUM+1]; | |
573 | if (auxregnum == -1) | |
574 | continue; | |
575 | regp = ®isters[REGISTER_BYTE (i)]; | |
576 | arc_xfer_reg (curr_processor, 0, 1, auxregnum, regp); | |
577 | } | |
578 | ||
579 | } | |
580 | ||
581 | #if 0 | |
582 | /* Use of the data cache is disabled because it loses for looking at | |
583 | and changing hardware I/O ports and the like. Accepting `voltile' | |
584 | would perhaps be one way to fix it, but a better way which would | |
585 | win for more cases would be to use the executable file for the text | |
586 | segment, like the `icache' code below but done cleanly (in some | |
587 | target-independent place, perhaps in target_xfer_memory, perhaps | |
588 | based on assigning each target a speed or perhaps by some simpler | |
589 | mechanism). */ | |
590 | ||
591 | /* Read a word from remote address ADDR and return it. | |
592 | This goes through the data cache. */ | |
593 | ||
594 | static int | |
595 | arc_fetch_word (addr) | |
596 | CORE_ADDR addr; | |
597 | { | |
598 | #if 0 | |
599 | if (icache) | |
600 | { | |
601 | extern CORE_ADDR text_start, text_end; | |
602 | ||
603 | if (addr >= text_start && addr < text_end) | |
604 | { | |
605 | int buffer; | |
606 | xfer_core_file (addr, &buffer, sizeof (int)); | |
607 | return buffer; | |
608 | } | |
609 | } | |
610 | #endif | |
611 | return dcache_fetch (remote_dcache, addr); | |
612 | } | |
613 | ||
614 | /* Write a word WORD into remote address ADDR. | |
615 | This goes through the data cache. */ | |
616 | ||
617 | static void | |
618 | arc_store_word (addr, word) | |
619 | CORE_ADDR addr; | |
620 | int word; | |
621 | { | |
622 | dcache_poke (remote_dcache, addr, word); | |
623 | } | |
624 | #endif /* 0 */ | |
625 | ||
626 | \f | |
627 | /* Write memory data directly to the remote machine. | |
628 | This does not inform the data cache; the data cache uses this. | |
629 | MEMADDR is the address in the remote memory space. | |
630 | MYADDR is the address of the buffer in our space. | |
631 | LEN is the number of bytes. | |
632 | ||
633 | Returns number of bytes transferred, or 0 for error. */ | |
634 | ||
635 | static int | |
636 | arc_write_bytes (memaddr, myaddr, len) | |
637 | CORE_ADDR memaddr; | |
638 | unsigned char *myaddr; | |
639 | int len; | |
640 | { | |
641 | char buf1[6] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0}; | |
642 | char buf2[6] = {0x21, 0x0, 0x0, 0x0, 0x0, 0x0}; | |
643 | int i; | |
644 | char *p; | |
645 | ||
646 | /* We send target system values byte by byte, in increasing byte addresses*/ | |
647 | ||
648 | buf1[4] = memaddr & 0xff; | |
649 | buf1[3] = (memaddr >> 8) & 0xff; | |
650 | buf1[2] = (memaddr >> 16) & 0xff; | |
651 | buf1[1] = (memaddr >> 24) & 0xff; | |
652 | putpkt (buf1, 5); | |
653 | ||
654 | for (i = 0; i < len; ) | |
655 | { | |
656 | buf2[1] = myaddr[i++]; | |
657 | buf2[2] = myaddr[i++]; | |
658 | buf2[3] = myaddr[i++]; | |
659 | buf2[4] = myaddr[i++]; | |
660 | putpkt (buf2, 5); | |
661 | } | |
662 | ||
663 | return len; | |
664 | } | |
665 | ||
666 | /* Read memory data directly from the remote machine. | |
667 | This does not use the data cache; the data cache uses this. | |
668 | MEMADDR is the address in the remote memory space. | |
669 | MYADDR is the address of the buffer in our space. | |
670 | LEN is the number of bytes. | |
671 | ||
672 | Returns number of bytes transferred, or 0 for error. */ | |
673 | ||
674 | static int | |
675 | arc_read_bytes (memaddr, myaddr, len) | |
676 | CORE_ADDR memaddr; | |
677 | unsigned char *myaddr; | |
678 | int len; | |
679 | { | |
680 | unsigned char buf1[6] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0}; | |
681 | unsigned char buf2[3] = {0x31, 0x0, 0x0}; | |
682 | unsigned char buf3[5]; | |
683 | int i; | |
684 | char *p; | |
685 | ||
686 | /* We send target system values byte by byte, in increasing byte addresses*/ | |
687 | ||
688 | buf1[4] = memaddr & 0xff; | |
689 | buf1[3] = (memaddr >> 8) & 0xff; | |
690 | buf1[2] = (memaddr >> 16) & 0xff; | |
691 | buf1[1] = (memaddr >> 24) & 0xff; | |
692 | putpkt (buf1, 5); | |
693 | ||
694 | for (i = 0; i < len; ) | |
695 | { | |
696 | putpkt (buf2, 2); | |
697 | getpkt (buf3, 4); | |
698 | myaddr[i++] = buf3[1]; | |
699 | myaddr[i++] = buf3[2]; | |
700 | myaddr[i++] = buf3[3]; | |
701 | myaddr[i++] = buf3[4]; | |
702 | } | |
703 | ||
704 | return i; | |
705 | } | |
706 | ||
707 | \f | |
708 | /* Read or write LEN bytes from inferior memory at MEMADDR, transferring | |
709 | to or from debugger address MYADDR. Write to inferior if SHOULD_WRITE is | |
710 | nonzero. Returns length of data written or read; 0 for error. */ | |
711 | ||
712 | /* ARGSUSED */ | |
713 | static int | |
714 | arc_xfer_memory(memaddr, myaddr, len, should_write, target) | |
715 | CORE_ADDR memaddr; | |
716 | char *myaddr; | |
717 | int len; | |
718 | int should_write; | |
719 | struct target_ops *target; /* ignored */ | |
720 | { | |
721 | int xfersize; | |
722 | int bytes_xferred; | |
723 | int total_xferred = 0; | |
724 | ||
725 | while (len > 0) | |
726 | { | |
727 | if (len > MAXBUFBYTES) | |
728 | xfersize = MAXBUFBYTES; | |
729 | else | |
730 | xfersize = len; | |
731 | ||
732 | if (should_write) | |
733 | bytes_xferred = arc_write_bytes (memaddr, | |
734 | (unsigned char *)myaddr, xfersize); | |
735 | else | |
736 | bytes_xferred = arc_read_bytes (memaddr, | |
737 | (unsigned char *)myaddr, xfersize); | |
738 | ||
739 | /* If we get an error, we are done xferring. */ | |
740 | if (bytes_xferred == 0) | |
741 | break; | |
742 | ||
743 | memaddr += bytes_xferred; | |
744 | myaddr += bytes_xferred; | |
745 | len -= bytes_xferred; | |
746 | total_xferred += bytes_xferred; | |
747 | } | |
748 | return total_xferred; | |
749 | } | |
750 | ||
751 | \f | |
752 | static void | |
753 | arc_files_info (ignore) | |
754 | struct target_ops *ignore; | |
755 | { | |
756 | puts_filtered ("Debugging a target over a serial line.\n"); | |
757 | } | |
758 | \f | |
759 | ||
760 | /* Read a single character from the remote end, masking it down to 7 bits. */ | |
761 | static int | |
762 | readchar () | |
763 | { | |
764 | int ch; | |
765 | ||
766 | ch = SERIAL_READCHAR (arc_desc, 0); | |
767 | ||
768 | switch (ch) | |
769 | { | |
770 | case SERIAL_EOF: | |
771 | error ("Remote connection closed"); | |
772 | case SERIAL_ERROR: | |
773 | perror_with_name ("Remote communication error"); | |
774 | case SERIAL_TIMEOUT: | |
775 | return ch; | |
776 | default: | |
777 | return ch & 0x7f; | |
778 | } | |
779 | } | |
780 | ||
781 | /* Send a packet to the remote machine, with error checking. | |
782 | The data of the packet is in BUF. */ | |
783 | ||
784 | static int | |
785 | putpkt (buf, len) | |
786 | char *buf; | |
787 | int len; | |
788 | { | |
789 | int i = 0; | |
790 | unsigned char csum = 0; | |
791 | ||
792 | while (i < len) | |
793 | { | |
794 | if (remote_debug) | |
795 | { | |
796 | printf_unfiltered ("Sending packet: %s...", buf); | |
797 | gdb_flush(gdb_stdout); | |
798 | } | |
799 | if (SERIAL_WRITE (arc_desc, buf, i)) | |
800 | perror_with_name ("putpkt: write failed"); | |
801 | i++; | |
802 | ||
803 | #if 0 | |
804 | /* This is wrong. If doing a long backtrace, the user should be | |
805 | able to get out next time we call QUIT, without anything as violent | |
806 | as interrupt_query. If we want to provide a way out of here | |
807 | without getting to the next QUIT, it should be based on hitting | |
808 | ^C twice as in arc_wait. */ | |
809 | if (quit_flag) | |
810 | { | |
811 | quit_flag = 0; | |
812 | interrupt_query (); | |
813 | } | |
814 | #endif | |
815 | } | |
816 | } | |
817 | ||
818 | /* Read a packet from the remote machine, with error checking, | |
819 | and store it in BUF. BUF is expected to be of size PBUFSIZ. | |
820 | If FOREVER, wait forever rather than timing out; this is used | |
821 | while the target is executing user code. */ | |
822 | ||
823 | static void | |
824 | getpkt (buf, len) | |
825 | char *buf; | |
826 | int len; | |
827 | { | |
828 | int c; | |
829 | int i; | |
830 | ||
831 | for (i = 0; i < len; i++) | |
832 | { | |
833 | c = readchar (); | |
834 | if (c == SERIAL_ERROR) | |
835 | { | |
836 | if (remote_debug) | |
837 | puts_filtered ("Read error.\n"); | |
838 | } | |
839 | } | |
840 | buf[i] = '\0'; | |
841 | ||
842 | if (remote_debug) | |
843 | fprintf_unfiltered (gdb_stderr, "Packet received: %s\n", buf); | |
844 | if (i != len) | |
845 | printf_unfiltered ("Ignoring packet error, continuing...\n"); | |
846 | } | |
847 | \f | |
848 | static void | |
849 | arc_kill () | |
850 | { | |
851 | /* For some mysterious reason, wait_for_inferior calls kill instead of | |
852 | mourn after it gets TARGET_WAITKIND_SIGNALLED. Work around it. */ | |
853 | if (kill_kludge) | |
854 | { | |
855 | kill_kludge = 0; | |
856 | target_mourn_inferior (); | |
857 | return; | |
858 | } | |
859 | target_mourn_inferior (); | |
860 | } | |
861 | ||
862 | static void | |
863 | arc_mourn () | |
864 | { | |
865 | unpush_target (&arc_ops); | |
866 | generic_mourn_inferior (); | |
867 | } | |
868 | ||
869 | \f | |
870 | #ifdef REMOTE_BREAKPOINT | |
871 | ||
872 | /* On some machines, e.g. 68k, we may use a different breakpoint instruction | |
873 | than other targets. */ | |
874 | static unsigned char break_insn[] = REMOTE_BREAKPOINT; | |
875 | ||
876 | /* Check that it fits in BREAKPOINT_MAX bytes. */ | |
877 | static unsigned char check_break_insn_size[BREAKPOINT_MAX] = REMOTE_BREAKPOINT; | |
878 | ||
879 | #else /* No REMOTE_BREAKPOINT. */ | |
880 | ||
881 | static unsigned char break_insn[] = BREAKPOINT; | |
882 | ||
883 | #endif /* No REMOTE_BREAKPOINT. */ | |
884 | ||
885 | /* Insert a breakpoint on targets that don't have any better breakpoint | |
886 | support. We read the contents of the target location and stash it, | |
887 | then overwrite it with a breakpoint instruction. ADDR is the target | |
888 | location in the target machine. CONTENTS_CACHE is a pointer to | |
889 | memory allocated for saving the target contents. It is guaranteed | |
890 | by the caller to be long enough to save sizeof BREAKPOINT bytes (this | |
891 | is accomplished via BREAKPOINT_MAX). */ | |
892 | ||
893 | static int | |
894 | arc_insert_breakpoint (addr, contents_cache) | |
895 | CORE_ADDR addr; | |
896 | char *contents_cache; | |
897 | { | |
898 | int val; | |
899 | ||
900 | val = target_read_memory (addr, contents_cache, sizeof break_insn); | |
901 | if (val == 0) | |
902 | val = target_write_memory (addr, (char *)break_insn, sizeof break_insn); | |
903 | return val; | |
904 | } | |
905 | ||
906 | static int | |
907 | arc_remove_breakpoint (addr, contents_cache) | |
908 | CORE_ADDR addr; | |
909 | char *contents_cache; | |
910 | { | |
911 | return target_write_memory (addr, contents_cache, sizeof break_insn); | |
912 | } | |
913 | ||
914 | /* switch_command | |
915 | support 'switch' command to switch among the three processors of ARC. */ | |
916 | ||
917 | static void | |
918 | switch_command (args, fromtty) | |
919 | char *args; | |
920 | int fromtty; | |
921 | { | |
922 | unsigned char cmd; | |
923 | int proc; | |
924 | struct target_waitstatus status; | |
925 | ||
926 | if (strncmp (args, "audio", 3) == 0) | |
927 | proc = 0; | |
928 | else if (strncmp (args, "graphic", 3) == 0) | |
929 | proc = 1; | |
930 | else if (strncmp (args, "host", 4) == 0) | |
931 | proc = 2; | |
932 | ||
933 | if (cntl_reg & cntl_reg_halt_bit[proc]) | |
934 | { | |
935 | curr_processor = proc; | |
936 | return; | |
937 | } | |
938 | ||
939 | if ((proc != HOST_PROCESSOR) && | |
940 | !(cntl_reg & cntl_reg_halt_bit[HOST_PROCESSOR])) | |
941 | { | |
942 | cmd = cntl_reg | cntl_reg_halt_bit[HOST_PROCESSOR]; | |
943 | arc_xfer_cntlreg (0, &cmd); | |
944 | curr_processor = HOST_PROCESSOR; | |
945 | arc_wait (inferior_pid, &status); | |
946 | } | |
947 | if (!(cntl_reg & cntl_reg_halt_bit[proc])) | |
948 | { | |
949 | cmd = cntl_reg | cntl_reg_halt_bit[proc]; | |
950 | arc_xfer_cntlreg (0, &cmd); | |
951 | curr_processor = proc; | |
952 | arc_wait (inferior_pid, &status); | |
953 | arc_fetch_registers (-1); | |
954 | } | |
955 | } | |
956 | ||
957 | \f | |
958 | /* Define the target subroutine names */ | |
959 | ||
960 | struct target_ops arc_ops = { | |
961 | "arc", /* to_shortname */ | |
962 | "Remote target in arc-specific protocol", /* to_longname */ | |
963 | "Use a remote computer via a parallel line, using a arc-specific protocol.\n\ | |
964 | Specify the device it is connected to.", /* to_doc */ | |
965 | arc_open, /* to_open */ | |
966 | arc_close, /* to_close */ | |
967 | NULL, /* to_attach */ | |
968 | arc_detach, /* to_detach */ | |
969 | arc_resume, /* to_resume */ | |
970 | arc_wait, /* to_wait */ | |
971 | arc_fetch_registers, /* to_fetch_registers */ | |
972 | arc_store_registers, /* to_store_registers */ | |
973 | arc_prepare_to_store, /* to_prepare_to_store */ | |
974 | arc_xfer_memory, /* to_xfer_memory */ | |
975 | arc_files_info, /* to_files_info */ | |
976 | ||
977 | arc_insert_breakpoint, /* to_insert_breakpoint */ | |
978 | arc_remove_breakpoint, /* to_remove_breakpoint */ | |
979 | ||
980 | NULL, /* to_terminal_init */ | |
981 | NULL, /* to_terminal_inferior */ | |
982 | NULL, /* to_terminal_ours_for_output */ | |
983 | NULL, /* to_terminal_ours */ | |
984 | NULL, /* to_terminal_info */ | |
985 | arc_kill, /* to_kill */ | |
986 | generic_load, /* to_load */ | |
987 | NULL, /* to_lookup_symbol */ | |
988 | NULL, /* to_create_inferior */ | |
989 | arc_mourn, /* to_mourn_inferior */ | |
990 | 0, /* to_can_run */ | |
991 | 0, /* to_notice_signals */ | |
992 | 0, /* to_stop */ | |
993 | process_stratum, /* to_stratum */ | |
994 | NULL, /* to_next */ | |
995 | 1, /* to_has_all_memory */ | |
996 | 1, /* to_has_memory */ | |
997 | 1, /* to_has_stack */ | |
998 | 1, /* to_has_registers */ | |
999 | 1, /* to_has_execution */ | |
1000 | NULL, /* sections */ | |
1001 | NULL, /* sections_end */ | |
1002 | OPS_MAGIC /* to_magic */ | |
1003 | }; | |
1004 | ||
1005 | void | |
1006 | _initialize_remote_arc () | |
1007 | { | |
1008 | add_target (&arc_ops); | |
1009 | add_com ("switch <processor>", class_obscure, switch_command, | |
1010 | "Switch to debug a different processor, can be one of 'host', \ | |
1011 | 'graphic' and 'audio'."); | |
1012 | } |