]> git.kernelconcepts.de Git - karo-tx-redboot.git/blob - packages/hal/arm/xscale/triton270/v2_0/src/hal_diag.c
RedBoot TX53 Release 2012-02-15
[karo-tx-redboot.git] / packages / hal / arm / xscale / triton270 / 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):   msalter
44 // Contributors:msalter
45 // Date:        2000-10-10
46 // Purpose:     HAL diagnostic output
47 // Description: Implementations of HAL diagnostic output support.
48 //
49 //####DESCRIPTIONEND####
50 //
51 //===========================================================================*/
52
53 #include <string.h>
54 #include <pkgconf/hal.h>
55 #include <pkgconf/system.h>
56 #include CYGBLD_HAL_PLATFORM_H
57
58 #include <cyg/infra/cyg_type.h>         // base types
59 #include <cyg/infra/cyg_trac.h>         // tracing macros
60 #include <cyg/infra/cyg_ass.h>          // assertion macros
61
62 #include <cyg/hal/hal_arch.h>           // basic machine info
63 #include <cyg/hal/hal_intr.h>           // interrupt macros
64 #include <cyg/hal/hal_io.h>             // IO macros
65 #include <cyg/hal/hal_if.h>             // calling interface API
66 #include <cyg/hal/hal_misc.h>           // helper functions
67 #include <cyg/hal/hal_diag.h>
68 #include <cyg/hal/hal_triton270.h>      // Hardware definitions
69 #include <cyg/hal/drv_api.h>            // cyg_drv_interrupt_acknowledge
70
71 #define SIO_IER_ERDAI SIO_IER_RAVIE
72
73 #if defined(CYGSEM_HAL_VIRTUAL_VECTOR_DIAG) || defined(CYGPRI_HAL_IMPLEMENTS_IF_SERVICES)
74 static void cyg_hal_plf_serial_init(void);
75
76 void resetSRAM(void)
77 {
78         memset((void *)0x0a000000, 0, 1024 * 1024);
79 }
80
81 void cyg_hal_plf_comms_init(void)
82 {
83         static int initialized = 0;
84
85         if (initialized) {
86                 return;
87         }
88         initialized = 1;
89
90         cyg_hal_plf_serial_init();
91
92         //        cyg_hal_plf_lcd_init();
93         resetSRAM();
94 }
95 #endif // CYGSEM_HAL_VIRTUAL_VECTOR_DIAG || CYGPRI_HAL_IMPLEMENTS_IF_SERVICES
96
97 //=============================================================================
98 // Serial driver
99 //=============================================================================
100
101 //-----------------------------------------------------------------------------
102 // There are three serial ports.
103 #define CYG_DEV_SERIAL_BASE_FF    0x40100000 
104 #define CYG_DEV_SERIAL_BASE_BT    0x40200000 
105 #define CYG_DEV_SERIAL_BASE_STD   0x40700000
106
107 //-----------------------------------------------------------------------------
108
109 // Based on Based on 14.7456 MHz clock
110 struct baud_config {
111         cyg_int32 baud_rate;
112         cyg_uint8 msb;
113         cyg_uint8 lsb;
114 };
115
116 struct baud_config baud_conf[] = {
117         {9600,   0x00, 0x60},
118         {19200,  0x00, 0x30},
119         {38400,  0x00, 0x18},
120         {57600,  0x00, 0x10},
121         {115200, 0x00, 0x08}};
122
123 // Default baud rate is 115200
124 // Based on 14.7456 MHz clock
125 #if CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL_BAUD==9600
126 #define CYG_DEV_SERIAL_BAUD_MSB        0x00
127 #define CYG_DEV_SERIAL_BAUD_LSB        0x60
128 #endif
129 #if CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL_BAUD==19200
130 #define CYG_DEV_SERIAL_BAUD_MSB        0x00
131 #define CYG_DEV_SERIAL_BAUD_LSB        0x30
132 #endif
133 #if CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL_BAUD==38400
134 #define CYG_DEV_SERIAL_BAUD_MSB        0x00
135 #define CYG_DEV_SERIAL_BAUD_LSB        0x18
136 #endif
137 #if CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL_BAUD==57600
138 #define CYG_DEV_SERIAL_BAUD_MSB        0x00
139 #define CYG_DEV_SERIAL_BAUD_LSB        0x10
140 #endif
141 #if CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL_BAUD==115200
142 #define CYG_DEV_SERIAL_BAUD_MSB        0x00
143 #define CYG_DEV_SERIAL_BAUD_LSB        0x08
144 #endif
145
146 #ifndef CYG_DEV_SERIAL_BAUD_MSB
147 #error Missing/incorrect serial baud rate defined - CDL error?
148 #endif
149
150 //-----------------------------------------------------------------------------
151 // Define the serial registers. The Cogent board is equipped with a 16552
152 // serial chip.
153 #define CYG_DEV_SERIAL_RBR   0x00 // receiver buffer register, read, dlab = 0
154 #define CYG_DEV_SERIAL_THR   0x00 // transmitter holding register, write, dlab = 0
155 #define CYG_DEV_SERIAL_DLL   0x00 // divisor latch (LS), read/write, dlab = 1
156 #define CYG_DEV_SERIAL_IER   0x04 // interrupt enable register, read/write, dlab = 0
157 #define CYG_DEV_SERIAL_DLM   0x04 // divisor latch (MS), read/write, dlab = 1
158 #define CYG_DEV_SERIAL_IIR   0x08 // interrupt identification register, read, dlab = 0
159 #define CYG_DEV_SERIAL_FCR   0x08 // fifo control register, write, dlab = 0
160 #define CYG_DEV_SERIAL_LCR   0x0c // line control register, write
161 #define CYG_DEV_SERIAL_MCR   0x10 // modem control register, write
162 #define CYG_DEV_SERIAL_LSR   0x14 // line status register, read
163 #define CYG_DEV_SERIAL_MSR   0x18 // modem status register, read
164 #define CYG_DEV_SERIAL_SPR   0x1c // scratch pad register
165 #define CYG_DEV_SERIAL_ISR   0x20 // slow infrared select register (ISR), read/write
166
167 // The interrupt enable register bits.
168 #define SIO_IER_RAVIE           0x01            // enable received data available irq
169 #define SIO_IER_TIE             0x02            // enable transmit data request interrupt
170 #define SIO_IER_RLSE            0x04            // enable receiver line status irq
171 #define SIO_IER_MIE             0x08            // enable modem status interrupt
172 #define SIO_IER_RTOIE           0x10            // enable Rx timeout interrupt
173 #define SIO_IER_NRZE            0x20            // enable NRZ coding
174 #define SIO_IER_UUE             0x40            // enable the UART unit
175 #define SIO_IER_DMAE            0x80            // enable DMA requests
176
177 // The interrupt identification register bits.
178 #define SIO_IIR_IP              0x01            // 0 if interrupt pending
179 #define SIO_IIR_ID_MASK         0xff            // mask for interrupt ID bits
180 #define ISR_Tx                  0x02
181 #define ISR_Rx                  0x04
182
183 // The line status register bits.
184 #define SIO_LSR_DR              0x01            // data ready
185 #define SIO_LSR_OE              0x02            // overrun error
186 #define SIO_LSR_PE              0x04            // parity error
187 #define SIO_LSR_FE              0x08            // framing error
188 #define SIO_LSR_BI              0x10            // break interrupt
189 #define SIO_LSR_THRE            0x20            // transmitter holding register empty
190 #define SIO_LSR_TEMT            0x40            // transmitter holding and Tx shift registers empty
191 #define SIO_LSR_ERR             0x80            // any error condition (FIFOE)
192
193 // The modem status register bits.
194 #define SIO_MSR_DCTS            0x01            // delta clear to send
195 #define SIO_MSR_DDSR            0x02            // delta data set ready
196 #define SIO_MSR_TERI            0x04            // trailing edge ring indicator
197 #define SIO_MSR_DDCD            0x08            // delta data carrier detect
198 #define SIO_MSR_CTS             0x10            // clear to send
199 #define SIO_MSR_DSR             0x20            // data set ready
200 #define SIO_MSR_RI              0x40            // ring indicator
201 #define SIO_MSR_DCD             0x80            // data carrier detect
202
203 // The line control register bits.
204 #define SIO_LCR_WLS0            0x01            // word length select bit 0
205 #define SIO_LCR_WLS1            0x02            // word length select bit 1
206 #define SIO_LCR_STB             0x04            // number of stop bits
207 #define SIO_LCR_PEN             0x08            // parity enable
208 #define SIO_LCR_EPS             0x10            // even parity select
209 #define SIO_LCR_SP              0x20            // stick parity
210 #define SIO_LCR_SB              0x40            // set break
211 #define SIO_LCR_DLAB            0x80            // divisor latch access bit
212
213 // The FIFO control register
214 #define SIO_FCR_FCR0            0x01            // enable xmit and rcvr fifos
215 #define SIO_FCR_FCR1            0x02            // clear RCVR FIFO
216 #define SIO_FCR_FCR2            0x04            // clear XMIT FIFO
217 #define SIO_FCR_ITL0            0x40            // Interrupt trigger level (ITL) bit 0
218 #define SIO_FCR_ITL1            0x80            // Interrupt trigger level (ITL) bit 1
219 #define SIO_FCR_ITL_1BYTE       0x00            // 1 byte triggers interrupt
220
221 //-----------------------------------------------------------------------------
222 typedef struct {
223         cyg_uint8* base;
224         cyg_int32 msec_timeout;
225         int isr_vector;
226         cyg_int32 baud_rate;
227 } channel_data_t;
228
229 //-----------------------------------------------------------------------------
230
231 static int set_baud(channel_data_t *chan)
232 {
233         cyg_uint8* base = chan->base;
234         cyg_uint8 i;
235
236         for (i=0; i<(sizeof(baud_conf)/sizeof(baud_conf[0])); i++) {
237                 if (chan->baud_rate == baud_conf[i].baud_rate) {
238                         cyg_uint8 lcr;
239                         HAL_READ_UINT8(base + CYG_DEV_SERIAL_LCR, lcr);
240                         HAL_WRITE_UINT8(base + CYG_DEV_SERIAL_LCR, lcr|SIO_LCR_DLAB);
241                         HAL_WRITE_UINT8(base + CYG_DEV_SERIAL_DLL, baud_conf[i].lsb);
242                         HAL_WRITE_UINT8(base + CYG_DEV_SERIAL_DLM, baud_conf[i].msb);
243                         HAL_WRITE_UINT8(base + CYG_DEV_SERIAL_LCR, lcr);
244                         return 1;
245                 }
246         }
247         return -1;
248 }
249
250 static void init_serial_channel(channel_data_t* chan)
251 {
252         cyg_uint8* base = chan->base;
253
254         // 8-1-no parity.
255         HAL_WRITE_UINT8(base+CYG_DEV_SERIAL_LCR, SIO_LCR_WLS0 | SIO_LCR_WLS1);
256
257         chan->baud_rate = CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL_BAUD;
258         set_baud(chan);
259
260         //  Enable & clear FIFOs
261         //  set Interrupt Trigger Level to be 1 byte
262         HAL_WRITE_UINT8(base+CYG_DEV_SERIAL_FCR, (SIO_FCR_FCR0 | SIO_FCR_FCR1 | SIO_FCR_FCR2)); // Enable & clear FIFO
263
264         //      Configure NRZ, disable DMA requests and enable UART
265         HAL_WRITE_UINT8(base+CYG_DEV_SERIAL_IER, SIO_IER_UUE);
266 }
267
268 static cyg_bool cyg_hal_plf_serial_getc_nonblock(void *__ch_data, cyg_uint8 *ch)
269 {
270         cyg_uint8* base = ((channel_data_t*)__ch_data)->base;
271         cyg_uint8 lsr;
272
273         HAL_READ_UINT8(base+CYG_DEV_SERIAL_LSR, lsr);
274         if ((lsr & SIO_LSR_DR) == 0)
275                 return false;
276
277         HAL_READ_UINT8(base+CYG_DEV_SERIAL_RBR, *ch);
278
279         return true;
280 }
281
282 cyg_uint8 cyg_hal_plf_serial_getc(void* __ch_data)
283 {
284         cyg_uint8 ch;
285         CYGARC_HAL_SAVE_GP();
286
287         while (!cyg_hal_plf_serial_getc_nonblock(__ch_data, &ch));
288
289         CYGARC_HAL_RESTORE_GP();
290         return ch;
291 }
292
293 void cyg_hal_plf_serial_putc(void* __ch_data, cyg_uint8 c)
294 {
295         cyg_uint8* base = ((channel_data_t*)__ch_data)->base;
296         cyg_uint8 lsr;
297         CYGARC_HAL_SAVE_GP();
298
299         do {
300                 HAL_READ_UINT8(base+CYG_DEV_SERIAL_LSR, lsr);
301         } while ((lsr & SIO_LSR_THRE) == 0);
302
303         HAL_WRITE_UINT8(base+CYG_DEV_SERIAL_THR, c);
304         // Hang around until the character has been safely sent.
305         do {
306                 HAL_READ_UINT8(base+CYG_DEV_SERIAL_LSR, lsr);
307         } while ((lsr & SIO_LSR_THRE) == 0);
308
309         CYGARC_HAL_RESTORE_GP();
310 }
311
312 #if defined(CYGSEM_HAL_VIRTUAL_VECTOR_DIAG) || defined(CYGPRI_HAL_IMPLEMENTS_IF_SERVICES)
313 static channel_data_t channels[3] = {
314         { (cyg_uint8*)CYG_DEV_SERIAL_BASE_FF, 1000, CYGNUM_HAL_INTERRUPT_FFUART, 38400 },
315         { (cyg_uint8*)CYG_DEV_SERIAL_BASE_BT, 1000, CYGNUM_HAL_INTERRUPT_BTUART, 38400 },
316         { (cyg_uint8*)CYG_DEV_SERIAL_BASE_STD, 1000, CYGNUM_HAL_INTERRUPT_STUART, 38400 },
317 };
318
319 static void cyg_hal_plf_serial_write(void* __ch_data, const cyg_uint8* __buf, cyg_uint32 __len)
320 {
321         CYGARC_HAL_SAVE_GP();
322
323         while (__len-- > 0) {
324                 cyg_hal_plf_serial_putc(__ch_data, *__buf++);
325         }
326         CYGARC_HAL_RESTORE_GP();
327 }
328
329 static void cyg_hal_plf_serial_read(void* __ch_data, cyg_uint8* __buf, cyg_uint32 __len)
330 {
331         CYGARC_HAL_SAVE_GP();
332
333         while (__len-- > 0) {
334                 *__buf++ = cyg_hal_plf_serial_getc(__ch_data);
335         }
336         CYGARC_HAL_RESTORE_GP();
337 }
338
339 cyg_bool cyg_hal_plf_serial_getc_timeout(void* __ch_data, cyg_uint8* ch)
340 {
341         int delay_count;
342         channel_data_t* chan = __ch_data;
343         cyg_bool res;
344         CYGARC_HAL_SAVE_GP();
345
346         delay_count = chan->msec_timeout * 10; // delay in .1 ms steps
347         for(;;) {
348                 res = cyg_hal_plf_serial_getc_nonblock(__ch_data, ch);
349                 if (res || 0 == delay_count--)
350                         break;
351
352                 CYGACC_CALL_IF_DELAY_US(100);
353         }
354
355         CYGARC_HAL_RESTORE_GP();
356         return res;
357 }
358
359 static int cyg_hal_plf_serial_control(void *__ch_data, __comm_control_cmd_t __func, ...)
360 {
361         static int irq_state = 0;
362         channel_data_t* chan = __ch_data;
363         cyg_uint8 ier;
364         int ret = 0;
365         CYGARC_HAL_SAVE_GP();
366
367         switch (__func) {
368         case __COMMCTL_IRQ_ENABLE:
369                 HAL_INTERRUPT_UNMASK(chan->isr_vector);
370                 HAL_INTERRUPT_SET_LEVEL(chan->isr_vector, 1);
371                 HAL_READ_UINT8(chan->base+CYG_DEV_SERIAL_IER, ier);
372                 ier |= SIO_IER_ERDAI;
373                 HAL_WRITE_UINT8(chan->base+CYG_DEV_SERIAL_IER, ier);
374                 irq_state = 1;
375                 break;
376         case __COMMCTL_IRQ_DISABLE:
377                 ret = irq_state;
378                 irq_state = 0;
379                 HAL_INTERRUPT_MASK(chan->isr_vector);
380                 HAL_READ_UINT8(chan->base+CYG_DEV_SERIAL_IER, ier);
381                 ier &= ~SIO_IER_ERDAI;
382                 HAL_WRITE_UINT8(chan->base+CYG_DEV_SERIAL_IER, ier);
383                 break;
384         case __COMMCTL_DBG_ISR_VECTOR:
385                 ret = chan->isr_vector;
386                 break;
387         case __COMMCTL_SET_TIMEOUT:
388                 {
389                         va_list ap;
390
391                         va_start(ap, __func);
392
393                         ret = chan->msec_timeout;
394                         chan->msec_timeout = va_arg(ap, cyg_uint32);
395
396                         va_end(ap);
397                 }  
398         case __COMMCTL_GETBAUD:
399                 ret = chan->baud_rate;
400                 break;
401         case __COMMCTL_SETBAUD:
402                 {
403                         va_list ap;
404                         va_start(ap, __func);
405                         chan->baud_rate = va_arg(ap, cyg_int32);
406                         va_end(ap);
407                         ret = set_baud(chan);
408                         break;
409                 }
410         default:
411                 break;
412         }
413         CYGARC_HAL_RESTORE_GP();
414         return ret;
415 }
416
417 static int cyg_hal_plf_serial_isr(void *__ch_data, int* __ctrlc, 
418                                   CYG_ADDRWORD __vector, CYG_ADDRWORD __data)
419 {
420         channel_data_t* chan = __ch_data;
421         cyg_uint8 _iir;
422         int res = 0;
423         CYGARC_HAL_SAVE_GP();
424
425         HAL_READ_UINT8(chan->base+CYG_DEV_SERIAL_IIR, _iir);
426         _iir &= SIO_IIR_ID_MASK;
427
428         *__ctrlc = 0;
429         if (ISR_Rx == _iir) {
430                 cyg_uint8 c, lsr;
431                 HAL_READ_UINT8(chan->base + CYG_DEV_SERIAL_LSR, lsr);
432                 if (lsr & SIO_LSR_DR) {
433                         HAL_READ_UINT8(chan->base + CYG_DEV_SERIAL_RBR, c);
434
435                         if (cyg_hal_is_break(&c, 1)) {
436                                 *__ctrlc = 1;
437                         }
438                 }
439
440                 // Acknowledge the interrupt
441                 HAL_INTERRUPT_ACKNOWLEDGE(chan->isr_vector);
442                 res = CYG_ISR_HANDLED;
443         }
444
445         CYGARC_HAL_RESTORE_GP();
446         return res;
447 }
448
449 static void cyg_hal_plf_serial_init(void)
450 {
451         hal_virtual_comm_table_t* comm;
452         int cur = CYGACC_CALL_IF_SET_CONSOLE_COMM(CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT);
453
454         // Disable interrupts.
455         HAL_INTERRUPT_MASK(channels[0].isr_vector);
456         HAL_INTERRUPT_MASK(channels[1].isr_vector);
457         HAL_INTERRUPT_MASK(channels[2].isr_vector);
458
459         // Init channels
460         init_serial_channel((channel_data_t *)&channels[0]);
461         init_serial_channel((channel_data_t *)&channels[1]);
462         init_serial_channel((channel_data_t *)&channels[2]);
463
464         // Setup procs in the vector table
465         // Set channel 0
466         CYGACC_CALL_IF_SET_CONSOLE_COMM(0);
467         comm = CYGACC_CALL_IF_CONSOLE_PROCS();
468         CYGACC_COMM_IF_CH_DATA_SET(*comm, &channels[0]);
469         CYGACC_COMM_IF_WRITE_SET(*comm, cyg_hal_plf_serial_write);
470         CYGACC_COMM_IF_READ_SET(*comm, cyg_hal_plf_serial_read);
471         CYGACC_COMM_IF_PUTC_SET(*comm, cyg_hal_plf_serial_putc);
472         CYGACC_COMM_IF_GETC_SET(*comm, cyg_hal_plf_serial_getc);
473         CYGACC_COMM_IF_CONTROL_SET(*comm, cyg_hal_plf_serial_control);
474         CYGACC_COMM_IF_DBG_ISR_SET(*comm, cyg_hal_plf_serial_isr);
475         CYGACC_COMM_IF_GETC_TIMEOUT_SET(*comm, cyg_hal_plf_serial_getc_timeout);
476
477         // Set channel 1
478         CYGACC_CALL_IF_SET_CONSOLE_COMM(1);
479         comm = CYGACC_CALL_IF_CONSOLE_PROCS();
480         CYGACC_COMM_IF_CH_DATA_SET(*comm, &channels[1]);
481         CYGACC_COMM_IF_WRITE_SET(*comm, cyg_hal_plf_serial_write);
482         CYGACC_COMM_IF_READ_SET(*comm, cyg_hal_plf_serial_read);
483         CYGACC_COMM_IF_PUTC_SET(*comm, cyg_hal_plf_serial_putc);
484         CYGACC_COMM_IF_GETC_SET(*comm, cyg_hal_plf_serial_getc);
485         CYGACC_COMM_IF_CONTROL_SET(*comm, cyg_hal_plf_serial_control);
486         CYGACC_COMM_IF_DBG_ISR_SET(*comm, cyg_hal_plf_serial_isr);
487         CYGACC_COMM_IF_GETC_TIMEOUT_SET(*comm, cyg_hal_plf_serial_getc_timeout);
488
489         // Set channel 2
490         CYGACC_CALL_IF_SET_CONSOLE_COMM(2);
491         comm = CYGACC_CALL_IF_CONSOLE_PROCS();
492         CYGACC_COMM_IF_CH_DATA_SET(*comm, &channels[2]);
493         CYGACC_COMM_IF_WRITE_SET(*comm, cyg_hal_plf_serial_write);
494         CYGACC_COMM_IF_READ_SET(*comm, cyg_hal_plf_serial_read);
495         CYGACC_COMM_IF_PUTC_SET(*comm, cyg_hal_plf_serial_putc);
496         CYGACC_COMM_IF_GETC_SET(*comm, cyg_hal_plf_serial_getc);
497         CYGACC_COMM_IF_CONTROL_SET(*comm, cyg_hal_plf_serial_control);
498         CYGACC_COMM_IF_DBG_ISR_SET(*comm, cyg_hal_plf_serial_isr);
499         CYGACC_COMM_IF_GETC_TIMEOUT_SET(*comm, cyg_hal_plf_serial_getc_timeout);
500
501         // Restore original console
502         CYGACC_CALL_IF_SET_CONSOLE_COMM(cur);
503 }
504 #endif // CYGSEM_HAL_VIRTUAL_VECTOR_DIAG || CYGPRI_HAL_IMPLEMENTS_IF_SERVICES
505
506 //=============================================================================
507 // Compatibility with older stubs
508 //=============================================================================
509
510 #ifndef CYGSEM_HAL_VIRTUAL_VECTOR_DIAG
511 #ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS
512 #include <cyg/hal/drv_api.h>
513 #include <cyg/hal/hal_stub.h>           // cyg_hal_gdb_interrupt
514 #endif
515
516 // Assumption: all diagnostic output must be GDB packetized unless this is a ROM (i.e.
517 // totally stand-alone) system.
518
519 #if defined(CYG_HAL_STARTUP_ROM) || defined(CYGDBG_HAL_DIAG_DISABLE_GDB_PROTOCOL)
520 #define HAL_DIAG_USES_HARDWARE
521 #endif
522
523 /*---------------------------------------------------------------------------*/
524 #if CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL==0
525 // This is the base address of the FF-channel
526 #define CYG_DEV_SERIAL_BASE     CYG_DEV_SERIAL_BASE_FF
527 #define CYG_DEV_SERIAL_INT      CYGNUM_HAL_INTERRUPT_FFUART
528 #elif CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL==1
529 // This is the base address of the BT-channel
530 #define CYG_DEV_SERIAL_BASE     CYG_DEV_SERIAL_BASE_BT
531 #define CYG_DEV_SERIAL_INT      CYGNUM_HAL_INTERRUPT_BTUART
532 elif CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL==2
533 // This is the base address of the STD-channel
534 #define CYG_DEV_SERIAL_BASE     CYG_DEV_SERIAL_BASE_STD
535 #define CYG_DEV_SERIAL_INT      CYGNUM_HAL_INTERRUPT_STUART
536 #elif !defined(CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL)
537 #error CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL undefined
538 #else
539 #error Bad CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL definition
540 #endif
541
542 static channel_data_t ser_channel = { (cyg_uint8*)CYG_DEV_SERIAL_BASE, 0, 0};
543
544 #ifdef HAL_DIAG_USES_HARDWARE
545 void hal_diag_init(void)
546 {
547         static int init = 0;
548         char *msg = "\n\rARM eCos\n\r";
549
550         if (init++) return;
551
552         init_serial_channel(&ser_channel);
553
554         while (*msg) hal_diag_write_char(*msg++);
555 }
556
557 #ifdef DEBUG_DIAG
558 #if defined(CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS)
559 #define DIAG_BUFSIZE 32
560 #else
561 #define DIAG_BUFSIZE 2048
562 #endif
563 static char diag_buffer[DIAG_BUFSIZE];
564 static int diag_bp = 0;
565 #endif
566
567 void hal_diag_write_char(char c)
568 {
569         cyg_uint8 lsr;
570
571         hal_diag_init();
572
573         cyg_hal_plf_serial_putc(&ser_channel, c);
574
575 #ifdef DEBUG_DIAG
576         diag_buffer[diag_bp++] = c;
577         if (diag_bp == DIAG_BUFSIZE) {
578                 while (1) ;
579                 diag_bp = 0;
580         }
581 #endif
582 }
583
584 void hal_diag_read_char(char *c)
585 {
586         *c = cyg_hal_plf_serial_getc(&ser_channel);
587 }
588
589 #else // HAL_DIAG relies on GDB
590
591 // Initialize diag port - assume GDB channel is already set up
592 void hal_diag_init(void)
593 {
594         if (0) init_serial_channel(&ser_channel); // avoid warning
595 }
596
597 // Actually send character down the wire
598 static void hal_diag_write_char_serial(char c)
599 {
600         cyg_hal_plf_serial_putc(&ser_channel, c);
601 }
602
603 static bool hal_diag_read_serial(char *c)
604 {
605         long timeout = 1000000000;  // A long time...
606
607         while (!cyg_hal_plf_serial_getc_nonblock(&ser_channel, c)) {
608                 if (0 == --timeout) return false;
609         }
610         return true;
611 }
612
613 void hal_diag_read_char(char *c)
614 {
615         while (!hal_diag_read_serial(c));
616 }
617
618 void hal_diag_write_char(char c)
619 {
620         static char line[100];
621         static int pos = 0;
622
623         // No need to send CRs
624         if (c == '\r') return;
625
626         line[pos++] = c;
627
628         if (c == '\n' || pos == sizeof(line)) {
629                 CYG_INTERRUPT_STATE old;
630
631                 // Disable interrupts. This prevents GDB trying to interrupt us
632                 // while we are in the middle of sending a packet. The serial
633                 // receive interrupt will be seen when we re-enable interrupts
634                 // later.
635
636 #ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS
637                 CYG_HAL_GDB_ENTER_CRITICAL_IO_REGION(old);
638 #else
639                 HAL_DISABLE_INTERRUPTS(old);
640 #endif
641                 while (1) {
642                         static char hex[] = "0123456789ABCDEF";
643                         cyg_uint8 csum = 0;
644                         int i;
645                         char c1;
646
647                         hal_diag_write_char_serial('$');
648                         hal_diag_write_char_serial('O');
649                         csum += 'O';
650                         for( i = 0; i < pos; i++ ) {
651                                 char ch = line[i];
652                                 char h = hex[(ch>>4)&0xF];
653                                 char l = hex[ch&0xF];
654                                 hal_diag_write_char_serial(h);
655                                 hal_diag_write_char_serial(l);
656                                 csum += h;
657                                 csum += l;
658                         }
659                         hal_diag_write_char_serial('#');
660                         hal_diag_write_char_serial(hex[(csum>>4)&0xF]);
661                         hal_diag_write_char_serial(hex[csum&0xF]);
662
663                         // Wait for the ACK character '+' from GDB here and handle
664                         // receiving a ^C instead.  This is the reason for this clause
665                         // being a loop.
666                         if (!hal_diag_read_serial(&c1)) {
667                                 continue;   // No response - try sending packet again
668                         }
669                         if (c1 == '+') {
670                                 break;          // a good acknowledge
671                         }
672 #ifdef CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT
673                         cyg_drv_interrupt_acknowledge(CYG_DEV_SERIAL_INT);
674                         if (c1 == 3) {
675                                 // Ctrl-C: breakpoint.
676                                 cyg_hal_gdb_interrupt(__builtin_return_address(0));
677                                 break;
678                         }
679 #endif
680                         // otherwise, loop round again
681                 }
682                 pos = 0;
683
684                 // And re-enable interrupts
685 #ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS
686                 CYG_HAL_GDB_LEAVE_CRITICAL_IO_REGION(old);
687 #else
688                 HAL_RESTORE_INTERRUPTS(old);
689 #endif
690         }
691 }
692 #endif
693
694 #endif // CYGSEM_HAL_VIRTUAL_VECTOR_DIAG
695
696 /*---------------------------------------------------------------------------*/
697 /* End of hal_diag.c */