]> git.karo-electronics.de Git - karo-tx-redboot.git/blob - packages/hal/mips/upd985xx/v2_0/src/hal_diag.c
Initial revision
[karo-tx-redboot.git] / packages / hal / mips / upd985xx / v2_0 / src / hal_diag.c
1 /*=============================================================================
2 //
3 //      hal_diag.c
4 //
5 //      HAL diagnostic output code
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):   hmt, nickg
44 // Contributors:        nickg
45 // Date:        2001-05-25
46 // Purpose:     HAL diagnostic output
47 // Description: Implementations of HAL diagnostic output support.
48 //
49 //####DESCRIPTIONEND####
50 //
51 //===========================================================================*/
52
53 #include <pkgconf/hal.h>
54
55 #include <cyg/infra/cyg_type.h>         // base types
56 #include <cyg/infra/cyg_trac.h>         // tracing macros
57 #include <cyg/infra/cyg_ass.h>          // assertion macros
58
59 #include <cyg/hal/hal_arch.h>           // which includes var_arch => UART.
60 #include <cyg/hal/hal_diag.h>
61 #include <cyg/hal/hal_intr.h>
62 #include <cyg/hal/hal_io.h>
63 #include <cyg/hal/drv_api.h>
64 #include <cyg/hal/hal_if.h>             // interface API
65 #include <cyg/hal/hal_misc.h>           // Helper functions
66
67 /*---------------------------------------------------------------------------*/
68 //#define CYG_KERNEL_DIAG_GDB
69
70 #if defined(CYGSEM_HAL_USE_ROM_MONITOR_GDB_stubs)
71
72 #define CYG_KERNEL_DIAG_GDB
73
74 #endif
75
76 /*---------------------------------------------------------------------------*/
77 static inline
78 void hal_uart_setbaud( int baud )
79 {
80     // now set the baud rate
81     *UARTLCR |= UARTLCR_DLAB;
82     *UARTDLM = UARTDLM_VAL( baud );
83     *UARTDLL = UARTDLL_VAL( baud );
84     *UARTLCR &=~UARTLCR_DLAB;
85 }
86
87 void hal_uart_init(void)
88 {
89     // Ensure that we use the internal clock
90     *S_GMR &=~S_GMR_UCSEL;
91
92     *UARTFCR = UARTFCR_16550_MODE;
93     *UARTLCR = UARTLCR_8N1;
94     *UARTIER = UARTIER_ERBFI;           // rx interrupts enabled for CTRL-C
95
96     hal_uart_setbaud( CYGHWR_HAL_MIPS_UPD985XX_DIAG_BAUD );
97 }
98
99 void hal_uart_write_char(char c)
100 {
101     while ( 0 == (UARTLSR_THRE & *UARTLSR) )
102         /* do nothing */ ;
103
104     *UARTTHR = (unsigned int)c;
105
106     // Ensure that this write does not provoke a spurious interrupt.
107     HAL_INTERRUPT_ACKNOWLEDGE( CYGHWR_HAL_GDB_PORT_VECTOR );
108 }
109
110 void hal_uart_read_char(char *c)
111 {
112     while ( 0 == (UARTLSR_DR & *UARTLSR) )
113         /* do nothing */ ;
114
115     *c = (char)*UARTRBR;
116
117     // Ensure that this read does not provoke a spurious interrupt.
118     HAL_INTERRUPT_ACKNOWLEDGE( CYGHWR_HAL_GDB_PORT_VECTOR );
119 }
120
121 int hal_uart_read_char_nonblock(char *c)
122 {
123     if ( 0 == (UARTLSR_DR & *UARTLSR) )
124         return 0;
125
126     *c = (char)*UARTRBR;
127
128     // Ensure that this read does not provoke a spurious interrupt.
129     HAL_INTERRUPT_ACKNOWLEDGE( CYGHWR_HAL_GDB_PORT_VECTOR );
130
131     return 1;
132 }
133
134
135 /*---------------------------------------------------------------------------*/
136
137 #ifdef CYGSEM_HAL_VIRTUAL_VECTOR_DIAG
138
139 #include <cyg/hal/hal_if.h>
140
141 // This is lame, duplicating all these wrappers with slightly different details.
142 // All this should be in hal_if.c
143 static void
144 cyg_hal_plf_serial_putc(void* __ch_data, cyg_uint8 c)
145 {
146     CYGARC_HAL_SAVE_GP();
147     hal_uart_write_char( (char)c );
148     CYGARC_HAL_RESTORE_GP();
149 }
150
151 static cyg_uint8
152 cyg_hal_plf_serial_getc(void* __ch_data)
153 {
154     cyg_uint8 result;
155     CYGARC_HAL_SAVE_GP();
156     hal_uart_read_char( (char *)&result );
157     CYGARC_HAL_RESTORE_GP();
158     return result;
159 }
160
161 static int
162 cyg_hal_plf_serial_getc_nonblock(void* __ch_data, cyg_uint8 *pc)
163 {
164     return hal_uart_read_char_nonblock( (char *)pc );
165 }
166
167 static void
168 cyg_hal_plf_serial_write(void* __ch_data, const cyg_uint8* __buf, 
169                          cyg_uint32 __len)
170 {
171     CYGARC_HAL_SAVE_GP();
172
173     while(__len-- > 0)
174         cyg_hal_plf_serial_putc(__ch_data, *__buf++);
175
176     CYGARC_HAL_RESTORE_GP();
177 }
178
179 static void
180 cyg_hal_plf_serial_read(void* __ch_data, cyg_uint8* __buf, cyg_uint32 __len)
181 {
182     CYGARC_HAL_SAVE_GP();
183
184     while(__len-- > 0)
185         *__buf++ = cyg_hal_plf_serial_getc(__ch_data);
186
187     CYGARC_HAL_RESTORE_GP();
188 }
189
190 static int chan__msec_timeout = 0;
191 static int chan__irq_state = 0;
192 static int chan__baud_rate = CYGHWR_HAL_MIPS_UPD985XX_DIAG_BAUD;
193
194 cyg_bool
195 cyg_hal_plf_serial_getc_timeout(void* __ch_data, cyg_uint8* ch)
196 {
197     int delay_count;
198     cyg_bool res;
199     CYGARC_HAL_SAVE_GP();
200
201     delay_count = chan__msec_timeout * 10; // delay in .1 ms steps
202
203     for(;;) {
204         res = cyg_hal_plf_serial_getc_nonblock(__ch_data, ch);
205         if (res || 0 >= delay_count--)
206             break;
207         
208         CYGACC_CALL_IF_DELAY_US(100);
209     }
210
211     CYGARC_HAL_RESTORE_GP();
212     return res;
213 }
214
215 static int
216 cyg_hal_plf_serial_control(void *__ch_data, __comm_control_cmd_t __func, ...)
217 {
218     int ret = -1;
219     va_list ap;
220
221     CYGARC_HAL_SAVE_GP();
222     va_start(ap, __func);
223
224     switch (__func) {
225     case __COMMCTL_GETBAUD:
226         ret = chan__baud_rate;
227         break;
228     case __COMMCTL_SETBAUD:
229         ret = 0;
230         chan__baud_rate = va_arg(ap, cyg_int32);
231         hal_uart_setbaud( chan__baud_rate );
232         break;
233     case __COMMCTL_IRQ_ENABLE:
234         ret = chan__irq_state;
235         chan__irq_state = 1;
236         HAL_INTERRUPT_UNMASK( CYGHWR_HAL_GDB_PORT_VECTOR );
237         break;
238     case __COMMCTL_IRQ_DISABLE:
239         ret = chan__irq_state;
240         chan__irq_state = 0;
241         HAL_INTERRUPT_MASK( CYGHWR_HAL_GDB_PORT_VECTOR );
242         break;
243     case __COMMCTL_DBG_ISR_VECTOR:
244         ret = CYGHWR_HAL_GDB_PORT_VECTOR;
245         break;
246     case __COMMCTL_SET_TIMEOUT:
247         ret = chan__msec_timeout;
248         chan__msec_timeout = va_arg(ap, cyg_uint32);
249         break;
250     default:
251         break;
252     }
253     va_end(ap);
254     CYGARC_HAL_RESTORE_GP();
255     return ret;
256 }
257
258 static int
259 cyg_hal_plf_serial_isr(void *__ch_data, int* __ctrlc, 
260                        CYG_ADDRWORD __vector, CYG_ADDRWORD __data)
261 {
262     int ret = 0;
263     char c;
264
265     *__ctrlc = 0;
266
267     if ( hal_uart_read_char_nonblock( &c ) ) {
268         if ( cyg_hal_is_break( &c , 1 ) )
269             *__ctrlc = 1;
270         ret = CYG_ISR_HANDLED;
271     }
272
273     return ret;
274 }
275
276 static void
277 cyg_hal_plf_serial_init(void)
278 {
279     hal_virtual_comm_table_t* comm;
280     int cur = CYGACC_CALL_IF_SET_CONSOLE_COMM(CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT);
281
282     // Init channels
283     CYGACC_CALL_IF_SET_CONSOLE_COMM(0);
284     comm = CYGACC_CALL_IF_CONSOLE_PROCS();
285     CYGACC_COMM_IF_CH_DATA_SET(*comm, comm);
286     CYGACC_COMM_IF_WRITE_SET(*comm, cyg_hal_plf_serial_write);
287     CYGACC_COMM_IF_READ_SET(*comm, cyg_hal_plf_serial_read);
288     CYGACC_COMM_IF_PUTC_SET(*comm, cyg_hal_plf_serial_putc);
289     CYGACC_COMM_IF_GETC_SET(*comm, cyg_hal_plf_serial_getc);
290     CYGACC_COMM_IF_CONTROL_SET(*comm, cyg_hal_plf_serial_control);
291     CYGACC_COMM_IF_DBG_ISR_SET(*comm, cyg_hal_plf_serial_isr);
292     CYGACC_COMM_IF_GETC_TIMEOUT_SET(*comm, cyg_hal_plf_serial_getc_timeout);
293      
294     // Restore original console
295     CYGACC_CALL_IF_SET_CONSOLE_COMM(cur);
296 }
297
298 void
299 cyg_hal_plf_comms_init(void)
300 {
301     static int initialized = 0;
302
303     if (initialized)
304         return;
305
306     initialized = 1;
307
308     hal_uart_init();
309     cyg_hal_plf_serial_init();
310 }
311
312 #endif // CYGSEM_HAL_VIRTUAL_VECTOR_DIAG
313
314 // ------------------------------------------------------------------------
315
316 void hal_diag_init(void)
317 {
318     hal_uart_init();
319 }
320
321 void hal_diag_read_char(char *c)
322 {
323     hal_uart_read_char(c);
324 }
325
326 extern cyg_bool cyg_hal_is_break(char *buf, int size);
327 extern void cyg_hal_user_break(CYG_ADDRWORD *regs);
328
329 void hal_diag_write_char(char c)
330 {
331 #ifdef CYG_KERNEL_DIAG_GDB    
332     static char line[100];
333     static int pos = 0;
334
335     // No need to send CRs
336     if( c == '\r' ) return;
337
338     line[pos++] = c;
339
340     if( c == '\n' || pos == sizeof(line) )
341     {
342
343         // Disable interrupts. This prevents GDB trying to interrupt us
344         // while we are in the middle of sending a packet. The serial
345         // receive interrupt will be seen when we re-enable interrupts
346         // later.
347         CYG_INTERRUPT_STATE oldstate;
348         HAL_DISABLE_INTERRUPTS(oldstate);
349         
350         while(1)
351         {
352             static char hex[] = "0123456789ABCDEF";
353             cyg_uint8 csum = 0;
354             int i;
355             char c1;
356         
357             hal_uart_write_char('$');
358             hal_uart_write_char('O');
359             csum += 'O';
360             for( i = 0; i < pos; i++ )
361             {
362                 char ch = line[i];
363                 char h = hex[(ch>>4)&0xF];
364                 char l = hex[ch&0xF];
365                 hal_uart_write_char(h);
366                 hal_uart_write_char(l);
367                 csum += h;
368                 csum += l;
369             }
370             hal_uart_write_char('#');
371             hal_uart_write_char(hex[(csum>>4)&0xF]);
372             hal_uart_write_char(hex[csum&0xF]);
373
374             hal_uart_read_char( &c1 );
375
376             if( c1 == '+' ) break;
377
378             if( cyg_hal_is_break( &c1 , 1 ) )
379                 cyg_hal_user_break( NULL );    
380
381         }
382         
383         pos = 0;
384
385         // Disabling the interrupts for an extended period of time
386         // can provoke a spurious interrupt.
387
388         // Ensure that this write does not provoke a spurious interrupt.
389         HAL_INTERRUPT_ACKNOWLEDGE( CYGHWR_HAL_GDB_PORT_VECTOR );
390
391         // And re-enable interrupts
392         HAL_RESTORE_INTERRUPTS( oldstate );
393         
394     }
395 #else
396     hal_uart_write_char(c);
397 #endif    
398 }
399
400 /*---------------------------------------------------------------------------*/
401 /* End of hal_diag.c */