]> git.kernelconcepts.de Git - karo-tx-redboot.git/blob - packages/hal/arm/integrator/v2_0/src/hal_diag.c
Initial revision
[karo-tx-redboot.git] / packages / hal / arm / integrator / 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):     David A Rusling
44 // Contributors:  Philippe Robin
45 // Date:          November 7, 2000
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 #include <pkgconf/hal_arm_integrator.h> // board specifics
55
56 #include <cyg/infra/cyg_type.h>         // base types
57 #include <cyg/infra/cyg_trac.h>         // tracing macros
58 #include <cyg/infra/cyg_ass.h>          // assertion macros
59
60 #include <cyg/hal/hal_arch.h>           // basic machine info
61 #include <cyg/hal/hal_intr.h>           // interrupt macros
62 #include <cyg/hal/hal_io.h>             // IO macros
63 #include <cyg/hal/hal_if.h>             // interface API
64 #include <cyg/hal/hal_misc.h>           // Helper functions
65 #include <cyg/hal/hal_diag.h>
66 #include <cyg/hal/drv_api.h>
67 #include <cyg/hal/hal_integrator.h>        // Hardware definitions
68
69
70 /*---------------------------------------------------------------------------*/
71 void abcd(void);
72
73 /* Codes for ASCI characters 32-127 */
74 unsigned int char_codes[] = {
75     0x0000, 0x2400, 0x0044, 0x7E12, 0x25DA, 0x4848, 0x2580, 0x0400,
76     0x0072, 0x001E, 0x7F80, 0x2580, 0x4000, 0x0180, 0x0000, 0x4800,
77     0x007E, 0x080C, 0x01B6, 0x011E, 0x01CC, 0x01DA, 0x01FA, 0x2802,
78     0x01FE, 0x01CE, 0x2400, 0x4400, 0x1800, 0x0190, 0x4200, 0x01A6,
79     0x217E, 0x01EE, 0x251E, 0x0072, 0x241E, 0x00F2, 0x00E2, 0x017A,
80     0x01EC, 0x2412, 0x001C, 0x18E0, 0x0070, 0x0A6C, 0x126C, 0x007E,
81     0x01E6, 0x107E, 0x11E6, 0x01DA, 0x2402, 0x007C, 0x4860, 0x506C,
82     0x5A00, 0x2A00, 0x4812, 0x0072, 0x1200, 0x001E, 0x0046, 0x0010,
83     0x0200, 0x01BE, 0x01F8, 0x01B0, 0x01BC, 0x01F6, 0x2980, 0x01DE,
84     0x01E8, 0x2000, 0x001C, 0x3500, 0x2400, 0x21A8, 0x01A8, 0x01B8,
85     0x01E6, 0x01CE, 0x01A0, 0x01DA, 0x00F0, 0x0038, 0x4020, 0x5028,
86     0x5A00, 0x030C, 0x4190, 0x2480, 0x2400, 0x2500, 0x0640, 0x0000
87 };
88
89 /* Codes for hexadecimal characters */
90 unsigned int hex_codes[] = {
91     0x007E, 0x080C, 0x01B6, 0x011E, 0x01CC, 0x01DA, 0x01FA, 0x2802,
92     0x01FE, 0x01CE, 0x01EE, 0x01F8, 0x0072, 0x01BC, 0x00F2, 0x00E2
93 };
94
95 void hal_diag_alpha_led_char(char c1, char c2);
96
97
98 // AMBA uart access macros
99 #define GET_STATUS(p)           (IO_READ((p) + AMBA_UARTFR))
100 #define GET_CHAR(p)             (IO_READ((p) + AMBA_UARTDR))
101 #define PUT_CHAR(p, c)          (IO_WRITE(((p) + AMBA_UARTDR), (c)))
102 #define IO_READ(p)              ((*(volatile unsigned int *)(p)) & 0xFF)
103 #define IO_WRITE(p, c)          (*(unsigned int *)(p) = (c))
104 #define RX_DATA(s)              (((s) & AMBA_UARTFR_RXFE) == 0)
105 #define TX_READY(s)             (((s) & AMBA_UARTFR_TXFF) == 0)
106 #define TX_EMPTY(p)             ((GET_STATUS(p) & AMBA_UARTFR_TMSK) == 0)
107 #define RX_EMPTY(p)             ((GET_STATUS(p) & AMBA_UARTFR_RXFE) == 0)
108 // Define the serial registers.
109
110 //-----------------------------------------------------------------------------
111 typedef struct {
112     cyg_uint8* base;
113     cyg_int32 msec_timeout;
114     int isr_vector;
115 } channel_data_t;
116
117 //-----------------------------------------------------------------------------
118
119 #if (CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL_BAUD == 9600)
120 #define ARM_INTEGRATOR_BAUD_DIVISOR     ARM_BAUD_9600
121 #elif (CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL_BAUD == 19200)
122 #define ARM_INTEGRATOR_BAUD_DIVISOR     ARM_BAUD_9600
123 #elif (CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL_BAUD == 38400)
124 #define ARM_INTEGRATOR_BAUD_DIVISOR     ARM_BAUD_38400
125 #elif (CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL_BAUD == 57600)
126 #define ARM_INTEGRATOR_BAUD_DIVISOR     ARM_BAUD_57600
127 #elif (CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL_BAUD == 115200)
128 #define ARM_INTEGRATOR_BAUD_DIVISOR     ARM_BAUD_115200
129 #endif
130
131 static void
132 cyg_hal_plf_serial_init_channel(void* __ch_data)
133 {
134     cyg_uint8* base = ((channel_data_t*)__ch_data)->base;
135
136     // first, disable everything
137     IO_WRITE(base + AMBA_UARTCR, 0x0);
138       
139     // Set baud rate CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL_BAUD
140     IO_WRITE(base + AMBA_UARTLCR_M, ((ARM_INTEGRATOR_BAUD_DIVISOR & 0xf00) >> 8));
141     IO_WRITE(base + AMBA_UARTLCR_L, (ARM_INTEGRATOR_BAUD_DIVISOR & 0xff));
142       
143     // ----------v----------v----------v----------v----------
144     // NOTE: MUST BE WRITTEN LAST (AFTER UARTLCR_M & UARTLCR_L)
145     // ----------^----------^----------^----------^----------
146     // set the UART to be 8 bits, 1 stop bit, no parity, fifo enabled
147     IO_WRITE(base + AMBA_UARTLCR_H, (AMBA_UARTLCR_H_WLEN_8 | AMBA_UARTLCR_H_FEN));
148   
149     // finally, enable the uart
150     IO_WRITE(base + AMBA_UARTCR, AMBA_UARTCR_UARTEN);
151
152 }
153
154 void
155 cyg_hal_plf_serial_putc(void *__ch_data, char c)
156 {
157     channel_data_t* chan = (channel_data_t*)__ch_data;
158     cyg_uint8* base = chan->base;
159     cyg_uint32 status;
160     CYGARC_HAL_SAVE_GP();
161
162     do {
163       status = GET_STATUS(base);
164     } while (!TX_READY(status));        // wait until ready
165
166     PUT_CHAR(base, c);
167
168     if (c == '\n') {
169       do {
170         status = GET_STATUS(base);
171       } while (!TX_READY(status));      // wait until ready
172       
173       PUT_CHAR(base, '\r');
174     }
175
176     CYGARC_HAL_RESTORE_GP();
177 }
178
179 static cyg_bool
180 cyg_hal_plf_serial_getc_nonblock(void* __ch_data, cyg_uint8* ch)
181 {
182     cyg_uint8* base = ((channel_data_t*)__ch_data)->base;
183     cyg_uint32 status ;
184     long timeout = 100;  // A long time...
185
186     do {
187       status = GET_STATUS(base);
188       if (--timeout == 0) return false ; 
189     } while (!RX_DATA(status)); // wait until ready
190
191     *ch = GET_CHAR(base);
192
193     return true;
194 }
195
196 cyg_uint8
197 cyg_hal_plf_serial_getc(void* __ch_data)
198 {
199     cyg_uint8 ch;
200     CYGARC_HAL_SAVE_GP();
201
202     while(!cyg_hal_plf_serial_getc_nonblock(__ch_data, &ch));
203
204     CYGARC_HAL_RESTORE_GP();
205     return ch;
206 }
207
208 #if defined(CYGSEM_HAL_VIRTUAL_VECTOR_DIAG) \
209     || defined(CYGPRI_HAL_IMPLEMENTS_IF_SERVICES)
210
211 static channel_data_t integrator_ser_channels[2] = {
212     { (cyg_uint8*)0x16000000, 1000, CYGNUM_HAL_INTERRUPT_UARTINT0 },
213     { (cyg_uint8*)0x17000000, 1000, CYGNUM_HAL_INTERRUPT_UARTINT1 }
214 };
215
216 static void
217 cyg_hal_plf_serial_write(void* __ch_data, const cyg_uint8* __buf, 
218                          cyg_uint32 __len)
219 {
220     CYGARC_HAL_SAVE_GP();
221
222     while(__len-- > 0)
223         cyg_hal_plf_serial_putc(__ch_data, *__buf++);
224
225     CYGARC_HAL_RESTORE_GP();
226 }
227
228 static void
229 cyg_hal_plf_serial_read(void* __ch_data, cyg_uint8* __buf, cyg_uint32 __len)
230 {
231     CYGARC_HAL_SAVE_GP();
232
233     while(__len-- > 0)
234         *__buf++ = cyg_hal_plf_serial_getc(__ch_data);
235
236     CYGARC_HAL_RESTORE_GP();
237 }
238
239 cyg_bool
240 cyg_hal_plf_serial_getc_timeout(void* __ch_data, cyg_uint8* ch)
241 {
242     int delay_count;
243     channel_data_t* chan = (channel_data_t*)__ch_data;
244     cyg_bool res;
245     CYGARC_HAL_SAVE_GP();
246
247     delay_count = chan->msec_timeout * 10; // delay in .1 ms steps
248
249     for(;;) {
250         res = cyg_hal_plf_serial_getc_nonblock(__ch_data, ch);
251         if (res || 0 == delay_count--)
252             break;
253         
254         CYGACC_CALL_IF_DELAY_US(100);
255     }
256
257     CYGARC_HAL_RESTORE_GP();
258     return res;
259 }
260
261 static int
262 cyg_hal_plf_serial_control(void *__ch_data, __comm_control_cmd_t __func, ...)
263 {
264     static int irq_state = 0;
265     channel_data_t* chan = (channel_data_t*)__ch_data;
266     int ret = 0;
267     cyg_uint8 status;
268     CYGARC_HAL_SAVE_GP();
269
270     switch (__func) {
271     case __COMMCTL_IRQ_ENABLE:
272         irq_state = 1;
273         // Ensure that only Receive ints are generated.
274         status = IO_READ(chan->base + AMBA_UARTCR);
275
276         status |= (AMBA_UARTCR_RTIE | AMBA_UARTCR_RIE);
277         HAL_WRITE_UINT32(chan->base + AMBA_UARTCR, status);
278
279         HAL_INTERRUPT_UNMASK(chan->isr_vector);
280         break;
281     case __COMMCTL_IRQ_DISABLE:
282         ret = irq_state;
283         irq_state = 0;
284
285         status = IO_READ(chan->base + AMBA_UARTCR);
286         status &= ~(AMBA_UARTCR_RTIE | AMBA_UARTCR_TIE | AMBA_UARTCR_RIE | AMBA_UARTCR_MSIE);
287         HAL_WRITE_UINT32(chan->base + AMBA_UARTCR, status);
288
289         HAL_INTERRUPT_MASK(chan->isr_vector);
290         break;
291     case __COMMCTL_DBG_ISR_VECTOR:
292         ret = chan->isr_vector;
293         break;
294     case __COMMCTL_SET_TIMEOUT:
295     {
296         va_list ap;
297
298         va_start(ap, __func);
299
300         ret = chan->msec_timeout;
301         chan->msec_timeout = va_arg(ap, cyg_uint32);
302
303         va_end(ap);
304     }        
305     default:
306         break;
307     }
308     CYGARC_HAL_RESTORE_GP();
309     return ret;
310 }
311
312 static int
313 cyg_hal_plf_serial_isr(void *__ch_data, int* __ctrlc, 
314                        CYG_ADDRWORD __vector, CYG_ADDRWORD __data)
315 {
316     int res = 0;
317     channel_data_t* chan = (channel_data_t*)__ch_data;
318     char c;
319     cyg_uint32 status;
320     CYGARC_HAL_SAVE_GP();
321
322     cyg_drv_interrupt_acknowledge(chan->isr_vector);
323
324     *__ctrlc = 0;
325     status = GET_STATUS(chan->base);
326
327     if ( RX_DATA(status) ) {
328         c = GET_CHAR(chan->base);
329
330         if( cyg_hal_is_break( &c , 1 ) )
331             *__ctrlc = 1;
332
333         res = CYG_ISR_HANDLED;
334     }
335
336     CYGARC_HAL_RESTORE_GP();
337     return res;
338 }
339
340 static void
341 cyg_hal_plf_serial_init(void)
342 {
343     hal_virtual_comm_table_t* comm;
344     int cur = CYGACC_CALL_IF_SET_CONSOLE_COMM(CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT);
345
346     // Disable interrupts.
347     HAL_INTERRUPT_MASK(integrator_ser_channels[0].isr_vector);
348     HAL_INTERRUPT_MASK(integrator_ser_channels[1].isr_vector);
349
350     // Init channels
351     cyg_hal_plf_serial_init_channel(&integrator_ser_channels[0]);
352     cyg_hal_plf_serial_init_channel(&integrator_ser_channels[1]);
353
354     // Setup procs in the vector table
355
356     // Set channel 0
357     CYGACC_CALL_IF_SET_CONSOLE_COMM(0);
358     comm = CYGACC_CALL_IF_CONSOLE_PROCS();
359     CYGACC_COMM_IF_CH_DATA_SET(*comm, &integrator_ser_channels[0]);
360     CYGACC_COMM_IF_WRITE_SET(*comm, cyg_hal_plf_serial_write);
361     CYGACC_COMM_IF_READ_SET(*comm, cyg_hal_plf_serial_read);
362     CYGACC_COMM_IF_PUTC_SET(*comm, cyg_hal_plf_serial_putc);
363     CYGACC_COMM_IF_GETC_SET(*comm, cyg_hal_plf_serial_getc);
364     CYGACC_COMM_IF_CONTROL_SET(*comm, cyg_hal_plf_serial_control);
365     CYGACC_COMM_IF_DBG_ISR_SET(*comm, cyg_hal_plf_serial_isr);
366     CYGACC_COMM_IF_GETC_TIMEOUT_SET(*comm, cyg_hal_plf_serial_getc_timeout);
367
368     // Set channel 1
369     CYGACC_CALL_IF_SET_CONSOLE_COMM(1);
370     comm = CYGACC_CALL_IF_CONSOLE_PROCS();
371     CYGACC_COMM_IF_CH_DATA_SET(*comm, &integrator_ser_channels[1]);
372     CYGACC_COMM_IF_WRITE_SET(*comm, cyg_hal_plf_serial_write);
373     CYGACC_COMM_IF_READ_SET(*comm, cyg_hal_plf_serial_read);
374     CYGACC_COMM_IF_PUTC_SET(*comm, cyg_hal_plf_serial_putc);
375     CYGACC_COMM_IF_GETC_SET(*comm, cyg_hal_plf_serial_getc);
376     CYGACC_COMM_IF_CONTROL_SET(*comm, cyg_hal_plf_serial_control);
377     CYGACC_COMM_IF_DBG_ISR_SET(*comm, cyg_hal_plf_serial_isr);
378     CYGACC_COMM_IF_GETC_TIMEOUT_SET(*comm, cyg_hal_plf_serial_getc_timeout);
379
380     // Restore original console
381     CYGACC_CALL_IF_SET_CONSOLE_COMM(cur);
382
383     
384 }
385
386 void
387 cyg_hal_plf_comms_init(void)
388 {
389     static int initialized = 0;
390
391     if (initialized)
392         return;
393
394     initialized = 1;
395
396     cyg_hal_plf_serial_init();
397
398 #ifdef CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT2
399     cyg_hal_gdb_isr_attach();   // FIXME, hack to get CTRLC working
400 #endif 
401 }
402
403 #endif // CYGSEM_HAL_VIRTUAL_VECTOR_DIAG || CYGPRI_HAL_IMPLEMENTS_IF_SERVICES
404
405 /*---------------------------------------------------------------------------*/
406
407 #ifdef CYGHWR_HAL_ARM_INTEGRATOR_DIAG_LEDS
408
409 void
410 hal_diag_led(int n)
411 {
412     volatile unsigned int *leds = (unsigned int *)INTEGRATOR_DBG_LEDS ;
413
414     *leds |= (n & 0xF) ;
415 }
416 void
417 hal_diag_alpha_led(unsigned int val)
418 {
419   volatile unsigned int *led = (unsigned int *)INTEGRATOR_DBG_BASE;
420
421   while (*led & 0x01) ;
422
423   *led = val;
424 }
425
426 void
427 hal_diag_alpha_led_char(char c1, char c2)
428 {
429   volatile unsigned int *led = (unsigned int *)INTEGRATOR_DBG_BASE;
430   unsigned int current;
431
432   current = *led;
433   if (c1) {
434     if (c1 < 32 || c1 > 127) c1=32;
435     if (c1 >= 'a' && c1 < 'z') c1 -= 32;
436
437     current &= ~(0x00007FFE << 14);
438     current |= (char_codes[c1-32] << 14);
439     }
440     
441     if (c2) {
442         if (c2 < 32 || c2 > 127) c2 = 32;
443         if (c2 >= 'a' && c2 <= 'z') c2 -= 32;
444         
445         current &= ~(0x00007FFE);
446         current |= char_codes[c2-32];
447     }
448     
449     hal_diag_alpha_led(current);
450
451 }
452
453 #endif // CYGHWR_HAL_ARM_INTEGRATOR_DIAG_LEDS
454
455 /*---------------------------------------------------------------------------*/
456 /* End of hal_diag.c */