]> git.kernelconcepts.de Git - karo-tx-redboot.git/blob - packages/hal/v85x/v850/v2_0/src/v850_ice.cxx
Initial revision
[karo-tx-redboot.git] / packages / hal / v85x / v850 / v2_0 / src / v850_ice.cxx
1 //========================================================================
2 //
3 //      v850_ice.cxx
4 //
5 //      ICE debugging support for V850 processors
6 //
7 //========================================================================
8 //####ECOSGPLCOPYRIGHTBEGIN####
9 // -------------------------------------------
10 // This file is part of eCos, the Embedded Configurable Operating System.
11 // Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
12 //
13 // eCos is free software; you can redistribute it and/or modify it under
14 // the terms of the GNU General Public License as published by the Free
15 // Software Foundation; either version 2 or (at your option) any later version.
16 //
17 // eCos is distributed in the hope that it will be useful, but WITHOUT ANY
18 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
19 // FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
20 // for more details.
21 //
22 // You should have received a copy of the GNU General Public License along
23 // with eCos; if not, write to the Free Software Foundation, Inc.,
24 // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
25 //
26 // As a special exception, if other files instantiate templates or use macros
27 // or inline functions from this file, or you compile this file and link it
28 // with other works to produce a work based on this file, this file does not
29 // by itself cause the resulting work to be covered by the GNU General Public
30 // License. However the source code for this file must still be made available
31 // in accordance with section (3) of the GNU General Public License.
32 //
33 // This exception does not invalidate any other reasons why a work based on
34 // this file might be covered by the GNU General Public License.
35 //
36 // Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
37 // at http://sources.redhat.com/ecos/ecos-license/
38 // -------------------------------------------
39 //####ECOSGPLCOPYRIGHTEND####
40 //========================================================================
41 //#####DESCRIPTIONBEGIN####
42 //
43 // Author(s):     jlarmour
44 // Contributors:  
45 // Date:          2001-03-12
46 // Purpose:       
47 // Description:   ICE debugging support for V850 processors
48 // Usage:         
49 //
50 //####DESCRIPTIONEND####
51 //
52 //========================================================================
53
54 #include <pkgconf/hal.h>
55
56 #ifdef CYGDBG_HAL_V850_ICE
57
58 #include <stddef.h>
59 #include <cyg/infra/cyg_type.h>
60 #include <cyg/hal/dbg-threads-api.h>
61 #include <cyg/hal/nec-stub.h>
62 #include <cyg/hal/hal_arch.h>
63
64 #define ICEDEBUG 0
65
66 #if ICEDEBUG
67 #include <cyg/infra/diag.h>
68 #endif
69
70 /* ----------------------------------------------------------------------- */
71 /* Common ICE syscall information */
72
73 /* Magic area for syscall information, from vectors.S */
74 __externC char hal_v85x_ice_syscall_info[];
75
76 /* Syscall operation codes. This is a "contract" with the host. */
77
78 #define V850ICE_SYSCALL_GET_THREADNEXT 1
79 #define V850ICE_SYSCALL_GET_THREADREGS 2
80 #define V850ICE_SYSCALL_SET_THREADREGS 3
81 #define V850ICE_SYSCALL_GET_CURRTHREAD 4
82 #define V850ICE_SYSCALL_GET_THREADINFO 5
83 #define V850ICE_SYSCALL_CONSOLE_INPUT  6
84
85 /* System call information area layout */
86 #define ICE_SYSCALL_INFO_VALIDATOR     (*(int *)&hal_v85x_ice_syscall_info[0])
87 #define ICE_SYSCALL_INFO_STARTPC       (*(int *)&hal_v85x_ice_syscall_info[4])
88 #define ICE_SYSCALL_INFO_ENDPC         (*(int *)&hal_v85x_ice_syscall_info[8])
89 #define ICE_SYSCALL_INFO_STACK         (*(int *)&hal_v85x_ice_syscall_info[12])
90 #define ICE_SYSCALL_INFO_IOBUF         (*(int *)&hal_v85x_ice_syscall_info[16])
91 #define ICE_SYSCALL_INFO_DIAGOUTPC     (*(int *)&hal_v85x_ice_syscall_info[20])
92 #define ICE_SYSCALL_INFO_DIAGOUTBUF    (*(int *)&hal_v85x_ice_syscall_info[24])
93 #define ICE_SYSCALL_INFO_DIAGOUTBUFEND (*(int *)&hal_v85x_ice_syscall_info[28])
94
95 /* We can't use normal memcpy when invoked via the ICE. It may be unsafe. */
96 static void
97 my_memcpy( void *vd, const void *vs, int n)
98 {
99     char *d = (char *)vd;
100     char *s = (char *)vs;
101
102     while (n--)
103         *d++=*s++;
104 }
105
106 static void
107 my_memset( void *vs, char c, int n)
108 {
109     char *s = (char *)vs;
110
111     while (n--)
112         *s++ = c;
113 }
114
115 /* ----------------------------------------------------------------------- */
116 /* Support for diag output via ICE */
117
118 #ifdef CYGDBG_HAL_V85X_V850_ICE_DIAG
119
120 #include <cyg/hal/hal_if.h>
121
122 static volatile cyg_uint8 v850ice_output_buf[128];
123 static volatile cyg_uint8 *v850ice_output_end = v850ice_output_buf;
124 #define OUTPUT_BUF_END (&v850ice_output_buf[ sizeof(v850ice_output_buf)])
125 static volatile cyg_uint8 v850ice_input_buf[128];
126 #define INPUT_BUF_END (&v850ice_input_buf[ sizeof(v850ice_input_buf)])
127 static volatile cyg_uint8 *v850ice_input_ptr_put = v850ice_input_buf;
128 static volatile cyg_uint8 *v850ice_input_ptr_get = v850ice_input_buf;
129 static volatile cyg_uint8 v850ice_input_buf_bytes_used = 0;
130
131 __externC void hal_v850_ice_output_break(void);
132
133 static void
134 hal_v850_ice_indicate_output(void)
135 {
136     HAL_BREAKPOINT(hal_v850_ice_output_break);
137 }
138
139 // Actually write character
140 void
141 cyg_hal_plf_diag_ice_putc(void* __ch_data, cyg_uint8 c)
142 {
143     CYGARC_HAL_SAVE_GP();
144
145     // Send character
146     *v850ice_output_end++ = c;
147
148     if (c == '\n' ||
149         v850ice_output_end == OUTPUT_BUF_END) {
150         hal_v850_ice_indicate_output();
151         v850ice_output_end = v850ice_output_buf;
152     }
153
154     CYGARC_HAL_RESTORE_GP();
155 }
156
157 static cyg_bool
158 cyg_hal_plf_diag_ice_getc_nonblock(void* __ch_data, cyg_uint8* ch)
159 {
160     if ( v850ice_input_buf_bytes_used == 0 )
161         return false; // buffer empty
162
163     *ch = *v850ice_input_ptr_get++;
164     if ( v850ice_input_ptr_get == INPUT_BUF_END ) {
165         v850ice_input_ptr_get = v850ice_input_buf;
166     }
167
168     v850ice_input_buf_bytes_used--;
169
170     return true;
171 }
172
173 cyg_uint8
174 cyg_hal_plf_diag_ice_getc(void* __ch_data)
175 {
176     cyg_uint8 ch;
177     CYGARC_HAL_SAVE_GP();
178
179     while(!cyg_hal_plf_diag_ice_getc_nonblock(__ch_data, &ch));
180
181     CYGARC_HAL_RESTORE_GP();
182     return ch;
183 }
184
185 static cyg_bool
186 cyg_hal_plf_diag_ice_receive_char(cyg_uint8 ch)
187 {
188      /* buffer full? */
189     if ( v850ice_input_buf_bytes_used == sizeof(v850ice_input_buf) )
190         return false;
191
192     *v850ice_input_ptr_put++ = ch;
193     
194     if ( v850ice_input_ptr_put == INPUT_BUF_END ) {
195         v850ice_input_ptr_put = v850ice_input_buf;
196     }
197     return true;
198 }
199
200 static void
201 cyg_hal_plf_diag_ice_write(void* __ch_data, const cyg_uint8* __buf, 
202                            cyg_uint32 __len)
203 {
204     CYGARC_HAL_SAVE_GP();
205
206 #define MIN(__x, __y) ((__x) < (__y) ? (__x) : (__y))
207
208     while(__len > 0) {
209         int copylen = MIN(__len,
210                           (cyg_uint32) (OUTPUT_BUF_END - v850ice_output_end));
211
212         my_memcpy( (void *)v850ice_output_buf, __buf, copylen );
213         __len -= copylen;
214         v850ice_output_end += copylen;
215         hal_v850_ice_indicate_output();
216         v850ice_output_end = v850ice_output_buf;
217     }
218             
219     CYGARC_HAL_RESTORE_GP();
220 }
221
222 static void
223 cyg_hal_plf_diag_ice_read(void* __ch_data, cyg_uint8* __buf, cyg_uint32 __len)
224 {
225     CYGARC_HAL_SAVE_GP();
226
227     while(__len-- > 0)
228         *__buf++ = cyg_hal_plf_diag_ice_getc(__ch_data);
229
230     CYGARC_HAL_RESTORE_GP();
231 }
232
233 static cyg_int32 msec_timeout = 1000;
234
235 cyg_bool
236 cyg_hal_plf_diag_ice_getc_timeout(void* __ch_data, cyg_uint8* ch)
237 {
238     int delay_count = msec_timeout * 10; // delay in .1 ms steps
239     cyg_bool res;
240     CYGARC_HAL_SAVE_GP();
241
242     for(;;) {
243         res = cyg_hal_plf_diag_ice_getc_nonblock(__ch_data, ch);
244         if (res || 0 == delay_count--)
245             break;
246         
247         CYGACC_CALL_IF_DELAY_US(100);
248     }
249
250     CYGARC_HAL_RESTORE_GP();
251     return res;
252 }
253
254 static int
255 cyg_hal_plf_diag_ice_control(void *__ch_data, __comm_control_cmd_t __func, ...)
256 {
257     static int irq_state = 0;
258     int ret = 0;
259     CYGARC_HAL_SAVE_GP();
260
261     switch (__func) {
262     case __COMMCTL_IRQ_ENABLE:
263         irq_state = 1;
264         break;
265     case __COMMCTL_IRQ_DISABLE:
266         ret = irq_state;
267         irq_state = 0;
268         break;
269     case __COMMCTL_DBG_ISR_VECTOR:
270         ret = 0;
271         break;
272     case __COMMCTL_SET_TIMEOUT:
273     {
274         va_list ap;
275
276         va_start(ap, __func);
277
278         ret = msec_timeout;
279         msec_timeout = va_arg(ap, cyg_uint32);
280
281         va_end(ap);
282     }        
283     default:
284         break;
285     }
286     CYGARC_HAL_RESTORE_GP();
287     return ret;
288 }
289
290 static int
291 cyg_hal_plf_diag_ice_isr(void *__ch_data, int* __ctrlc, 
292                          CYG_ADDRWORD __vector, CYG_ADDRWORD __data)
293 {
294     CYGARC_HAL_SAVE_GP();
295     *__ctrlc = 0;
296     CYGARC_HAL_RESTORE_GP();
297     return 0;
298 }
299
300 __externC void
301 cyg_hal_plf_ice_diag_init()
302 {
303     hal_virtual_comm_table_t* comm;
304     int cur = CYGACC_CALL_IF_SET_CONSOLE_COMM(CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT);
305
306     // Init channels
307     ICE_SYSCALL_INFO_DIAGOUTPC     = (int)&hal_v850_ice_output_break;
308     ICE_SYSCALL_INFO_DIAGOUTBUF    = (int)&v850ice_output_buf[0];
309     ICE_SYSCALL_INFO_DIAGOUTBUFEND = (int)&v850ice_output_end;
310
311     // Setup procs in the vector table
312
313     // Set channel 1
314     CYGACC_CALL_IF_SET_CONSOLE_COMM(1);
315     comm = CYGACC_CALL_IF_CONSOLE_PROCS();
316     CYGACC_COMM_IF_CH_DATA_SET(*comm, 0);
317     CYGACC_COMM_IF_WRITE_SET(*comm, cyg_hal_plf_diag_ice_write);
318     CYGACC_COMM_IF_READ_SET(*comm, cyg_hal_plf_diag_ice_read);
319     CYGACC_COMM_IF_PUTC_SET(*comm, cyg_hal_plf_diag_ice_putc);
320     CYGACC_COMM_IF_GETC_SET(*comm, cyg_hal_plf_diag_ice_getc);
321     CYGACC_COMM_IF_CONTROL_SET(*comm, cyg_hal_plf_diag_ice_control);
322     CYGACC_COMM_IF_DBG_ISR_SET(*comm, cyg_hal_plf_diag_ice_isr);
323     CYGACC_COMM_IF_GETC_TIMEOUT_SET(*comm, cyg_hal_plf_diag_ice_getc_timeout);
324     
325     // Restore original console
326     CYGACC_CALL_IF_SET_CONSOLE_COMM(cur);
327 }
328
329 #endif // ifdef CYGDBG_HAL_V85X_V850_ICE_DIAG
330
331
332 /* ----------------------------------------------------------------------- */
333 /* Support for debugging via ICE */
334
335 #define ICE_STACK_SIZE 1024/sizeof(int)
336 static int ice_stack[ICE_STACK_SIZE]; // ints so as to ensure alignment
337 static int ice_iobuf[128];
338
339 static void
340 hal_v85x_ice_syscall_end(void)
341 {
342     for (;;);
343 }
344
345 static void
346 hal_v85x_ice_syscall(void)
347 {
348     int code, len;
349     code = ice_iobuf[0];
350     len = ice_iobuf[1];
351     switch (code) {
352     case V850ICE_SYSCALL_GET_THREADNEXT:
353         {
354             int ret;
355             threadref currthread, nextthread;
356             int thread_id;
357
358             /* Unmarshall thread ref */
359             my_memcpy( &currthread, &ice_iobuf[2], 8 );
360 #if ICEDEBUG
361             diag_printf("*NEXTTHREAD* currthread=%08x,%08x\n",
362                         *(int *)&currthread[0],
363                         *(int *)(((char *)&currthread[0])+4));
364 #endif
365             // null threadref?
366             if ((ice_iobuf[2] == 0) &&
367                 (ice_iobuf[3] == 0)) {
368 #if ICEDEBUG
369                 diag_printf("null threadref\n");
370 #endif
371                 ret = dbg_threadlist( 1, NULL, &nextthread );
372             } else {
373 #if ICEDEBUG
374                 diag_printf("non-null threadref\n");
375 #endif
376                 ret = dbg_threadlist( 0, &currthread, &nextthread );
377             }
378 #if ICEDEBUG
379             diag_printf("*NEXTTHREAD* nextthread=%08x,%08x\n",
380                         *(int *)&nextthread[0],
381                         *(int *)(((char *)&nextthread[0])+4));
382 #endif
383             if (ret) { // if valid thread found
384                 thread_id = dbg_thread_id( &nextthread );
385                 /* Returns 0 on error */
386                 if (thread_id != 0) {
387                     ice_iobuf[1] = thread_id;
388                     my_memcpy( &ice_iobuf[2], nextthread, 8 );
389                     
390                     // set return data size to 12
391                     ice_iobuf[0] = 12;
392 #if ICEDEBUG
393                     {
394                         int i;
395                         for (i=0; i<3; i++)
396                             diag_printf("%x, ", ice_iobuf[i]);
397                         diag_printf("\n");
398                     }
399 #endif
400                 } else {
401                     ret = 0;
402                 }
403             } 
404             if (!ret) {
405                 // set to null
406                 my_memset( &ice_iobuf[1], 0, 12 );
407             }
408         }
409         break;
410     case V850ICE_SYSCALL_GET_THREADREGS:
411         {
412             int ret;
413             threadref thread;
414
415             /* Unmarshall thread ref */
416             my_memcpy( &thread, &ice_iobuf[2], 8 );
417 #if ICEDEBUG
418             diag_printf("*GTHREADREGS* thread=%08x,%08x\n", *(int *)&thread[0],
419                         *(int *)(((char *)&thread[0])+4));
420 #endif
421             ret = dbg_getthreadreg( &thread, NUMREGS, &ice_iobuf[1]);
422             if (ret)
423                 ice_iobuf[0] = NUMREGS * 4;
424             else
425                 ice_iobuf[0] = 0;
426                                     
427         }
428         break;
429     case V850ICE_SYSCALL_SET_THREADREGS:
430         {
431             int ret;
432             threadref thread;
433
434             /* Unmarshall thread ref */
435             my_memcpy( &thread, &ice_iobuf[2], 8 );
436 #if ICEDEBUG
437             diag_printf("*STHREADREGS* thread=%08x,%08x\n", *(int *)&thread[0],
438                         *(int *)(((char *)&thread[0])+4));
439 #endif
440             ret = dbg_setthreadreg( &thread, NUMREGS, &ice_iobuf[4]);
441             if (ret)
442                 ice_iobuf[0] = 1;
443             else
444                 ice_iobuf[0] = 0;
445         }
446         break;
447     case V850ICE_SYSCALL_GET_CURRTHREAD:
448         {
449             int ret, thread_id;
450             threadref thread;
451
452             ret = dbg_currthread( &thread );
453 #if ICEDEBUG
454             diag_printf("*CURRTHREAD* thread=%08x,%08x\n", *(int *)&thread[0],
455                         *(int *)(((char *)&thread[0])+4));
456 #endif
457             
458             if (ret) {
459                 thread_id = dbg_thread_id( &thread );
460                 /* Returns 0 on error */
461                 if (thread_id != 0) {
462                     ice_iobuf[1] = thread_id;
463                     my_memcpy( &ice_iobuf[2], thread, 8 );
464                 }
465                 else {
466                     ret = 0;
467                 }
468             }
469             if (ret)
470                 ice_iobuf[0] = 12;
471             else
472                 ice_iobuf[0] = 0;
473         } 
474         break;
475     case V850ICE_SYSCALL_GET_THREADINFO:
476         {
477             int ret;
478             threadref thread;
479             struct cygmon_thread_debug_info info;
480             char *s=(char *)&ice_iobuf[1], *p;
481
482             /* Unmarshall thread ref */
483             my_memcpy( &thread, &ice_iobuf[2], 8 );
484 #if ICEDEBUG
485             diag_printf("*INFO* thread=%08x,%08x\n", *(int *)&thread[0],
486                         *(int *)(((char *)&thread[0])+4));
487 #endif
488
489             ret = dbg_threadinfo( &thread, &info );
490             if (ret) {
491                 if (info.thread_display) {
492                     my_memcpy (s, "State: ", 7);
493                     s += 7;
494                     p = info.thread_display;
495                     while (*p) {
496                         *s++ = *p++;
497                     }
498                 }
499
500                 if (info.unique_thread_name && info.unique_thread_name[0]) {
501                     my_memcpy (s, ", Name: ", 8);
502                     s += 8;
503                     p = info.unique_thread_name;
504                     while (*p) {
505                         *s++ = *p++;
506                     }
507                 }
508
509                 if (info.more_display) {
510                     my_memcpy (s, ", ", 2);
511                     s += 2;
512                     p = info.more_display;
513                     while (*p) {
514                         *s++ = *p++;
515                     }
516                 }
517
518             }
519             *s++ = '\0';
520             if (ret)
521                 ice_iobuf[0] = s - (char *)&ice_iobuf[1];
522             else
523                 ice_iobuf[0] = 0;
524         }
525         break;
526     case V850ICE_SYSCALL_CONSOLE_INPUT:
527         {
528 #ifdef CYGDBG_HAL_V85X_V850_ICE_DIAG    
529             int len = ice_iobuf[0];
530             int i;
531
532             for (i=1; i <= len; i++) {
533                 if (false == cyg_hal_plf_diag_ice_receive_char(ice_iobuf[i]))
534                     break;
535             }
536             ice_iobuf[0] = i-1;
537 #else
538             ice_iobuf[0] = 0;
539 #endif
540         }
541         break;
542     default:
543         // set return data size to 0
544         ice_iobuf[0] = 0;
545         break;
546     }
547     hal_v85x_ice_syscall_end();
548 }
549
550 class Cyg_dummy_ice_syscall_init_class {
551 public:
552     Cyg_dummy_ice_syscall_init_class() {
553
554         const int valid_string = 0x45434956; // "VICE"
555
556         ICE_SYSCALL_INFO_STARTPC = (int)&hal_v85x_ice_syscall;
557         ICE_SYSCALL_INFO_ENDPC = (int)&hal_v85x_ice_syscall_end;
558         // top of stack, less 4 ints for parameter flushback area as per ABI
559         ICE_SYSCALL_INFO_STACK = (int)&ice_stack[ICE_STACK_SIZE-4];
560         ICE_SYSCALL_INFO_IOBUF = (int)&ice_iobuf[0];
561
562         HAL_REORDER_BARRIER();
563
564         // Leave validation string to last
565         ICE_SYSCALL_INFO_VALIDATOR = valid_string;
566     }
567 };
568
569 static Cyg_dummy_ice_syscall_init_class dummy_syscall_class;
570
571 #endif // ifdef CYGDBG_HAL_V850_ICE
572
573 // EOF v850_ice.cxx