]> git.karo-electronics.de Git - karo-tx-redboot.git/blob - packages/io/serial/v2_0/tests/ser_test_protocol.inl
Initial revision
[karo-tx-redboot.git] / packages / io / serial / v2_0 / tests / ser_test_protocol.inl
1 //==========================================================================
2 //
3 //        ser_test_protocol.c
4 //
5 //        Serial device driver testing protocol
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):     jskov
44 // Contributors:  jskov, gthomas
45 // Date:          1999-03-17
46 // Description:   Protocol implementation used to test eCos serial devices.
47 //                Relies on ser_filter to be present on the host side to
48 //                respond to test requests.
49 // 
50 // To Do:
51 //  o Clean up.
52 //  o Clean up config change magic.
53 //  o Figure out how to handle kernel dependency
54 //    : without kernel, no timeout. Without timeout, no filter auto detection.
55 //
56 //####DESCRIPTIONEND####
57
58 #include <pkgconf/system.h>
59 #include <pkgconf/io.h>
60 #include <pkgconf/io_serial.h>
61
62 #include <cyg/io/io.h>
63 #include <cyg/io/devtab.h>
64 #include <cyg/io/ttyio.h>
65 #include <cyg/infra/diag.h>
66 #include <cyg/infra/cyg_ass.h>
67
68 #include <cyg/hal/hal_intr.h>           // for reclaiming interrupt vector
69
70 //----------------------------------------------------------------------------
71 // Definition of which device to run tests on on various platforms.
72
73 #define NA_MSG "No test device specified"
74
75 // Cleaned up drivers will export the testing parameters via CDL.
76 // When all drivers are changed, replace the TEST_ macros throughout
77 // with the CYGPRI_ equivalents.
78 #ifdef CYGPRI_SER_TEST_CRASH_ID
79 # define TEST_CRASH_ID CYGPRI_SER_TEST_CRASH_ID
80 # define TEST_SER_DEV  CYGPRI_SER_TEST_SER_DEV
81 # define TEST_TTY_DEV  CYGPRI_SER_TEST_TTY_DEV
82 #endif
83
84 // Note that CYGPRI_SER_TEST_OVERRIDE_INT_1 and CYGPRI_SER_TEST_OVERRIDE_INT_2
85 // may also be exported. These identify interrupts that should be reclaimed
86 // from the ROM monitor before the test is started.
87
88 #if defined(CYGPKG_HAL_POWERPC_MBX)                          \
89     && defined(CYGPKG_HAL_QUICC)                 \
90     && defined(CYGPKG_IO_SERIAL_POWERPC_QUICC_SMC)                 \
91     && defined(CYGPKG_IO_SERIAL_POWERPC_QUICC_SMC_SMC1)
92 # define TEST_CRASH_ID "ppcmbx"
93 # define TEST_SER_DEV CYGDAT_IO_SERIAL_POWERPC_QUICC_SMC_SMC1_NAME
94 # if defined(CYGPKG_IO_SERIAL_TTY_TTY1)
95 #  define TEST_TTY_DEV CYGDAT_IO_SERIAL_TTY_TTY1_DEV
96 # endif
97 #endif
98 #if defined(CYGPKG_HAL_MN10300_AM31_STDEVAL1)           \
99     && defined(CYGPKG_IO_SERIAL_MN10300)                \
100     && defined(CYGPKG_IO_SERIAL_MN10300_SERIAL2)
101 # define TEST_CRASH_ID "am31st"
102 # define TEST_SER_DEV CYGDAT_IO_SERIAL_MN10300_SERIAL2_NAME
103 # if defined(CYGPKG_IO_SERIAL_TTY_TTY2)
104 #  define TEST_TTY_DEV CYGDAT_IO_SERIAL_TTY_TTY1_DEV
105 # endif
106 #endif
107 #if defined(CYGPKG_HAL_MN10300_AM33_STB)                \
108     && defined(CYGPKG_IO_SERIAL_MN10300)                \
109     && defined(CYGPKG_IO_SERIAL_MN10300_SERIAL0)
110 # define TEST_CRASH_ID "am33st"
111 # define TEST_SER_DEV CYGDAT_IO_SERIAL_MN10300_SERIAL0_NAME
112 # if defined(CYGPKG_IO_SERIAL_TTY_TTY0)
113 #  define TEST_TTY_DEV CYGDAT_IO_SERIAL_TTY_TTY0_DEV
114 # endif
115 #endif
116
117 // We can't rely on haldiag for ser_filter detection - it may not define
118 // a working character reading function.
119 #ifndef   TEST_SER_DEV
120 # define  SER_NOP_TEST
121 # define  TTY_NOP_TEST
122 # define  TEST_SER_DEV "/dev/null"
123 # define  TEST_TTY_DEV "/dev/null"
124 #else
125 # ifndef  TEST_TTY_DEV
126 #  define TTY_NOP_TEST
127 # define  TEST_TTY_DEV "/dev/null"
128 # endif
129 #endif
130
131 #ifndef TEST_CRASH_ID
132 #define TEST_CRASH_ID "......"
133 #endif
134
135 //----------------------------------------------------------------------------
136 // Crash types
137 // Eventually this will be moved into a separate header file so a script
138 // can read the definitions and use the output formats/codes to analyze
139 // test results. For now we just keep it here...
140
141 // FAILCODE:<tttttt:cccc:[optional data, separated by :]!>
142 //  tttttt: 6 letter target code
143 //  cccc:   crash code (16bit hex value)
144
145 #define TEST_CRASH(__h, __code, __msg, args...)                         \
146     CYG_MACRO_START                                                     \
147     cyg_uint32 __len = 1;                                               \
148     /* Try to flush remaining input */                                  \
149     cyg_thread_delay(50);                                               \
150     cyg_io_get_config(__h, CYG_IO_GET_CONFIG_SERIAL_INPUT_FLUSH,        \
151                       0, &__len);                                       \
152     diag_printf("FAILCODE:<" TEST_CRASH_ID ":%04x:" __code, ## args);   \
153     diag_printf("!>\n");                                                \
154     CYG_FAIL(__msg);                                                    \
155     hang();                                                             \
156     CYG_MACRO_END
157
158 // Target IO
159 #define TEST_CRASH_IO                     0x0000
160 #define TEST_CRASH_IO_READ                "%d",            0x0001
161 #define TEST_CRASH_IO_WRITE               "%d",            0x0002
162 #define TEST_CRASH_IO_DRAIN               "%d",            0x0003
163 #define TEST_CRASH_IO_GET_CFG             "%d",            0x0004
164 #define TEST_CRASH_IO_SET_CFG             "%d",            0x0005
165
166 // Target
167 #define TEST_CRASH_CRC                    0x0010
168 #define TEST_CRASH_CRC_CHAR               "%02x",          0x0011
169 #define TEST_CRASH_CRC_BAD                "%08x:%08x",     0x0012
170 #define TEST_CRASH_CRC_HOST               "",              0x0013
171
172 // Protocol errors
173 #define TEST_CRASH_PROT                   0x1000
174 #define TEST_CRASH_PROT_BIN_MODE          "%d",            0x1080
175 #define TEST_CRASH_PROT_TEXT              "%d",            0x1100
176
177 #define TEST_CRASH_HOST_xx                0xf000
178 #define TEST_CRASH_HOST_TIMEOUT           "%d:%d:%d:%d",      0xf000
179         // command#, read invocation#, expected, actual
180 #define TEST_CRASH_HOST_CRC_BAD           "%d:%08x:%08x:%d:%02x:%02x", 0xf010
181         // command#, expected CRC, actual, index, expected char, actual
182 #define TEST_CRASH_HOST_DUPLEX_BAD        "%d:%d:%02x:%02x",     0xf020
183         // command#, index, expected char, actual
184
185 //----------------------------------------------------------------------------
186 // The data in buffer and the cmd buffer
187 #ifndef IN_BUFFER_SIZE
188 # define IN_BUFFER_SIZE 1024
189 #endif
190 cyg_uint8 in_buffer[IN_BUFFER_SIZE];
191
192 char cmd_buffer[128];
193
194 //----------------------------------------------------------------------------
195 // Some types specific to the testing protocol.
196 typedef enum {
197     MODE_NO_ECHO = 0,
198     MODE_EOP_ECHO,
199     MODE_DUPLEX_ECHO
200 } cyg_mode_t;
201
202 typedef enum {
203     TEST_RETURN_OK = ENOERR,
204     TEST_RETURN_NA
205 } cyg_test_return_t;
206
207 typedef struct ser_cfg {
208     cyg_serial_baud_rate_t    baud_rate;
209     cyg_serial_word_length_t  data_bits;
210     cyg_serial_stop_bits_t    stop_bits;
211     cyg_serial_parity_t       parity;
212     cyg_uint32                flags;
213     // etc...
214 } cyg_ser_cfg_t;
215
216 typedef enum {
217     OPT_SERIAL_DEBUG = 0,
218     OPT_VERBOSE_LEVEL
219 } cyg_option_t;
220
221 typedef enum {
222     _NONE = 0,
223     PROTOCOL_PROGRESS,
224     PROTOCOL_DATA,
225 } cyg_verbosity_level_t;
226
227
228 // A few predifined option macros. Use after test_ping().
229 #define TEST_OPTIONS(__handle, __array) \
230   test_options(__handle, sizeof(__array)/8, __array)
231
232 #define TEST_HOST_DEBUG(__handle)                               \
233     CYG_MACRO_START                                             \
234     cyg_uint32 __options[] = {OPT_SERIAL_DEBUG, 1};             \
235     test_options((__handle), sizeof(__options)/8,               \
236                  __options);                                    \
237     CYG_MACRO_END
238
239 #define TEST_HOST_PROGRESS(__handle)                            \
240     CYG_MACRO_START                                             \
241     cyg_uint32 __options[] =                                    \
242         {OPT_SERIAL_DEBUG, 1,                                   \
243          OPT_VERBOSE_LEVEL, PROTOCOL_PROGRESS};                 \
244     test_options((__handle), sizeof(__options)/8,               \
245                  __options);                                    \
246     CYG_MACRO_END
247
248 #define TEST_HOST_DATA(__handle)                                \
249     CYG_MACRO_START                                             \
250     cyg_uint32 __options[] =                                    \
251         {OPT_SERIAL_DEBUG, 1,                                   \
252          OPT_VERBOSE_LEVEL, PROTOCOL_DATA};                     \
253     test_options((__handle), sizeof(__options)/8,               \
254                  __options);                                    \
255     CYG_MACRO_END
256
257 //----------------------------------------------------------------------------
258 // A few predefined configurations. These must all be valid for any
259 // given target until change_config is behaving correctly.
260 cyg_ser_cfg_t test_configs[] = {
261 #if (0 == CYGINT_IO_SERIAL_TEST_SKIP_9600)
262     { CYGNUM_SERIAL_BAUD_9600, CYGNUM_SERIAL_WORD_LENGTH_8, 
263       CYGNUM_SERIAL_STOP_1, CYGNUM_SERIAL_PARITY_NONE,
264       CYGNUM_SERIAL_FLOW_NONE },
265 #endif
266
267 #if (0 == CYGINT_IO_SERIAL_TEST_SKIP_14400)
268 #if !defined(CYGPKG_HAL_MN10300_AM31) &&    \
269     !defined(CYGPKG_HAL_MN10300_AM33)
270     { CYGNUM_SERIAL_BAUD_14400, CYGNUM_SERIAL_WORD_LENGTH_8, 
271       CYGNUM_SERIAL_STOP_1, CYGNUM_SERIAL_PARITY_NONE,
272       CYGNUM_SERIAL_FLOW_NONE },
273 #endif
274 #endif
275
276     { CYGNUM_SERIAL_BAUD_19200, CYGNUM_SERIAL_WORD_LENGTH_8, 
277       CYGNUM_SERIAL_STOP_1, CYGNUM_SERIAL_PARITY_NONE,
278       CYGNUM_SERIAL_FLOW_NONE },
279
280 #if (0 == CYGINT_IO_SERIAL_TEST_SKIP_38400)
281     { CYGNUM_SERIAL_BAUD_38400, CYGNUM_SERIAL_WORD_LENGTH_8, 
282       CYGNUM_SERIAL_STOP_1, CYGNUM_SERIAL_PARITY_NONE,
283       CYGNUM_SERIAL_FLOW_NONE },
284 #endif
285
286 #if (0 == CYGINT_IO_SERIAL_TEST_SKIP_57600)
287 #if !defined(CYGPKG_HAL_MN10300_AM33)
288     { CYGNUM_SERIAL_BAUD_57600, CYGNUM_SERIAL_WORD_LENGTH_8, 
289       CYGNUM_SERIAL_STOP_1, CYGNUM_SERIAL_PARITY_NONE,
290       CYGNUM_SERIAL_FLOW_NONE },
291 #endif
292 #endif
293
294 #if (0 == CYGINT_IO_SERIAL_TEST_SKIP_115200)
295 #if !defined(CYGPKG_HAL_MN10300_STDEVAL1)
296     { CYGNUM_SERIAL_BAUD_115200, CYGNUM_SERIAL_WORD_LENGTH_8, 
297       CYGNUM_SERIAL_STOP_1, CYGNUM_SERIAL_PARITY_NONE,
298       CYGNUM_SERIAL_FLOW_NONE },
299 #endif
300 #endif
301
302 #if (0 == CYGINT_IO_SERIAL_TEST_SKIP_PARITY_EVEN)
303     // One stop bit, even parity
304     { CYGNUM_SERIAL_BAUD_19200, CYGNUM_SERIAL_WORD_LENGTH_8, 
305       CYGNUM_SERIAL_STOP_1, CYGNUM_SERIAL_PARITY_EVEN,
306       CYGNUM_SERIAL_FLOW_NONE },
307 #endif
308
309 #if (0 == CYGINT_IO_SERIAL_TEST_SKIP_PARITY_EVEN)
310 #if (0 == CYGINT_IO_SERIAL_TEST_SKIP_STOP_2)
311     // Two stop bits, even parity
312     { CYGNUM_SERIAL_BAUD_19200, CYGNUM_SERIAL_WORD_LENGTH_8, 
313       CYGNUM_SERIAL_STOP_2, CYGNUM_SERIAL_PARITY_EVEN,
314       CYGNUM_SERIAL_FLOW_NONE },
315 #endif
316 #endif
317
318 #if (0 == CYGINT_IO_SERIAL_TEST_SKIP_STOP_2)
319     // Two stop bits, no parity
320     { CYGNUM_SERIAL_BAUD_19200, CYGNUM_SERIAL_WORD_LENGTH_8, 
321       CYGNUM_SERIAL_STOP_2, CYGNUM_SERIAL_PARITY_NONE,
322       CYGNUM_SERIAL_FLOW_NONE },
323 #endif
324 };
325
326 //----------------------------------------------------------------------------
327 // Macros to help extract values from the argument string.
328 // Note: This is probably not an ideal solution, but it was easy to make :)
329
330 #define INIT_VALUE(__args)                      \
331     unsigned int v;                             \
332     char *__ptr1, *__ptr2 = (__args)
333
334 #define SET_VALUE(__slot)                       \
335 do {                                            \
336     __ptr1 = index(__ptr2, (int) ':');          \
337     if (__ptr1)                                 \
338         *__ptr1 = 0;                            \
339     v = atoi(__ptr2);                           \
340     __ptr2 = __ptr1+1;                          \
341     (__slot) = v;                               \
342 } while (0)
343
344
345 //----------------------------------------------------------------------------
346 // CRC magic - it's a bit of a hack for now.
347 // FIXME: standard definition?
348 #define ADD_CRC_BYTE(__crc, __c)                \
349     CYG_MACRO_START                             \
350     (__crc) = ((__crc) << 1) ^ (__c);           \
351     CYG_MACRO_END
352
353 // FIXME: Hack to allow easy ASCII transfer.
354 #define FIX_CRC(__crc, __icrc)                  \
355     CYG_MACRO_START                             \
356     __icrc = (int) (__crc);                     \
357     if (__icrc < 0)                             \
358         __icrc = -__icrc;                       \
359     CYG_MACRO_END
360
361 //----------------------------------------------------------------------------
362 // Macros for read/write to serial with error cheking.
363 static volatile cyg_uint32 r_stamp;
364 static volatile int aborted;
365
366 // This routine will be called if the read "times out"
367 static void
368 do_abort(void *handle)
369 {
370     cyg_io_handle_t io_handle = (cyg_io_handle_t)handle;
371     cyg_uint32 len = 1;  // Need something here
372     cyg_io_get_config(io_handle, CYG_IO_GET_CONFIG_SERIAL_ABORT, 0, &len);
373     aborted = 1;
374 }
375 #include "timeout.inl"
376
377 // Read with timeout (__t = timeout in ticks, int* __r = result)
378 #define Tcyg_io_read_timeout(__h, __d, __l, __t, __r)           \
379     CYG_MACRO_START                                             \
380     int __res;                                                  \
381     r_stamp = timeout((__t), do_abort, (__h));                  \
382     __res = cyg_io_read((__h), (__d), (__l));                   \
383     if (ENOERR != __res && -EINTR != __res) {                   \
384         TEST_CRASH(__h, TEST_CRASH_IO_READ,                     \
385                    "cyg_io_read/timeout failed", __res);        \
386     }                                                           \
387     *(__r) = __res;                                             \
388     untimeout(r_stamp);                                         \
389     CYG_MACRO_END
390
391 #define Tcyg_io_read(__h, __d, __l)                     \
392     CYG_MACRO_START                                     \
393     int __res = cyg_io_read((__h), (__d), (__l));       \
394     if (ENOERR != __res) {                              \
395         TEST_CRASH(__h, TEST_CRASH_IO_READ,             \
396                    "cyg_io_read failed", __res);        \
397     }                                                   \
398     CYG_MACRO_END
399
400 #define Tcyg_io_write(__h, __d, __l)                                    \
401     CYG_MACRO_START                                                     \
402     int __res;                                                          \
403     cyg_uint32 __len = 1;                                               \
404     __res = cyg_io_write((__h), (__d), (__l));                          \
405     if (ENOERR != __res) {                                              \
406         TEST_CRASH(__h, TEST_CRASH_IO_WRITE,                            \
407                    "cyg_io_write failed", __res);                       \
408     }                                                                   \
409     __res = cyg_io_get_config((__h),                                    \
410                               CYG_IO_GET_CONFIG_SERIAL_OUTPUT_DRAIN,    \
411                               0, &__len);                               \
412     if (ENOERR != __res) {                                              \
413         TEST_CRASH(__h, TEST_CRASH_IO_DRAIN,                            \
414                    "DRAIN failed", __res);                              \
415     }                                                                   \
416     CYG_MACRO_END
417
418
419 //----------------------------------------------------------------------------
420 // Some libc like functions that are handy to have around.
421 static int
422 strlen(const char *c)
423 {
424     int l = 0;
425     while (*c++) l++;
426     return l;
427 }
428
429 static char*
430 strcpy(char* dest, const char* src)
431 {
432     char c;
433     while ((c = *src++)) {
434         *dest++ = c;
435     }
436     *dest = c;
437
438     return dest;
439 }
440
441 static char*
442 itoa(char* dest, int v)
443 {
444     char b[16];
445     char* p = &b[16];
446
447     *--p = 0;
448     if (v) {
449         while (v){
450             *--p = (v % 10) + '0';
451             v = v / 10;
452         }
453     } else
454         *--p = '0';
455
456     return strcpy(dest, p);
457 }
458
459 #define min(_a, _b) ((_a) < (_b)) ? (_a) : (_b)
460
461 void
462 hang(void)
463 {
464     while (1);
465 }
466
467 //-----------------------------------------------------------------------------
468 // Configuration changing function.
469 //
470 // First change to the new config and back again to determine if the driver
471 // can handle the config.
472 // If not, return error.
473 //
474 // Then query the host for its capability to use the config:
475 // Format out:
476 //  "@CONFIG:<baud rate code>:<#data bits>:<#stop bits>:<parity on/off>:<flow control code>!"
477 // Format in:
478 //  OK/ER
479 //
480 // On ER, return error.
481 //
482 // On OK, change to the new configuration. Resynchronize with the host:
483 //  Target waits for host to send S(ync) 
484 //     [host will delay at least .1 secs after changing baud rate so the 
485 //      line has time to settle.]
486 //
487 //  When receiving S(ync), target replies OK to the host which then
488 //  acknowledges with D(one).
489 //
490 //  Host can also send R(esync) which means it didn't receieve the OK. If
491 //  so the target resends its S(ync) message.
492 //
493 // If the synchronization has not succeeded within 1 second
494 // (configurable in the protocol), both host and target will revert to
495 // the previous configuration and attempt to synchronize again. If
496 // this fails, this call will hang and the host will consider the test
497 // a failure.
498 //
499 // To Do:
500 //  Host&protocol currently only supports:
501 //   - no/even parity
502 int
503 change_config(cyg_io_handle_t handle, cyg_ser_cfg_t* cfg)
504 {
505     cyg_serial_info_t old_cfg, new_cfg;
506     const char cmd[] = "@CONFIG:";
507     char reply[2];
508     cyg_uint32 msglen;
509     int res;
510     cyg_uint32 len;
511     char *p1;
512
513     // Prepare the command.
514     p1 = &cmd_buffer[0];
515     p1 = strcpy(p1, &cmd[0]);
516     p1 = itoa(p1, cfg->baud_rate);
517     *p1++ = ':';
518     p1 = itoa(p1, cfg->data_bits);
519     *p1++ = ':';
520     p1 = itoa(p1, cfg->stop_bits);
521     *p1++ = ':';
522     p1 = itoa(p1, cfg->parity);
523     *p1++ = ':';
524     p1 = itoa(p1, cfg->flags);
525     *p1++ = '!';
526     *p1 = 0;                            // note: we may append to this later
527
528     // Tell user what we're up to.
529     CYG_TEST_INFO((char *)&cmd_buffer[1]);
530
531     // Change to new config and then back to determine if the driver likes it.
532     len = sizeof(old_cfg);
533     res = cyg_io_get_config(handle, CYG_IO_GET_CONFIG_SERIAL_INFO, 
534                             &old_cfg, &len);
535     res = cyg_io_get_config(handle, CYG_IO_GET_CONFIG_SERIAL_INFO, 
536                             &new_cfg, &len);
537
538     if (res != ENOERR) {
539         TEST_CRASH(handle, TEST_CRASH_IO_GET_CFG, 
540                    "Can't get serial config", res);
541     }
542
543     new_cfg.baud = cfg->baud_rate;
544     new_cfg.word_length = cfg->data_bits;
545     new_cfg.stop = cfg->stop_bits;
546     new_cfg.parity = cfg->parity;
547     new_cfg.flags = cfg->flags;
548
549     res = cyg_io_set_config(handle, CYG_IO_SET_CONFIG_SERIAL_INFO, 
550                             &new_cfg, &len);
551     cyg_thread_delay(10);  // Some chips don't like changes to happen to fast...
552
553     // Driver didn't like it. It will not have changed anything, so it's
554     // safe to return now.
555     if (ENOERR != res) {
556         // Let user know that the config was skipped due to the target.
557         const char txt_tskipped[] = "- skipped by target!";
558         p1 = strcpy(p1, txt_tskipped);
559         *p1 = 0;
560         CYG_TEST_INFO(&cmd_buffer[1]);
561         return res;
562     }
563
564     // Succeeded. Change back to the original config so we can communicate
565     // with the host.
566     res = cyg_io_set_config(handle, CYG_IO_SET_CONFIG_SERIAL_INFO, 
567                             &old_cfg, &len);
568     cyg_thread_delay(10); // Some chips don't like changes to happen to fast...
569
570     if (res != ENOERR) {
571         TEST_CRASH(handle, TEST_CRASH_IO_SET_CFG, 
572                    "Can't set serial config", res);
573     }
574
575     // Send command to host and read host's reply.
576     msglen = strlen(&cmd_buffer[0]);
577     Tcyg_io_write(handle, &cmd_buffer[0], &msglen);
578     msglen = 2;
579     Tcyg_io_read(handle, &reply[0], &msglen);
580
581     // Did host accept configuration?
582     if ('O' != reply[0] || 'K' != reply[1]) {
583         // Let user know that the config was skipped due to the host.
584         const char txt_hskipped[] = "- skipped by host!";
585         p1 = strcpy(p1, txt_hskipped);
586         *p1 = 0;
587         CYG_TEST_INFO(&cmd_buffer[1]);
588         diag_printf("Host didn't accept config (%02x, %02x).\n",
589                     reply[0], reply[1]);
590
591         res = ENOSUPP;
592         return res;
593     }
594
595     // Now change config and wait for host to send us a S(ync)
596     // character.  
597     // Loop until protocol exchange completed. This may hang (as seen
598     // from the host), but only when we get totally lost, in which
599     // case there's not much else to do really. In this case the host
600     // will consider the test a FAIL.
601     len = sizeof(new_cfg);
602     res = cyg_io_set_config(handle, CYG_IO_SET_CONFIG_SERIAL_INFO, 
603                             &new_cfg, &len);
604     cyg_thread_delay(10);  // Some chips don't like changes to happen to fast...
605     if (res != ENOERR) {
606         TEST_CRASH(handle, TEST_CRASH_IO_SET_CFG, 
607                    "Can't set serial config/2", res);
608     }
609
610     {
611         int change_succeeded = 0;
612         int using_old_config = 0;
613         char in_buf[1];
614         cyg_uint32 len;
615         int saw_host_sync;
616
617         for (;;) {
618             aborted = 0;                    // global abort flag
619
620             // FIXME: Timeout time needs to be configurable, and needs to
621             // be sent to the host before getting here. That would allow
622             // changing the timeout by just rebuilding the test - without
623             // changing the host software.
624             saw_host_sync = 0;
625             r_stamp = timeout(100, do_abort, handle);
626             while(!aborted) {
627                 len = 1;
628                 in_buf[0] = 0;
629                 res = cyg_io_read(handle, in_buf, &len);
630                 if (ENOERR != res && -EINTR != res) {
631                     // We may have to reset the driver here if the fail
632                     // was due to a framing or parity error.
633                     break;
634                 }
635                 if ('R' == in_buf[0]) {
636                     // Resync - host didn't see our message. Try again.
637                     saw_host_sync = 0;
638                 } else if ('S' == in_buf[0] && !saw_host_sync) {
639                     // In sync - reply to host if we haven't already
640                     char ok_msg[2] = "OK";
641                     cyg_uint32 ok_len = 2;
642                     Tcyg_io_write(handle, ok_msg, &ok_len);
643                     saw_host_sync = 1;
644                 } else if ('D' == in_buf[0] && saw_host_sync) {
645                     // Done - exchange completed.
646                     change_succeeded = 1;
647                     break;
648                 }
649             }
650             untimeout(r_stamp);
651
652             if (change_succeeded) {
653                 // If we had to revert to the old configuration, return error.
654                 if (using_old_config)
655                     return -EIO;
656                 else
657                     return ENOERR;
658             }
659
660             // We didn't synchronize with the host. Due to an IO error?
661             if (ENOERR != res && -EINTR != res) {
662                 // We may have to reset the driver if the fail was due to
663                 // a framing or parity error.
664             }
665
666             // Revert to the old configuration and try again.
667             len = sizeof(old_cfg);
668             res = cyg_io_set_config(handle, CYG_IO_SET_CONFIG_SERIAL_INFO, 
669                                     &old_cfg, &len);
670             cyg_thread_delay(10);  // Some chips don't like changes to happen to fast...
671             if (res != ENOERR) {
672                 TEST_CRASH(handle, TEST_CRASH_IO_SET_CFG,
673                            "Can't set serial config/3", res);
674             }
675             using_old_config = 1;
676         }
677
678     }
679 }
680
681
682 //-----------------------------------------------------------------------------
683 // Host sends CRC in decimal ASCII, terminated with !
684 int
685 read_host_crc(cyg_io_handle_t handle)
686 {
687     int crc;
688     cyg_uint32 len;
689     cyg_uint8 ch;
690
691     crc = 0;
692     while (1) {
693         len = 1;
694         Tcyg_io_read(handle, &ch, &len);
695         if ('!' == ch)
696             break;
697
698         if (!((ch >= '0' && ch <= '9'))){
699             TEST_CRASH(handle, TEST_CRASH_CRC_CHAR,
700                        "Illegal CRC format from host", ch);
701         }
702
703         crc = crc*10 + (ch - '0');
704     }
705
706     return crc;
707 }
708
709 //---------------------------------------------------------------------------
710 // Test binary data transmission.
711 // Format out:
712 //  "@BINARY:<byte size>:<mode>!"
713 // Format in:
714 //  <checksum>!<#size bytes data>
715 // For echo modes, also:
716 //     Format out:
717 //      <#size bytes data>
718 //     Format in:
719 //      OK/ER
720 // Format out:
721 //  DONE
722 //
723 //  The last DONE allows the host to eat bytes if target is sending too many.
724 //
725 // Mode:
726 //   MODE_NO_ECHO:  
727 //       Just receive data and verify CRC.
728 //   MODE_EOP_ECHO:
729 //       Receive data, verify CRC, resend data.
730 //       Expect OK/ER reply from host when done.
731 //   MODE_DUPLEX_ECHO:
732 //       Receive data, echo data, verify CRC.
733 //       Expect OK/ER reply from host when done.
734 //
735 // Note:
736 //   Using diag_printf while talking with the host may cause some funky
737 //   errors (bytes from the host side being lost!?!?)
738 //
739 // To Do:
740 //   MODE_DUPLEX_ECHO:
741 //     The current implementation is simple and may not stress the
742 //     driver enough. Also, it's command packet format doesn't match
743 //     that of the other modes.
744
745 cyg_test_return_t
746 test_binary(cyg_io_handle_t handle, int size, cyg_mode_t mode)
747 {
748     const char cmd[] = "@BINARY:";
749     cyg_uint32 msglen;
750     cyg_uint32 xcrc;
751     int icrc, host_crc;
752     char *p1;
753     cyg_int8 host_status = 'O';         // host is happy by default
754
755     // Verify that the test can be run with available ressources.
756     if (MODE_EOP_ECHO == mode && size > IN_BUFFER_SIZE)
757         return TEST_RETURN_NA;
758
759     // Prepare and send the command.
760     p1 = &cmd_buffer[0];
761     p1 = strcpy(p1, &cmd[0]);
762     p1 = itoa(p1, size);
763     *p1++ = ':';
764     p1 = itoa(p1, mode);
765     *p1++ = '!';
766     *p1++ = 0;
767
768     CYG_TEST_INFO(&cmd_buffer[1]);
769   
770     msglen = strlen(&cmd_buffer[0]);
771     Tcyg_io_write(handle, &cmd_buffer[0], &msglen);
772
773     // Get CRC back.
774     host_crc = read_host_crc(handle);
775
776     // Depending on mode, start reading data.
777     xcrc = 0;
778     switch (mode) {
779     case MODE_NO_ECHO:
780     {
781         // Break transfers into chunks no larger than the buffer size.
782         int tx_len, i;
783         cyg_uint32 chunk_len;
784         while (size > 0) {
785             chunk_len = min(IN_BUFFER_SIZE, size);
786             tx_len = chunk_len;
787             size -= chunk_len;
788
789             Tcyg_io_read(handle, &in_buffer[0], &chunk_len);
790
791             for (i = 0; i < tx_len; i++) {
792                 ADD_CRC_BYTE(xcrc, in_buffer[i]);
793             }
794         }
795
796         // Reply that we have completed the test.
797         {
798             const char msg_done[] = "DONE";
799
800             chunk_len = strlen(&msg_done[0]);
801             Tcyg_io_write(handle, &msg_done[0], &chunk_len);
802         }
803
804     }
805     break;
806     case MODE_EOP_ECHO:
807     {
808         // We have already checked that the in buffer is large enough.
809         int i, tx_len;
810         cyg_uint32 chunk_len;
811         chunk_len = tx_len = size;
812         Tcyg_io_read(handle, &in_buffer[0], &chunk_len);
813
814         for (i = 0; i < tx_len; i++) {
815             ADD_CRC_BYTE(xcrc, in_buffer[i]);
816         }
817
818         // Echo data back.
819         chunk_len = size;
820         Tcyg_io_write(handle, &in_buffer[0], &chunk_len);
821         
822         // Now read host side's status
823         chunk_len = 2;
824         Tcyg_io_read(handle, &in_buffer[0], &chunk_len);
825         host_status = in_buffer[0];
826
827         // Reply that we have completed the test.
828         {
829             const char msg_done[] = "DONE";
830
831             chunk_len = strlen(&msg_done[0]);
832             Tcyg_io_write(handle, &msg_done[0], &chunk_len);
833         }
834     }
835     break;
836     case MODE_DUPLEX_ECHO:
837     {
838         cyg_uint32 chunk_len;
839         int block_size = 64;
840
841         // This is a simple implementation (maybe too simple).
842         // Host sends 4 packets with the same size (64 bytes atm).
843         // Target echoes in this way:
844         //  packet1 -> packet1
845         //  packet2 -> packet2, packet2
846         //  packet3 -> packet3
847         //  packet4 -> /dev/null
848         //
849         // The reads/writes are interleaved in a way that should ensure
850         // the target out buffer to be full before the target starts to read
851         // packet3. That is, the target should be both receiving (packet3)
852         // and sending (packet2) at the same time.
853
854         while (size--) {
855             // block_size -> block_size
856             chunk_len = block_size;
857             Tcyg_io_read(handle, &in_buffer[0], &chunk_len);
858             chunk_len = block_size;
859             Tcyg_io_write(handle, &in_buffer[0], &chunk_len);
860
861             // block_size -> 2 x block_size
862             chunk_len = block_size;
863             Tcyg_io_read(handle, &in_buffer[0], &chunk_len);
864             chunk_len = block_size;
865             Tcyg_io_write(handle, &in_buffer[0], &chunk_len);
866             chunk_len = block_size;
867             Tcyg_io_write(handle, &in_buffer[0], &chunk_len);
868
869             // block_size -> block_size
870             chunk_len = block_size;
871             Tcyg_io_read(handle, &in_buffer[0], &chunk_len);
872             chunk_len = block_size;
873             Tcyg_io_write(handle, &in_buffer[0], &chunk_len);
874         
875             // block_size -> 0
876             chunk_len = block_size;
877             Tcyg_io_read(handle, &in_buffer[0], &chunk_len);
878         }
879
880         // Kill the CRC. Leave packet verification to the host for now.
881         xcrc = host_crc = 0;
882
883         // Now read host side's status
884         chunk_len = 2;
885         Tcyg_io_read(handle, &in_buffer[0], &chunk_len);
886         host_status = in_buffer[0];
887
888         // Reply that we have completed the test.
889         {
890             const char msg_done[] = "DONE";
891
892             chunk_len = strlen(&msg_done[0]);
893             Tcyg_io_write(handle, &msg_done[0], &chunk_len);
894         }
895     }
896     break;
897     default:
898         TEST_CRASH(handle, TEST_CRASH_PROT_BIN_MODE, 
899                    "Unknown mode", mode);
900         break;
901     }
902
903
904     // Verify that the CRC matches the one from the host.
905     FIX_CRC(xcrc, icrc);
906     if (host_crc != icrc) {
907         TEST_CRASH(handle, TEST_CRASH_CRC_BAD,
908                    "Input CRC failed", icrc, host_crc);
909     }
910
911     // Verify that the host is happy with the data we echoed.
912     if ('O' != host_status) {
913         TEST_CRASH(handle, TEST_CRASH_CRC_HOST, 
914                    "Output CRC failed");
915     }
916
917     CYG_TEST_PASS("Binary test completed");
918     return TEST_RETURN_OK;
919 }
920
921 //---------------------------------------------------------------------------
922 // Test transformations on text transmissions
923 // Format out:
924 //  "@TEXT:<mode>!<4 bytes binary checksum><C string>"
925 // Format in:
926 //  "<C string>"
927 //  OK/ER
928 //
929 // Mode:
930 //   MODE_EOP_ECHO:
931 //       Receive data, verify CRC, resend data.
932 //       Expect OK/ER reply from host when done.
933 //   MODE_DUPLEX_ECHO:
934 //       Receive data, echo data, verify CRC.
935 //       Expect OK/ER reply from host when done.
936 //
937 cyg_test_return_t
938 test_text(cyg_io_handle_t handle, cyg_mode_t mode, const char* s_base,
939            const char* s_out, const char* s_in)
940 {
941     return TEST_RETURN_NA;
942 }
943
944 //---------------------------------------------------------------------------
945 // Send PING to host, verifying the filter's presence.
946 // Format out:
947 //  "@PING:<crash id>!"
948 // Format in:
949 //  "OK"
950 // or
951 //  No response if directly connected to GDB.
952 //
953 // This call only returns if the ser_filter is listening. Otherwise it
954 // sends N/A and hangs.
955 void
956 test_ping(cyg_io_handle_t handle)
957 {
958     char msg[] = "@PING:" TEST_CRASH_ID "!";
959     char msg2[] = "\n";
960     cyg_uint32 msglen = strlen(msg);
961     int res;
962
963     msglen = strlen(msg);
964     Tcyg_io_write(handle, msg, &msglen);
965
966     // Now read host side's status
967     msglen = 2;
968     Tcyg_io_read_timeout(handle, &in_buffer[0], &msglen, 100, &res);
969     if (ENOERR == res && 'O' == in_buffer[0] && 'K' == in_buffer[1])
970         return;
971
972     msglen = strlen(msg2);
973     Tcyg_io_write(handle, msg2, &msglen);
974
975     CYG_TEST_NA("No host side testing harness detected.");
976 }
977
978
979 //---------------------------------------------------------------------------
980 // Send OPT to host, setting options in the filter.
981 // Format out:
982 //  "@OPT:option1,value1:...:optionN,valueN!"
983 // Format in:
984 //  "OK"
985 //
986 // Only integer values can be used. Any option not recognized by the
987 // filter will be silently ignored.
988 void
989 test_options(cyg_io_handle_t handle, int count, cyg_uint32* options)
990 {
991     const char cmd[] = "@OPT:";
992     cyg_uint32 msglen;
993     char *p1;
994
995     // Prepare and send the command.
996     p1 = &cmd_buffer[0];
997     p1 = strcpy(p1, &cmd[0]);
998     while(count--) {
999         p1 = itoa(p1, *options++);      // option
1000         *p1++ = ':';
1001         p1 = itoa(p1, *options++);      // value
1002         *p1++ = ':';
1003     }
1004     *(p1-1) = '!';
1005     *p1++ = 0;
1006
1007     CYG_TEST_INFO(&cmd_buffer[1]);
1008   
1009     msglen = strlen(&cmd_buffer[0]);
1010     Tcyg_io_write(handle, &cmd_buffer[0], &msglen);
1011
1012     // Now read host side's status
1013     msglen = 2;
1014     Tcyg_io_read(handle, &in_buffer[0], &msglen);
1015 }
1016
1017
1018 //---------------------------------------------------------------------------
1019 // Some helper functions to get a test started.
1020 void
1021 test_open_ser( cyg_io_handle_t* handle )
1022 {
1023 #if defined(CYGPKG_IO_SERIAL_DEVICES) && !defined(SER_NOP_TEST)
1024     Cyg_ErrNo res;
1025
1026     if (cyg_test_is_simulator)
1027         CYG_TEST_NA("Cannot run from simulator");
1028
1029 #if defined(HAL_VSR_SET_TO_ECOS_HANDLER)
1030 # if defined(CYGPRI_SER_TEST_OVERRIDE_INT_1)
1031     HAL_VSR_SET_TO_ECOS_HANDLER(CYGPRI_SER_TEST_OVERRIDE_INT_1, NULL);
1032 # endif
1033 # if defined(CYGPRI_SER_TEST_OVERRIDE_INT_2)
1034     HAL_VSR_SET_TO_ECOS_HANDLER(CYGPRI_SER_TEST_OVERRIDE_INT_2, NULL);
1035 # endif
1036 #endif
1037
1038     res = cyg_io_lookup(TEST_SER_DEV, handle);
1039     if (res != ENOERR) {
1040         CYG_TEST_FAIL_FINISH("Can't lookup " TEST_SER_DEV);
1041     }
1042 #else
1043     CYG_TEST_NA(NA_MSG);
1044 #endif
1045 }
1046
1047 void
1048 test_open_tty( cyg_io_handle_t* handle )
1049 {
1050 #if defined(CYGPKG_IO_SERIAL_TTY) && !defined(TTY_NOP_TEST)
1051     Cyg_ErrNo res;
1052
1053     if (cyg_test_is_simulator)
1054         CYG_TEST_NA("Cannot run from simulator");
1055
1056 #if defined(HAL_VSR_SET_TO_ECOS_HANDLER)
1057 # if defined(CYGPRI_SER_TEST_OVERRIDE_INT_1)
1058     HAL_VSR_SET_TO_ECOS_HANDLER(CYGPRI_SER_TEST_OVERRIDE_INT_1, NULL);
1059 # endif
1060 # if defined(CYGPRI_SER_TEST_OVERRIDE_INT_2)
1061     HAL_VSR_SET_TO_ECOS_HANDLER(CYGPRI_SER_TEST_OVERRIDE_INT_2, NULL);
1062 # endif
1063 #endif
1064
1065     res = cyg_io_lookup(TEST_TTY_DEV, handle);
1066     if (res != ENOERR) {
1067         CYG_TEST_FAIL_FINISH("Can't lookup " TEST_TTY_DEV);
1068     }
1069 #else
1070     CYG_TEST_NA(NA_MSG);
1071 #endif
1072 }
1073
1074 //---------------------------------------------------------------------------
1075 // end of ser_test_protocol.inl