* Makefile.in, remote-udi.c, remote-vx.c, 29k-share/dfe/mini2udi.c,
[deliverable/binutils-gdb.git] / gdb / remote-udi.c
1 /*
2 - Remote debugging interface for Am290*0 running MiniMON monitor, for GDB.
3 This is like remote.c but expects MiniMON to be running on the Am29000
4 target hardware.
5 - Originally written by Daniel Mann at AMD for gdb 3.91.6.
6 - David Wood (wood@lab.ultra.nyu.edu) at New York University adapted this
7 file to gdb 3.95. I was unable to get this working on sun3os4
8 with termio, only with sgtty. Because we are only attempting to
9 use this module to debug our kernel, which is already loaded when
10 gdb is started up, I did not code up the file downloading facilities.
11 As a result this module has only the stubs to download files.
12 You should get tagged at compile time if you need to make any
13 changes/additions.
14 *- Daniel Mann at AMD took the 3.95 adaptions above and replaced
15 MiniMON interface with UDI-p interface.
16
17 Copyright (C) 1990 Free Software Foundation, Inc.
18
19 This file is part of GDB.
20
21 This program is free software; you can redistribute it and/or modify
22 it under the terms of the GNU General Public License as published by
23 the Free Software Foundation; either version 1, or (at your option)
24 any later version.
25
26 This program is distributed in the hope that it will be useful,
27 but WITHOUT ANY WARRANTY; without even the implied warranty of
28 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
29 GNU General Public License for more details.
30
31 You should have received a copy of the GNU General Public License
32 along with this program; see the file COPYING. If not, write to
33 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
34
35
36 #include <stdio.h>
37 #include "defs.h"
38 #include "inferior.h"
39 #include "wait.h"
40 #include "value.h"
41 #include <ctype.h>
42 #include <fcntl.h>
43 #include <signal.h>
44 #include <errno.h>
45 #include <string.h>
46 #include "terminal.h"
47 #include "target.h"
48 #include "29k-share/udi/udiproc.h"
49
50 /* access the register store directly, without going through
51 the normal handler functions. This avoids an extra data copy
52 */
53
54 /* #define DEBUG 1 /* */
55 #ifdef DEBUG
56 # define DENTER(NAME) (printf("Entering %s\n",NAME), fflush(stdout))
57 # define DEXIT(NAME) (printf("Exiting %s\n",NAME), fflush(stdout))
58 #else
59 # define DENTER(NAME)
60 # define DEXIT(NAME)
61 #endif
62
63
64 extern char register_valid[];
65 extern int stop_soon_quietly; /* for wait_for_inferior */
66 extern struct value *call_function_by_hand();
67 static void udi_resume();
68 static void udi_fetch_registers ();
69 static void udi_load();
70 static int fetch_register ();
71 static void udi_store_registers ();
72 static int store_register ();
73 static int regnum_to_srnum();
74 static void udi_close ();
75 static CPUSpace udi_memory_space();
76 static int udi_write_inferior_memory();
77 static int udi_read_inferior_memory();
78 char CoffFileName[100] = "";
79 /*
80 * Processor types.
81 */
82 #define TYPE_UNKNOWN 0
83 #define TYPE_A29000 1
84 #define TYPE_A29030 2
85 #define TYPE_A29050 3
86 static char *processor_name[] = { "Unknown", "Am29000", "Am29030", "Am29050" };
87 static int processor_type=TYPE_UNKNOWN;
88 #define FREEZE_MODE (read_register(CPS_REGNUM) && 0x400)
89 #define USE_SHADOW_PC ((processor_type == TYPE_A29050) && FREEZE_MODE)
90
91 #define LLOG_FILE "udi.log"
92 #if defined (LOG_FILE)
93 FILE *log_file;
94 #endif
95
96 static int timeout = 5;
97 extern struct target_ops udi_ops; /* Forward declaration */
98
99 /* Special register enumeration.
100 */
101
102 /******************************************************************* UDI DATA*/
103 #define MAXDATA 2*1024 /* max UDI[read/write] byte size */
104 /* Descriptor for I/O to remote machine. Initialize it to -1 so that
105 udi_open knows that we don't have a file open when the program
106 starts. */
107 UDISessionId udi_session_id = -1;
108
109 CPUOffset IMemStart = 0;
110 CPUSizeT IMemSize = 0;
111 CPUOffset DMemStart = 0;
112 CPUSizeT DMemSize = 0;
113 CPUOffset RMemStart = 0;
114 CPUSizeT RMemSize = 0;
115 UDIUInt32 CPUPRL;
116 UDIUInt32 CoProcPRL;
117
118 #define SBUF_MAX 1024 /* maximum size of string handling buffer */
119 char sbuf[SBUF_MAX];
120
121 typedef struct bkpt_entry_str
122 {
123 UDIResource Addr;
124 UDIUInt32 PassCount;
125 UDIBreakType Type;
126 unsigned int BreakId;
127 } bkpt_entry_t;
128 #define BKPT_TABLE_SIZE 40
129 static bkpt_entry_t bkpt_table[BKPT_TABLE_SIZE];
130 extern char dfe_errmsg[]; /* error string */
131
132 /*********************************************************** SIGNAL SUPPORT */
133 /* Called when SIGALRM signal sent due to alarm() timeout. */
134 #ifndef HAVE_TERMIO
135
136 #ifndef __STDC__
137 # ifndef volatile
138 # define volatile /**/
139 # endif
140 #endif
141 volatile int n_alarms;
142
143 static void
144 udi_timer ()
145 {
146 #if 0
147 if (kiodebug)
148 printf ("udi_timer called\n");
149 #endif
150 n_alarms++;
151 }
152 #endif /* HAVE_TERMIO */
153
154 /* malloc'd name of the program on the remote system. */
155 static char *prog_name = NULL;
156
157
158 /* Number of SIGTRAPs we need to simulate. That is, the next
159 NEED_ARTIFICIAL_TRAP calls to udi_wait should just return
160 SIGTRAP without actually waiting for anything. */
161
162 /******************************************************* UDI_CREATE_INFERIOR */
163 /* This is called not only when we first attach, but also when the
164 user types "run" after having attached. */
165 static void
166 udi_create_inferior (execfile, args, env)
167 char *execfile;
168 char *args;
169 char **env;
170 {
171 DENTER("udi_create_inferior()");
172
173 if (execfile)
174 { if (prog_name != NULL)
175 free (prog_name);
176 prog_name = savestring (execfile, strlen (execfile));
177 }
178
179 if (prog_name == 0 /* || exec_bfd == 0 */ )
180 error ("No exec file specified");
181
182 if (udi_session_id < 0){
183 printf("UDI connection not open yet.\n");
184 return;
185 }
186
187 inferior_pid = 40000;
188
189 #if defined(ULTRA3) && defined(KERNEL_DEBUGGING)
190 /* On ultra3 (NYU) we assume the kernel is already running so there is
191 * no file to download
192 */
193 #else
194 if(*args == '\0') args = prog_name;
195 udi_load(args, 0);
196 #endif /* !ULTRA3 */
197
198 /* We will get a task spawn event immediately. */
199 #ifdef NOTDEF /* start_remote() now does a wait without a resume
200 so don't use it*/
201 start_remote ();
202 #else
203 init_wait_for_inferior ();
204 clear_proceed_status ();
205 proceed(-1,-1,0);
206 #endif
207 DEXIT("udi_create_inferior()");
208 }
209 /******************************************************* UDI_MOURN_INFERIOR */
210 static void
211 udi_mourn()
212 {
213 DENTER("udi_mourn()");
214 pop_target (); /* Pop back to no-child state */
215 generic_mourn_inferior ();
216 DEXIT("udi_mourn()");
217 }
218
219 /******************************************************************** UDI_OPEN
220 ** Open a connection to remote TIP.
221 NAME is the socket domain used for communication with the TIP,
222 then a space and the socket name or TIP-host name.
223 '<udi_udi_config_id> [progname]' for example.
224 */
225
226 /* XXX - need cleanups for udiconnect for various failures!!! */
227
228 static char *udi_config_id;
229 static void
230 udi_open (name, from_tty)
231 char *name;
232 int from_tty;
233 {
234 unsigned int prl;
235 char *p;
236 int cnt;
237 UDIMemoryRange KnownMemory[10];
238 UDIUInt32 ChipVersions[10];
239 UDIInt NumberOfRanges = 10;
240 UDIInt NumberOfChips = 10;
241 UDIPId PId;
242 UDIUInt32 TIPId, TargetId, DFEId, DFE, TIP, DFEIPCId, TIPIPCId;
243
244 DENTER("udi_open()");
245
246 target_preopen(from_tty);
247
248 /* Find the first whitespace character, it separates udi_config_id
249 from prog_name. */
250 if(!name) goto erroid;
251 for (p = name;
252 *p != '\0' && !isspace (*p); p++)
253 ;
254 if (*p == '\0')
255 erroid:
256 error("Usage: target udi config_id progname, where config_id appears in udi_soc file");
257
258 udi_config_id = (char*)malloc (p - name + 1);
259 strncpy (udi_config_id, name, p - name);
260 udi_config_id[p - name] = '\0';
261
262 /* Skip over the whitespace after udi_config_id */
263 for (; isspace (*p); p++)
264 /*EMPTY*/;
265
266 if (prog_name != NULL)
267 free (prog_name);
268 prog_name = savestring (p, strlen (p));
269
270 if (UDIConnect(udi_config_id, &udi_session_id))
271 error("UDIConnect() failed: %s\n", dfe_errmsg);
272
273 push_target (&udi_ops);
274
275 #ifndef HAVE_TERMIO
276 #ifndef NO_SIGINTERRUPT
277 /* Cause SIGALRM's to make reads fail with EINTR instead of resuming
278 the read. */
279 if (siginterrupt (SIGALRM, 1) != 0)
280 error ("udi_open: siginterrupt() %s", safe_strerror(errno));
281 #endif
282
283 /* Set up read timeout timer. */
284 if ((void (*)) signal (SIGALRM, udi_timer) == (void (*)) -1)
285 error ("udi_open: signal() %s", safe_strerror(errno));
286 #endif
287
288 #if defined (LOG_FILE)
289 log_file = fopen (LOG_FILE, "w");
290 if (log_file == NULL)
291 error ("udi_open: fopen(%s) %s", LOG_FILE, safe_strerror(errno));
292 #endif
293 /*
294 ** Initialize target configuration structure (global)
295 */
296 if(UDIGetTargetConfig( KnownMemory, &NumberOfRanges,
297 ChipVersions, &NumberOfChips))
298 error ("UDIGetTargetConfig() failed");
299 if(NumberOfChips > 2)
300 fprintf(stderr,"Taret has more than one processor\n");
301 for(cnt=0; cnt<NumberOfRanges; cnt++)
302 { switch(KnownMemory[cnt].Space)
303 {
304 default: fprintf(stderr, "UDIGetTargetConfig() unknown memory space\n");
305 break;
306 case UDI29KCP_S:
307 break;
308 case UDI29KIROMSpace:
309 RMemStart = KnownMemory[cnt].Offset;
310 RMemSize = KnownMemory[cnt].Size;
311 break;
312 case UDI29KIRAMSpace:
313 IMemStart = KnownMemory[cnt].Offset;
314 IMemSize = KnownMemory[cnt].Size;
315 break;
316 case UDI29KDRAMSpace:
317 DMemStart = KnownMemory[cnt].Offset;
318 DMemSize = KnownMemory[cnt].Size;
319 break;
320 }
321 }
322
323 /* Determine the processor revision level */
324 prl = (unsigned int)read_register(CFG_REGNUM) >> 24;
325 if ((prl&0xe0) == 0)
326 { fprintf_filtered(stderr,
327 "Remote debugging Am29000 rev %c\n",'A'+(prl&0x1f));
328 processor_type = TYPE_A29000;
329 } else if ((prl&0xe0) == 0x40) /* 29030 = 0x4* */
330 { fprintf_filtered(stderr,
331 "Remote debugging Am2903* rev %c\n",'A'+(prl&0x1f));
332 processor_type = TYPE_A29030;
333 } else if ((prl&0xe0) == 0x20) /* 29050 = 0x2* */
334 { fprintf_filtered(stderr,
335 "Remote debugging Am29050 rev %c\n",'A'+(prl&0x1f));
336 processor_type = TYPE_A29050;
337 } else {
338 processor_type = TYPE_UNKNOWN;
339 fprintf_filtered(stderr,"WARNING: processor type unknown.\n");
340 }
341 if(UDICreateProcess(&PId))
342 fprintf(stderr, "UDICreateProcess() failed\n");
343
344 /* Print out some stuff, letting the user now what's going on */
345 if(UDICapabilities( &TIPId, &TargetId, DFEId, DFE, &TIP, &DFEIPCId,
346 &TIPIPCId, sbuf))
347 error ("UDICapabilities() failed");
348 if (from_tty) {
349 printf_filtered("Remote debugging an %s connected via UDI socket,\n\
350 DFE-IPC version %x.%x.%x TIP-IPC version %x.%x.%x TIP version %x.%x.%x\n %s\n",
351 processor_name[processor_type],
352 (DFEIPCId>>8)&0xf, (DFEIPCId>>4)&0xf, DFEIPCId&0xf,
353 (TIPIPCId>>8)&0xf, (TIPIPCId>>4)&0xf, TIPIPCId&0xf,
354 (TargetId>>8)&0xf, (TargetId>>4)&0xf, TargetId&0xf,
355 sbuf);
356 #ifdef ULTRA3
357 /* FIXME: can this restriction be removed? */
358 printf_filtered("Remote debugging using virtual addresses works only\n");
359 printf_filtered(" when virtual addresses map 1:1 to physical addresses.\n");
360 #endif
361 }
362 #ifdef ULTRA3
363 if (processor_type != TYPE_A29050) {
364 fprintf_filtered(stderr,
365 "Freeze-mode debugging can only be done on an Am29050,\n");
366 fprintf_filtered(stderr,
367 " unless GDB is being used with a 29K simulator.\n");
368 }
369 #endif
370 }
371
372 /******************************************************************* UDI_CLOSE
373 Close the open connection to the TIP process.
374 Use this when you want to detach and do something else
375 with your gdb. */
376 static void
377 udi_close (quitting) /*FIXME: how is quitting used */
378 int quitting;
379 {
380 int Terminate = -1;
381 DENTER("udi_close()");
382
383 if (udi_session_id < 0)
384 error ("Can't close udi connection: not debugging remotely.");
385
386 /* We should never get here if there isn't something valid in
387 udi_session_id.
388
389 if(UDIDisconnect(udi_stream, Terminate);)
390 error ("UDIDisconnect() failed in udi_close");
391
392 /* Do not try to close udi_session_id again, later in the program. */
393 udi_session_id = -1;
394 inferior_pid = 0;
395
396 #if defined (LOG_FILE)
397 if (ferror (log_file))
398 printf ("Error writing log file.\n");
399 if (fclose (log_file) != 0)
400 printf ("Error closing log file.\n");
401 #endif
402
403 printf_filtered (" Ending remote debugging\n");
404
405 DEXIT("udi_close()");
406 }
407
408 /**************************************************************** UDI_ATACH */
409 /* Attach to a program that is already loaded and running
410 * Upon exiting the process's execution is stopped.
411 */
412 static void
413 udi_attach (args, from_tty)
414 char *args;
415 int from_tty;
416 {
417 UDIResource From;
418 UDIInt32 PC_adds;
419 UDICount Count = 1;
420 UDISizeT Size = 4;
421 UDICount CountDone;
422 UDIBool HostEndian = 0;
423 DENTER("udi_attach()");
424
425 if (udi_session_id < 0)
426 printf ("UDI connection not opened yet, use the 'target udi' command.\n");
427
428 if (from_tty)
429 printf ("Attaching to remote program %s...\n", prog_name);
430
431 mark_breakpoints_out ();
432 UDIStop();
433 From.Space = 11;
434 From.Offset = UDI29KSpecialRegs;
435 if(UDIRead(From, &PC_adds, Count, Size, &CountDone, HostEndian))
436 error ("UDIRead failed in udi_attach");
437 printf ("Remote process is now halted, pc1 = 0x%x.\n", PC_adds);
438
439 DEXIT("udi_attach()");
440 }
441 /************************************************************* UDI_DETACH */
442 /* Terminate the open connection to the TIP process.
443 Use this when you want to detach and do something else
444 with your gdb. Leave remote process running (with no breakpoints set). */
445 static void
446 udi_detach (args,from_tty)
447 char *args;
448 int from_tty;
449 {
450 DENTER("udi_dettach()");
451 remove_breakpoints(); /* Just in case there were any left in */
452 if(UDIDisconnect(udi_session_id))
453 error ("UDIDisconnect() failed in udi_detach");
454 pop_target(); /* calls udi_close to do the real work */
455 if (from_tty)
456 printf ("Ending remote debugging\n");
457 DEXIT("udi_dettach()");
458 }
459
460
461 /****************************************************************** UDI_RESUME
462 ** Tell the remote machine to resume. */
463
464 static void
465 udi_resume (step, sig)
466 int step, sig;
467 {
468 UDIError tip_error;
469 UDIUInt32 Steps = 1;
470 UDIStepType StepType = UDIStepNatural;
471 UDIRange Range;
472 DENTER("udi_resume()");
473 if (step) /* step 1 instruction */
474 { tip_error = tip_error = UDIStep(Steps, StepType, Range);
475 if(tip_error)fprintf(stderr, "UDIStep() error = %d\n", tip_error);
476 if(tip_error)error ("failed in udi_resume");
477
478 }
479 else
480 { if(UDIExecute())
481 error ("UDIExecute() failed in udi_resume");
482 }
483
484 DEXIT("udi_resume()");
485 }
486
487 /******************************************************************** UDI_WAIT
488 ** Wait until the remote machine stops, then return,
489 storing status in STATUS just as `wait' would. */
490
491 static int
492 udi_wait (status)
493 WAITTYPE *status;
494 {
495 UDIInt32 MaxTime;
496 UDIPId PId;
497 UDIInt32 StopReason;
498 UDISizeT CountDone;
499 int old_timeout = timeout;
500 int old_immediate_quit = immediate_quit;
501 int i;
502
503 DENTER("udi_wait()");
504 WSETEXIT ((*status), 0);
505
506 /* wait for message to arrive. It should be:
507 If the target stops executing, udi_wait() should return.
508 */
509 timeout = 0; /* Wait indefinetly for a message */
510 immediate_quit = 1; /* Helps ability to QUIT */
511 while(1)
512 {
513 i = 0;
514 MaxTime = UDIWaitForever;
515 UDIWait(MaxTime, &PId, &StopReason);
516 QUIT; /* Let user quit if they want */
517 switch (StopReason & 0xff)
518 {
519 default:
520 goto halted;
521 case UDIStdoutReady:
522 if(UDIGetStdout(sbuf, (UDISizeT)SBUF_MAX, &CountDone))
523 error("UDIGetStdin() failed in udi_wait");
524 while(CountDone--)putc(sbuf[i++], stdout);
525 fflush(stdout);
526 break;
527 case UDIStderrReady:
528 UDIGetStderr(sbuf, (UDISizeT)SBUF_MAX, &CountDone);
529 while(CountDone--)putc(sbuf[i++], stderr);
530 fflush(stderr);
531 fflush(stderr);
532 break;
533 case UDIStdinNeeded:
534 printf("DEBUG: stdin requested ... continue\n");
535 /* UDIPutStdin(sbuf, (UDISizeT)i, &CountDone); */
536 break;
537 case UDIStdinModeX:
538 break;
539 }
540 continue;
541 }
542 halted:
543 if (StopReason & 0xff == UDITrapped ) /* lower 8-bits == 0 */
544 {
545 if (StopReason >> 24 == 0)
546 { printf("Am290*0 received vector number 0 (break point)\n");
547 WSETSTOP ((*status), SIGTRAP);
548 }
549 else if (StopReason >> 24 == 1)
550 { printf("Am290*0 received vector 1\n");
551 WSETSTOP ((*status), SIGBUS);
552 }
553 else if (StopReason >> 24 == 3
554 || StopReason >> 24 == 4)
555 { printf("Am290*0 received vector number %d\n",
556 StopReason >> 24);
557 WSETSTOP ((*status), SIGFPE);
558 }
559 else if (StopReason >> 24 == 5)
560 { printf("Am290*0 received vector number %d\n",
561 StopReason >> 24);
562 WSETSTOP ((*status), SIGILL);
563 }
564 else if (StopReason >> 24 >= 6
565 && StopReason >> 24 <= 11)
566 { printf("Am290*0 received vector number %d\n",
567 StopReason >> 24);
568 WSETSTOP ((*status), SIGSEGV);
569 }
570 else if (StopReason >> 24 == 12
571 || StopReason >> 24 == 13)
572 { printf("Am290*0 received vector number %d\n",
573 StopReason >> 24);
574 WSETSTOP ((*status), SIGILL);
575 }
576 else if ((StopReason & 0xff) == 14)
577 { printf("Am290*0 received vector number %d\n",
578 StopReason >> 24);
579 WSETSTOP ((*status), SIGALRM);
580 }
581 else if ((StopReason & 0xff) == 15)
582 WSETSTOP ((*status), SIGTRAP);
583 else if ((StopReason >> 24) >= 16
584 && (StopReason >> 24) <= 21)
585 { printf("Am290*0 received vector number %d\n",
586 StopReason >> 24);
587 WSETSTOP ((*status), SIGINT);
588 }
589 else if ((StopReason & 0xff) == 22)
590 { printf("Am290*0 received vector number %d\n",
591 StopReason >> 24);
592 WSETSTOP ((*status), SIGILL);
593 }
594 else if ((StopReason & 0xff) == 77)
595 WSETSTOP ((*status), SIGTRAP);
596 else
597 exit:
598 WSETEXIT ((*status), 0);
599 }
600 else if ((StopReason & 0xff) == UDIBreak)
601 WSETSTOP ((*status), SIGTRAP);
602 else if ((StopReason & 0xff) == UDINotExecuting)
603 WSETSTOP ((*status), SIGTERM);
604 else if ((StopReason & 0xff) == UDIRunning)
605 WSETSTOP ((*status), SIGILL);
606 else if ((StopReason & 0xff) == UDIStopped)
607 WSETSTOP ((*status), SIGTSTP);
608 else if ((StopReason & 0xff) == UDIWarned)
609 WSETSTOP ((*status), SIGLOST);
610 else if ((StopReason & 0xff) == UDIStepped)
611 WSETSTOP ((*status), SIGTRAP);
612 else if ((StopReason & 0xff) == UDIWaiting)
613 WSETSTOP ((*status), SIGSTOP);
614 else if ((StopReason & 0xff) == UDIHalted)
615 WSETSTOP ((*status), SIGKILL);
616 else
617 WSETEXIT ((*status), 0);
618
619 timeout = old_timeout; /* Restore original timeout value */
620 immediate_quit = old_immediate_quit;
621 DEXIT("udi_wait()");
622 return 0;
623 }
624
625 /********************************************************** UDI_FETCH_REGISTERS
626 * Read a remote register 'regno'.
627 * If regno==-1 then read all the registers.
628 */
629 static void
630 udi_fetch_registers (regno)
631 int regno;
632 {
633 UDIResource From;
634 UDIUInt32 *To;
635 UDICount Count;
636 UDISizeT Size = 4;
637 UDICount CountDone;
638 UDIBool HostEndian = 0;
639 int i;
640
641 if (regno >= 0) {
642 fetch_register(regno);
643 return;
644 }
645
646 /* Gr1/rsp */
647
648 From.Space = UDI29KGlobalRegs;
649 From.Offset = 1;
650 To = (UDIUInt32 *)&registers[4 * GR1_REGNUM];
651 Count = 1;
652 if (UDIRead(From, To, Count, Size, &CountDone, HostEndian))
653 error("UDIRead() failed in udi_fetch_registers");
654
655 register_valid[GR1_REGNUM] = 1;
656
657 #if defined(GR64_REGNUM) /* Read gr64-127 */
658
659 /* Global Registers gr64-gr95 */
660
661 From.Space = UDI29KGlobalRegs;
662 From.Offset = 64;
663 To = (UDIUInt32 *)&registers[4 * GR64_REGNUM];
664 Count = 32;
665 if (UDIRead(From, To, Count, Size, &CountDone, HostEndian))
666 error("UDIRead() failed in udi_fetch_registers");
667
668 for (i = GR64_REGNUM; i < GR64_REGNUM + 32; i++)
669 register_valid[i] = 1;
670
671 #endif /* GR64_REGNUM */
672
673 /* Global Registers gr96-gr127 */
674
675 From.Space = UDI29KGlobalRegs;
676 From.Offset = 96;
677 To = (UDIUInt32 *)&registers[4 * GR96_REGNUM];
678 Count = 32;
679 if (UDIRead(From, To, Count, Size, &CountDone, HostEndian))
680 error("UDIRead() failed in udi_fetch_registers");
681
682 for (i = GR96_REGNUM; i < GR96_REGNUM + 32; i++)
683 register_valid[i] = 1;
684
685 /* Local Registers */
686
687 From.Space = UDI29KLocalRegs;
688 From.Offset = 0;
689 To = (UDIUInt32 *)&registers[4 * LR0_REGNUM];
690 Count = 128;
691 if (UDIRead(From, To, Count, Size, &CountDone, HostEndian))
692 error("UDIRead() failed in udi_fetch_registers");
693
694 for (i = LR0_REGNUM; i < LR0_REGNUM + 128; i++)
695 register_valid[i] = 1;
696
697 /* Protected Special Registers */
698
699 From.Space = UDI29KSpecialRegs;
700 From.Offset = 0;
701 To = (UDIUInt32 *)&registers[4 * SR_REGNUM(0)];
702 Count = 15;
703 if (UDIRead(From, To, Count, Size, &CountDone, HostEndian))
704 error("UDIRead() failed in udi_fetch_registers");
705
706 for (i = SR_REGNUM(0); i < SR_REGNUM(0) + 15; i++)
707 register_valid[i] = 1;
708
709 if (USE_SHADOW_PC) { /* Let regno_to_srnum() handle the register number */
710 fetch_register(NPC_REGNUM);
711 fetch_register(PC_REGNUM);
712 fetch_register(PC2_REGNUM);
713
714 /* Unprotected Special Registers sr128-sr135 */
715
716 From.Space = UDI29KSpecialRegs;
717 From.Offset = 128;
718 To = (UDIUInt32 *)&registers[4 * SR_REGNUM(128)];
719 Count = 135-128 + 1;
720 if (UDIRead(From, To, Count, Size, &CountDone, HostEndian))
721 error("UDIRead() failed in udi_fetch_registers");
722
723 for (i = SR_REGNUM(128); i < SR_REGNUM(128) + 135-128+1; i++)
724 register_valid[i] = 1;
725 }
726
727 /* There doesn't seem to be any way to get these. */
728 {
729 int val = -1;
730 supply_register (FPE_REGNUM, (char *) &val);
731 supply_register (INTE_REGNUM, (char *) &val);
732 supply_register (FPS_REGNUM, (char *) &val);
733 supply_register (EXO_REGNUM, (char *) &val);
734 }
735 }
736
737
738 /********************************************************* UDI_STORE_REGISTERS
739 ** Store register regno into the target.
740 * If regno==-1 then store all the registers.
741 */
742
743 static void
744 udi_store_registers (regno)
745 int regno;
746 {
747 UDIUInt32 *From;
748 UDIResource To;
749 UDICount Count;
750 UDISizeT Size = 4;
751 UDICount CountDone;
752 UDIBool HostEndian = 0;
753
754 if (regno >= 0)
755 {
756 store_register(regno);
757 return;
758 }
759
760 /* Gr1/rsp */
761
762 From = (UDIUInt32 *)&registers[4 * GR1_REGNUM];
763 To.Space = UDI29KGlobalRegs;
764 To.Offset = 1;
765 Count = 1;
766 if(UDIWrite(From, To, Count, Size, &CountDone, HostEndian))
767 error("UDIWrite() failed in udi_store_regisetrs");
768
769 #if defined(GR64_REGNUM)
770
771 /* Global registers gr64-gr95 */
772
773 From = (UDIUInt32 *)&registers[4 * GR64_REGNUM];
774 To.Space = UDI29KGlobalRegs;
775 To.Offset = 64;
776 Count = 32;
777 if(UDIWrite(From, To, Count, Size, &CountDone, HostEndian))
778 error("UDIWrite() failed in udi_store_regisetrs");
779
780 #endif /* GR64_REGNUM */
781
782 /* Global registers gr96-gr127 */
783
784 From = (UDIUInt32 *)&registers[4 * GR96_REGNUM];
785 To.Space = UDI29KGlobalRegs;
786 To.Offset = 96;
787 Count = 32;
788 if(UDIWrite(From, To, Count, Size, &CountDone, HostEndian))
789 error("UDIWrite() failed in udi_store_regisetrs");
790
791 /* Local Registers */
792
793 From = (UDIUInt32 *)&registers[4 * LR0_REGNUM];
794 To.Space = UDI29KLocalRegs;
795 To.Offset = 0;
796 Count = 128;
797 if(UDIWrite(From, To, Count, Size, &CountDone, HostEndian))
798 error("UDIWrite() failed in udi_store_regisetrs");
799
800
801 /* Protected Special Registers */ /* VAB through TMR */
802
803 From = (UDIUInt32 *)&registers[4 * SR_REGNUM(0)];
804 To.Space = UDI29KSpecialRegs;
805 To.Offset = 0;
806 Count = 10;
807 if(UDIWrite(From, To, Count, Size, &CountDone, HostEndian))
808 error("UDIWrite() failed in udi_store_regisetrs");
809
810 /* PC0, PC1, PC2 possibly as shadow registers */
811
812 From = (UDIUInt32 *)&registers[4 * SR_REGNUM(10)];
813 To.Space = UDI29KSpecialRegs;
814 Count = 3;
815 if (USE_SHADOW_PC)
816 To.Offset = 20; /* SPC0 */
817 else
818 To.Offset = 10; /* PC0 */
819 if(UDIWrite(From, To, Count, Size, &CountDone, HostEndian))
820 error("UDIWrite() failed in udi_store_regisetrs");
821
822 /* LRU and MMU */
823
824 From = (UDIUInt32 *)&registers[4 * SR_REGNUM(13)];
825 To.Space = UDI29KSpecialRegs;
826 To.Offset = 13;
827 Count = 2;
828 if(UDIWrite(From, To, Count, Size, &CountDone, HostEndian))
829 error("UDIWrite() failed in udi_store_regisetrs");
830
831 /* Unprotected Special Registers */
832
833 From = (UDIUInt32 *)&registers[4 * SR_REGNUM(128)];
834 To.Space = UDI29KSpecialRegs;
835 To.Offset = 128;
836 Count = 135-128 +1;
837 if(UDIWrite(From, To, Count, Size, &CountDone, HostEndian))
838 error("UDIWrite() failed in udi_store_regisetrs");
839
840 registers_changed ();
841 }
842
843 /****************************************************** UDI_PREPARE_TO_STORE */
844 /* Get ready to modify the registers array. On machines which store
845 individual registers, this doesn't need to do anything. On machines
846 which store all the registers in one fell swoop, this makes sure
847 that registers contains all the registers from the program being
848 debugged. */
849
850 static void
851 udi_prepare_to_store ()
852 {
853 /* Do nothing, since we can store individual regs */
854 }
855
856 /********************************************************** TRANSLATE_ADDR */
857 static CORE_ADDR
858 translate_addr(addr)
859 CORE_ADDR addr;
860 {
861 #if defined(ULTRA3) && defined(KERNEL_DEBUGGING)
862 /* Check for a virtual address in the kernel */
863 /* Assume physical address of ublock is in paddr_u register */
864 /* FIXME: doesn't work for user virtual addresses */
865 if (addr >= UVADDR) {
866 /* PADDR_U register holds the physical address of the ublock */
867 CORE_ADDR i = (CORE_ADDR)read_register(PADDR_U_REGNUM);
868 return(i + addr - (CORE_ADDR)UVADDR);
869 } else {
870 return(addr);
871 }
872 #else
873 return(addr);
874 #endif
875 }
876 /************************************************* UDI_XFER_INFERIOR_MEMORY */
877 /* FIXME! Merge these two. */
878 static int
879 udi_xfer_inferior_memory (memaddr, myaddr, len, write)
880 CORE_ADDR memaddr;
881 char *myaddr;
882 int len;
883 int write;
884 {
885
886 memaddr = translate_addr(memaddr);
887
888 if (write)
889 return udi_write_inferior_memory (memaddr, myaddr, len);
890 else
891 return udi_read_inferior_memory (memaddr, myaddr, len);
892 }
893
894 /********************************************************** UDI_FILES_INFO */
895 static void
896 udi_files_info ()
897 {
898 printf ("\tAttached to UDI socket to %s and running program %s.\n",
899 udi_config_id, prog_name);
900 }
901
902 /**************************************************** UDI_INSERT_BREAKPOINT */
903 static int
904 udi_insert_breakpoint (addr, contents_cache)
905 CORE_ADDR addr;
906 char *contents_cache;
907 {
908 int cnt;
909 UDIError err;
910
911 for (cnt = 0; cnt < BKPT_TABLE_SIZE; cnt++)
912 if (bkpt_table[cnt].Type == 0) /* Find first free slot */
913 break;
914
915 if(cnt >= BKPT_TABLE_SIZE)
916 error("Too many breakpoints set");
917
918 bkpt_table[cnt].Addr.Offset = addr;
919 bkpt_table[cnt].Addr.Space = UDI29KIRAMSpace;
920 bkpt_table[cnt].PassCount = 1;
921 bkpt_table[cnt].Type = UDIBreakFlagExecute;
922
923 err = UDISetBreakpoint(bkpt_table[cnt].Addr,
924 bkpt_table[cnt].PassCount,
925 bkpt_table[cnt].Type,
926 &bkpt_table[cnt].BreakId);
927
928 if (err == 0) return 0; /* Success */
929
930 bkpt_table[cnt].Type = 0;
931 error("UDISetBreakpoint returned error code %d\n", err);
932 }
933
934 /**************************************************** UDI_REMOVE_BREAKPOINT */
935 static int
936 udi_remove_breakpoint (addr, contents_cache)
937 CORE_ADDR addr;
938 char *contents_cache;
939 {
940 int cnt;
941 UDIError err;
942
943 for (cnt = 0; cnt < BKPT_TABLE_SIZE; cnt++)
944 if (bkpt_table[cnt].Addr.Offset == addr) /* Find matching breakpoint */
945 break;
946
947 if(cnt >= BKPT_TABLE_SIZE)
948 error("Can't find breakpoint in table");
949
950 bkpt_table[cnt].Type = 0;
951
952 err = UDIClearBreakpoint(bkpt_table[cnt].BreakId);
953 if (err == 0) return 0; /* Success */
954
955 error("UDIClearBreakpoint returned error code %d\n", err);
956 }
957
958 /***************************************************************** UDI_KILL */
959 static void
960 udi_kill(arg,from_tty)
961 char *arg;
962 int from_tty;
963 {
964 char buf[4];
965
966 DENTER("udi_kill()");
967 #if defined(ULTRA3) && defined(KERNEL_DEBUGGING)
968 /* We don't ever kill the kernel */
969 if (from_tty) {
970 printf_filtered("Kernel not killed, but left in current state.\n");
971 printf_filtered("Use detach to leave kernel running.\n");
972 }
973 #else
974 UDIStop();
975 inferior_pid = 0;
976 if (from_tty) {
977 printf("Target has been stopped.");
978 }
979 pop_target();
980 #endif
981 DEXIT("udi_kill()");
982 }
983
984
985
986 /***************************************************************** UDI_LOAD */
987 /*
988 * Load a program into the target.
989 */
990 static void
991 udi_load(arg_string,from_tty)
992 char *arg_string;
993 int from_tty;
994 {
995 #define MAX_TOKENS 25
996 #define BUFFER_SIZE 256
997 int token_count;
998 char *token[MAX_TOKENS];
999 char cmd_line[BUFFER_SIZE];
1000
1001 dont_repeat ();
1002
1003 #if defined(KERNEL_DEBUGGING) && defined(ULTRA3)
1004 printf("The kernel had better be loaded already! Loading not done.\n");
1005 #else
1006 if (arg_string == 0)
1007 error ("The load command takes a file name");
1008 arg_string = tilde_expand (arg_string);
1009 sprintf(cmd_line,"y %s %s", prog_name, arg_string);
1010
1011 token_count = 0;
1012 token[0] = cmd_line;
1013
1014 if (cmd_line[0] != '\0')
1015 { token[token_count] = strtok(cmd_line, " \t,;\n\r");
1016
1017 if (token[token_count] != NULL)
1018 { do {
1019 token_count = token_count + 1;
1020 token[token_count] = strtok((char *) NULL, " \t,;\n\r");
1021 } while ((token[token_count] != NULL) &&
1022 (token_count < MAX_TOKENS));
1023 }
1024 else
1025 *token[0] = '\0';
1026 }
1027 make_cleanup (free, arg_string);
1028 QUIT;
1029 immediate_quit++;
1030 if(yank_cmd(token, token_count))
1031 error("Failure when tring to load program");
1032 immediate_quit--;
1033 symbol_file_add (arg_string, from_tty, 0, 0, 0, 0);/*DEBUG need to add text_addr */
1034 #endif
1035
1036 }
1037
1038 /*************************************************** UDI_WRITE_INFERIOR_MEMORY
1039 ** Copy LEN bytes of data from debugger memory at MYADDR
1040 to inferior's memory at MEMADDR. Returns number of bytes written. */
1041 static int
1042 udi_write_inferior_memory (memaddr, myaddr, len)
1043 CORE_ADDR memaddr;
1044 char *myaddr;
1045 int len;
1046 {
1047 int nwritten = 0;
1048 UDIUInt32 *From;
1049 UDIResource To;
1050 UDICount Count;
1051 UDISizeT Size = 1;
1052 UDICount CountDone = 0;
1053 UDIBool HostEndian = 0;
1054
1055
1056 /* DENTER("udi_write_inferior_memory()"); */
1057 To.Space = udi_memory_space(memaddr);
1058 From = (UDIUInt32*)myaddr;
1059
1060 while (nwritten < len)
1061 { Count = len - nwritten;
1062 if (Count > MAXDATA) Count = MAXDATA;
1063 To.Offset = memaddr + nwritten;
1064 if(UDIWrite(From, To, Count, Size, &CountDone, HostEndian))
1065 { error("UDIWrite() failed in udi_write_inferrior_memory");
1066 break;
1067 }
1068 else
1069 { nwritten += CountDone;
1070 From += CountDone;
1071 }
1072 }
1073 /* DEXIT("udi_write_inferior_memory()"); */
1074 return(nwritten);
1075 }
1076
1077 /**************************************************** UDI_READ_INFERIOR_MEMORY
1078 ** Read LEN bytes from inferior memory at MEMADDR. Put the result
1079 at debugger address MYADDR. Returns number of bytes read. */
1080 static int
1081 udi_read_inferior_memory(memaddr, myaddr, len)
1082 CORE_ADDR memaddr;
1083 char *myaddr;
1084 int len;
1085 {
1086 int nread = 0;
1087 UDIResource From;
1088 UDIUInt32 *To;
1089 UDICount Count;
1090 UDISizeT Size = 1;
1091 UDICount CountDone = 0;
1092 UDIBool HostEndian = 0;
1093
1094
1095 /* DENTER("udi_read_inferior_memory()"); */
1096 From.Space = udi_memory_space(memaddr);
1097 To = (UDIUInt32*)myaddr;
1098
1099 while (nread < len)
1100 { Count = len - nread;
1101 if (Count > MAXDATA) Count = MAXDATA;
1102 From.Offset = memaddr + nread;
1103 if(UDIRead(From, To, Count, Size, &CountDone, HostEndian))
1104 { error("UDIWrite() failed in udi_read_inferrior_memory");
1105 break;
1106 }
1107 else
1108 { nread += CountDone;
1109 To += CountDone;
1110 }
1111 }
1112 return(nread);
1113 }
1114
1115 /********************************************************************* WARNING
1116 */
1117 udi_warning(num)
1118 int num;
1119 {
1120 error ("ERROR while loading program into remote TIP: $d\n", num);
1121 }
1122
1123
1124 /*****************************************************************************/
1125 /* Fetch a single register indicatated by 'regno'.
1126 * Returns 0/-1 on success/failure.
1127 */
1128 static int
1129 fetch_register (regno)
1130 int regno;
1131 {
1132 UDIResource From;
1133 UDIUInt32 To;
1134 UDICount Count = 1;
1135 UDISizeT Size = 4;
1136 UDICount CountDone;
1137 UDIBool HostEndian = 0;
1138 int result;
1139
1140 if (regno == GR1_REGNUM)
1141 {
1142 From.Space = UDI29KGlobalRegs;
1143 From.Offset = 1;
1144 }
1145 else if (regno >= GR96_REGNUM && regno < GR96_REGNUM + 32)
1146 {
1147 From.Space = UDI29KGlobalRegs;
1148 From.Offset = (regno - GR96_REGNUM) + 96;;
1149 }
1150
1151 #if defined(GR64_REGNUM)
1152
1153 else if (regno >= GR64_REGNUM && regno < GR64_REGNUM + 32 )
1154 {
1155 From.Space = UDI29KGlobalRegs;
1156 From.Offset = (regno - GR64_REGNUM) + 64;
1157 }
1158
1159 #endif /* GR64_REGNUM */
1160
1161 else if (regno >= LR0_REGNUM && regno < LR0_REGNUM + 128)
1162 {
1163 From.Space = UDI29KLocalRegs;
1164 From.Offset = (regno - LR0_REGNUM);
1165 }
1166 else if (regno>=FPE_REGNUM && regno<=EXO_REGNUM)
1167 {
1168 int val = -1;
1169 supply_register(160 + (regno - FPE_REGNUM),(char *) &val);
1170 return 0; /* Pretend Success */
1171 }
1172 else
1173 {
1174 From.Space = UDI29KSpecialRegs;
1175 From.Offset = regnum_to_srnum(regno);
1176 }
1177
1178 if (UDIRead(From, &To, Count, Size, &CountDone, HostEndian))
1179 error("UDIRead() failed in udi_fetch_registers");
1180
1181 supply_register(regno, (char *) &To);
1182 return result;
1183 }
1184 /*****************************************************************************/
1185 /* Store a single register indicated by 'regno'.
1186 * Returns 0/-1 on success/failure.
1187 */
1188 static int
1189 store_register (regno)
1190 int regno;
1191 {
1192 int result;
1193 UDIUInt32 From;
1194 UDIResource To;
1195 UDICount Count = 1;
1196 UDISizeT Size = 4;
1197 UDICount CountDone;
1198 UDIBool HostEndian = 0;
1199
1200 DENTER("store_register()");
1201 From = read_register (regno); /* get data value */
1202
1203 if (regno == GR1_REGNUM)
1204 { To.Space = UDI29KGlobalRegs;
1205 To.Offset = 1;
1206 result = UDIWrite(&From, To, Count, Size, &CountDone, HostEndian);
1207 /* Setting GR1 changes the numbers of all the locals, so invalidate the
1208 * register cache. Do this *after* calling read_register, because we want
1209 * read_register to return the value that write_register has just stuffed
1210 * into the registers array, not the value of the register fetched from
1211 * the inferior.
1212 */
1213 registers_changed ();
1214 }
1215 #if defined(GR64_REGNUM)
1216 else if (regno >= GR64_REGNUM && regno < GR64_REGNUM + 32 )
1217 { To.Space = UDI29KGlobalRegs;
1218 To.Offset = (regno - GR64_REGNUM) + 64;
1219 result = UDIWrite(&From, To, Count, Size, &CountDone, HostEndian);
1220 }
1221 #endif /* GR64_REGNUM */
1222 else if (regno >= GR96_REGNUM && regno < GR96_REGNUM + 32)
1223 { To.Space = UDI29KGlobalRegs;
1224 To.Offset = (regno - GR96_REGNUM) + 96;
1225 result = UDIWrite(&From, To, Count, Size, &CountDone, HostEndian);
1226 }
1227 else if (regno >= LR0_REGNUM && regno < LR0_REGNUM + 128)
1228 { To.Space = UDI29KLocalRegs;
1229 To.Offset = (regno - LR0_REGNUM);
1230 result = UDIWrite(&From, To, Count, Size, &CountDone, HostEndian);
1231 }
1232 else if (regno>=FPE_REGNUM && regno<=EXO_REGNUM)
1233 {
1234 return 0; /* Pretend Success */
1235 }
1236 else /* An unprotected or protected special register */
1237 { To.Space = UDI29KSpecialRegs;
1238 To.Offset = regnum_to_srnum(regno);
1239 result = UDIWrite(&From, To, Count, Size, &CountDone, HostEndian);
1240 }
1241
1242 DEXIT("store_register()");
1243 if(result)
1244 { result = -1;
1245 error("UDIWrite() failed in store_registers");
1246 }
1247 return result;
1248 }
1249 /********************************************************** REGNUM_TO_SRNUM */
1250 /*
1251 * Convert a gdb special register number to a 29000 special register number.
1252 */
1253 static int
1254 regnum_to_srnum(regno)
1255 int regno;
1256 {
1257 switch(regno) {
1258 case VAB_REGNUM: return(0);
1259 case OPS_REGNUM: return(1);
1260 case CPS_REGNUM: return(2);
1261 case CFG_REGNUM: return(3);
1262 case CHA_REGNUM: return(4);
1263 case CHD_REGNUM: return(5);
1264 case CHC_REGNUM: return(6);
1265 case RBP_REGNUM: return(7);
1266 case TMC_REGNUM: return(8);
1267 case TMR_REGNUM: return(9);
1268 case NPC_REGNUM: return(USE_SHADOW_PC ? (20) : (10));
1269 case PC_REGNUM: return(USE_SHADOW_PC ? (21) : (11));
1270 case PC2_REGNUM: return(USE_SHADOW_PC ? (22) : (12));
1271 case MMU_REGNUM: return(13);
1272 case LRU_REGNUM: return(14);
1273 case IPC_REGNUM: return(128);
1274 case IPA_REGNUM: return(129);
1275 case IPB_REGNUM: return(130);
1276 case Q_REGNUM: return(131);
1277 case ALU_REGNUM: return(132);
1278 case BP_REGNUM: return(133);
1279 case FC_REGNUM: return(134);
1280 case CR_REGNUM: return(135);
1281 case FPE_REGNUM: return(160);
1282 case INTE_REGNUM: return(161);
1283 case FPS_REGNUM: return(162);
1284 case EXO_REGNUM:return(164);
1285 default:
1286 return(255); /* Failure ? */
1287 }
1288 }
1289 /****************************************************************************/
1290 /*
1291 * Determine the Target memory space qualifier based on the addr.
1292 * FIXME: Can't distinguis I_ROM/D_ROM.
1293 * FIXME: Doesn't know anything about I_CACHE/D_CACHE.
1294 */
1295 static CPUSpace
1296 udi_memory_space(addr)
1297 CORE_ADDR *addr;
1298 {
1299 UDIUInt32 tstart = IMemStart;
1300 UDIUInt32 tend = tstart + IMemSize;
1301 UDIUInt32 dstart = DMemStart;
1302 UDIUInt32 dend = tstart + DMemSize;
1303 UDIUInt32 rstart = RMemStart;
1304 UDIUInt32 rend = tstart + RMemSize;
1305
1306 if (((UDIUInt32)addr >= tstart) && ((UDIUInt32)addr < tend)) {
1307 return UDI29KIRAMSpace;
1308 } else if (((UDIUInt32)addr >= dstart) && ((UDIUInt32)addr < dend)) {
1309 return UDI29KDRAMSpace;
1310 } else if (((UDIUInt32)addr >= rstart) && ((UDIUInt32)addr < rend)) {
1311 /* FIXME: how do we determine between D_ROM and I_ROM */
1312 return UDI29KIROMSpace;
1313 } else /* FIXME: what do me do now? */
1314 return UDI29KDRAMSpace; /* Hmmm! */
1315 }
1316 /*********************************************************************** STUBS
1317 */
1318
1319 void convert16() {;}
1320 void convert32() {;}
1321 FILE* EchoFile = 0; /* used for debugging */
1322 int QuietMode = 0; /* used for debugging */
1323
1324 /****************************************************************************/
1325 /*
1326 * Define the target subroutine names
1327 */
1328 static struct target_ops udi_ops = {
1329 "udi", "Remote UDI connected TIP",
1330 "Remote debug an Am290*0 using socket connection to TIP process ",
1331 udi_open, udi_close,
1332 udi_attach, udi_detach, udi_resume, udi_wait,
1333 udi_fetch_registers, udi_store_registers,
1334 udi_prepare_to_store, 0, 0, /* conv_to, conv_from */
1335 udi_xfer_inferior_memory,
1336 udi_files_info,
1337 udi_insert_breakpoint, udi_remove_breakpoint, /* Breakpoints */
1338 0, 0, 0, 0, 0, /* Terminal handling */
1339 udi_kill, /* FIXME, kill */
1340 udi_load,
1341 0, /* lookup_symbol */
1342 udi_create_inferior, /* create_inferior */
1343 udi_mourn, /* mourn_inferior FIXME */
1344 process_stratum, 0, /* next */
1345 1, 1, 1, 1, 1, /* all mem, mem, stack, regs, exec */
1346 0, 0, /* Section pointers */
1347 OPS_MAGIC, /* Always the last thing */
1348 };
1349
1350 void _initialize_remote_udi()
1351 {
1352 add_target (&udi_ops);
1353 }
1354
1355 #ifdef NO_HIF_SUPPORT
1356 service_HIF(msg)
1357 union msg_t *msg;
1358 {
1359 return(0); /* Emulate a failure */
1360 }
1361 #endif
This page took 0.05711 seconds and 5 git commands to generate.