OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [tags/] [start/] [gdb-5.0/] [utils/] [amd-udi/] [montip/] [checksum.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 106 markom
static char _[] = "@(#)checksum.c       5.25 93/10/27 15:11:54, Srini, AMD.";
2
/******************************************************************************
3
 * Copyright 1991 Advanced Micro Devices, Inc.
4
 *
5
 * This software is the property of Advanced Micro Devices, Inc  (AMD)  which
6
 * specifically  grants the user the right to modify, use and distribute this
7
 * software provided this notice is not removed or altered.  All other rights
8
 * are reserved by AMD.
9
 *
10
 * AMD MAKES NO WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, WITH REGARD TO THIS
11
 * SOFTWARE.  IN NO EVENT SHALL AMD BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL
12
 * DAMAGES IN CONNECTION WITH OR ARISING FROM THE FURNISHING, PERFORMANCE, OR
13
 * USE OF THIS SOFTWARE.
14
 *
15
 * So that all may benefit from your experience, please report  any  problems
16
 * or  suggestions about this software to the 29K Technical Support Center at
17
 * 800-29-29-AMD (800-292-9263) in the USA, or 0800-89-1131  in  the  UK,  or
18
 * 0031-11-1129 in Japan, toll free.  The direct dial number is 512-462-4118.
19
 *
20
 * Advanced Micro Devices, Inc.
21
 * 29K Support Products
22
 * Mail Stop 573
23
 * 5900 E. Ben White Blvd.
24
 * Austin, TX 78741
25
 * 800-292-9263
26
 *****************************************************************************
27
 *      Engineer: Srini Subramanian.
28
 *****************************************************************************
29
 **
30
 **       This file contains code for intercepting failed messages
31
 **      due to serial transmission errors.  The code logically
32
 **      resides between the messages system and the character
33
 **      based serial driver.  Messages with invalid checksums, or
34
 **      other communication errors are retried.
35
 *****************************************************************************
36
 */
37
 
38
#include <stdio.h>
39
#include <string.h>
40
#include "types.h"
41
#include "memspcs.h"
42
#include "messages.h"
43
#include "mtip.h"
44
#include "tdfunc.h"
45
 
46
#ifdef MSDOS
47
#include <conio.h>
48
#endif
49
 
50
#define ACK_HDR_CODE -1
51
#define CHECKSUM_PASS 0
52
#define CHECKSUM_FAIL -1
53
 
54
extern  int     MessageRetries;
55
extern  unsigned int    TimeOut;
56
extern  unsigned int    BlockCount;
57
#ifdef __hpux
58
static volatile int     bcount;
59
#else
60
static int      bcount;
61
#endif
62
 
63
extern  int     use_parport;
64
 
65
#ifdef MSDOS
66
INT32   par_write PARAMS ((char *, INT32));
67
#endif
68
 
69
void   endian_cvt PARAMS((union msg_t *, int));
70
void   send_nack PARAMS((INT32 port_base));
71
 
72
extern  FILE    *MsgFile;       /* for logging error retries */
73
 
74
struct  ack_msg_t {
75
  INT32         code;
76
  INT32         passfail;
77
};
78
union  ack_msg_buf_t {
79
   struct ack_msg_t  ack_msg;
80
   unsigned char     buf[(2*sizeof(INT32))];
81
};
82
 
83
 
84
INT32
85
msg_send_serial(msg_ptr, port_base)
86
   union  msg_t  *msg_ptr;
87
   INT32  port_base;
88
   {
89
   INT32 result, i, ack, comm_err;
90
   UINT32 checksum;
91
   int          retries;
92
   unsigned int         timeout;
93
   INT32        Rx_ack[2];
94
 
95
   INT32 header_size = (2 * sizeof(INT32));
96
 
97
   BYTE  *bfr_ptr = (BYTE *) msg_ptr;
98
 
99
   /* Save length before doing endian conversion */
100
   INT32 length = msg_ptr->generic_msg.length;
101
   INT32 total_length;
102
 
103
   /*
104
    * MiniMON29K release 2.1 has new Communications Interface module
105
    * which does not expect the checksum to be aligned on a word
106
    * boundary. It expects the checksum to immediately follow the
107
    * end of the message body.
108
    * The old handler aligned the checksum on the next word boundar after
109
    * the message body, but did _not_ update the message length field.
110
    * That caused problems when one end of the Communications gets
111
    * changed.
112
    */
113
   if (((tip_target_config.version >> 24) & 0xf) > 5) { /* new comm handler */
114
   } else { /* old comm handler */
115
      /* round length up to even word */
116
      if ((length & 3) != 0) {   /* round up to word boundary */
117
           length = length + 3;
118
           length = length & 0xfffffffc;
119
      };
120
   }
121
 
122
   total_length = header_size + length;
123
 
124
   /* Endian conversion */
125
   if (tip_target_config.TipEndian != tip_target_config.P29KEndian)
126
      endian_cvt(msg_ptr, OUTGOING_MSG);
127
 
128
   /* calc checksum for msg */
129
   checksum = 0;
130
   for (i=0; i < total_length; i++)
131
     checksum = checksum + bfr_ptr[i];
132
 
133
   /* Append checksum to the end of the message. Do not update the
134
    * "length" field of the message header.
135
    */
136
   bfr_ptr[total_length] = (BYTE) ((checksum >> 24) & 0xff);
137
   bfr_ptr[total_length+1] = (BYTE) ((checksum >> 16) & 0xff);
138
   bfr_ptr[total_length+2] = (BYTE) ((checksum >> 8) & 0xff);
139
   bfr_ptr[total_length+3] = (BYTE) ((checksum >> 0) & 0xff);
140
   /* send msg */
141
   retries = 0;
142
   do  {
143
        retries = retries + 1;
144
        comm_err = (INT32) 0;
145
 
146
        /* send msg */
147
        result = send_bfr_serial(bfr_ptr, total_length+4, /* 4 for checksum*/
148
                                        port_base, &comm_err);
149
        if (comm_err != (INT32) 0) {
150
          (void) reset_comm_serial ((INT32) -1, (INT32) -1);
151
          return ((INT32) MSGRETRY);
152
        }
153
        if (result != (INT32) 0)
154
            return((INT32) FAILURE);
155
 
156
        /* get ack */
157
        timeout = 0;
158
        result = (INT32) -1;
159
        comm_err = (INT32) 0;
160
        while ((timeout < TimeOut) && (result == (INT32) -1)
161
                                          && (comm_err == (INT32) 0)) {
162
        /* Poll for user interrupt */
163
           SIGINT_POLL
164
           timeout=timeout+1;
165
           result = recv_bfr_serial((BYTE *) Rx_ack, (2 * sizeof(INT32)),
166
                                        BLOCK, port_base, &comm_err);
167
#ifndef MSDOS
168
           /* printf("ack wait timeout=0x%lx\n", timeout); */
169
           if (result == (INT32) -1)
170
             for (bcount = 0; bcount < BlockCount; bcount++);
171
#endif
172
        }
173
 
174
        if (comm_err != (INT32) 0) {
175
             reset_comm_serial((INT32) -1, (INT32) -1);
176
             return ((INT32) MSGRETRY);
177
        }
178
        /* Poll for user interrupt */
179
           SIGINT_POLL
180
        /* check if timed out */
181
        if (timeout >= TimeOut) {
182
         if (MsgFile) {
183
           fprintf(MsgFile,"Timed out before ACK received. Reset comm. retries=%d timeout=%ld\n",retries, timeout);
184
           fflush(MsgFile);
185
          }
186
          (void) reset_comm_serial((INT32) 0, (INT32) 0);
187
          continue;
188
        }
189
 
190
        ack = (INT32) Rx_ack[1];
191
 
192
        /* endian convert Ack */
193
        if (tip_target_config.TipEndian != tip_target_config.P29KEndian)
194
                                tip_convert32((BYTE *) &ack);
195
 
196
        if (Rx_ack[0] == (INT32) 0xFFFFFFFF && ack != CHECKSUM_FAIL) {
197
                return(0);               /* successful send */
198
                }
199
        else {
200
          (void) reset_comm_serial((INT32) 0, (INT32) 0);
201
                if (MsgFile) {  /* log the error */
202
                        fprintf(MsgFile,
203
                          "\n** Checksum: Nack Received, Resending.\n");
204
                        fflush(MsgFile);
205
                        };
206
                }
207
 
208
   } while ( retries < MessageRetries);
209
   return ((INT32) FAILURE);
210
}
211
 
212
INT32
213
msg_recv_serial(msg_ptr, port_base, Mode)
214
   union  msg_t  *msg_ptr;
215
   INT32  port_base;
216
   INT32  Mode; /* Block or NonBlock */
217
   {
218
   union  ack_msg_buf_t  AckMsg;
219
   UINT32 checksum_calc, checksum_recv;
220
   INT32 i, result;
221
   INT32 comm_err;
222
   INT32 ack_hdr;
223
   BYTE  *bfr_ptr;
224
   INT32 header_size;
225
   INT32 length, total_length;
226
 
227
again:
228
        /* Poll for user interrupt */
229
           SIGINT_POLL
230
 
231
   comm_err = (INT32) 0;
232
   ack_hdr = (INT32) ACK_HDR_CODE;
233
   bfr_ptr = (BYTE *) msg_ptr;
234
   header_size = (2 * sizeof(INT32));
235
 
236
   /* recv header - if available */
237
   if (Mode == NONBLOCK) {
238
#ifndef MSDOS
239
             for (bcount = 0; bcount < BlockCount; bcount++);
240
#endif
241
     result = recv_bfr_serial(bfr_ptr, header_size, Mode,
242
                                        port_base, &comm_err);
243
              /* printf("nbread: result = 0x%lx Mode=0x%lx\n", result, Mode); */
244
   } else {
245
             /* printf("bread: header_size = %d Mode=0x%lx\n", header_size, Mode); */
246
     result = recv_bfr_serial(bfr_ptr, header_size, Mode,
247
                                        port_base, &comm_err);
248
     if (result == (INT32) -1) {
249
#ifndef MSDOS
250
             for (bcount = 0; bcount < BlockCount; bcount++);
251
#endif
252
             goto again;
253
     }
254
   }
255
   if (comm_err != (INT32) 0) {
256
          (void) reset_comm_serial ((INT32) -1, (INT32) -1);
257
          send_nack(port_base);
258
          goto again;
259
   }
260
   if (result != (INT32) 0)
261
            return((INT32) FAILURE);
262
 
263
        /* Poll for user interrupt */
264
           SIGINT_POLL
265
   /*
266
    * Before computing the length here, we should make sure that we have
267
    * received a valid (defined) MiniMON29K message by checking the
268
    * Message Code field. Otherwise, a lousy stream of bytes could send this
269
    * to a toss waiting for an unknown number of bytes.
270
    * But we hope none of those things would happen here!
271
    */
272
   result = msg_ptr->generic_msg.code;
273
   if (tip_target_config.TipEndian != tip_target_config.P29KEndian)
274
                tip_convert32((BYTE *) &result);
275
   if ((result < (INT32) 0) || (result > 101)) {
276
        (void) reset_comm_serial ((INT32) -1, (INT32) -1);
277
        send_nack(port_base);
278
        goto again;     /* retry */
279
   }
280
   /* Message header received.  Save message length. */
281
   length = msg_ptr->generic_msg.length;
282
   if (tip_target_config.TipEndian != tip_target_config.P29KEndian)
283
                tip_convert32((BYTE *) &length);
284
 
285
   /*
286
    * MiniMON29K release 2.1 has new Communications Interface module
287
    * which does not expect the checksum to be aligned on a word
288
    * boundary. It expects the checksum to immediately follow the
289
    * end of the message body.
290
    * The old handler aligned the checksum on the next word boundar after
291
    * the message body, but did _not_ update the message length field.
292
    * That caused problems when one end of the Communications gets
293
    * changed.
294
    */
295
   if (((tip_target_config.version >> 24) & 0xf) > 5) { /* new comm handler */
296
   } else { /* old comm handler */
297
      /* round length up to even word */
298
      if ((length & 3) != 0) {
299
           length = length + 3;
300
           length = length & 0xfffffffc;
301
      }
302
   }
303
 
304
   /* committed now - recv rest of msg and checksum */
305
   comm_err = (INT32) 0;
306
   result = (INT32) 0;
307
   if (length >= 0) {
308
        result = recv_bfr_serial(bfr_ptr + header_size, length+4,/* +4 */
309
                                BLOCK, port_base, &comm_err);
310
   }
311
 
312
   if (comm_err != (INT32) 0) {
313
          (void) reset_comm_serial ((INT32) -1, (INT32) -1);
314
          send_nack(port_base);
315
          goto again;   /* retry */
316
   }
317
   if (result != (INT32) 0) {
318
          (void) reset_comm_serial ((INT32) -1, (INT32) -1);
319
            send_nack(port_base);
320
            goto again; /* retry */
321
    }
322
 
323
 
324
   /* Do endian conversion */
325
   if (tip_target_config.TipEndian != tip_target_config.P29KEndian)
326
        endian_cvt(msg_ptr, INCOMING_MSG);
327
 
328
   /* calc checksum for msg */
329
   checksum_calc = 0;
330
   total_length = header_size + length;
331
   for (i=0; i < total_length; i++)
332
      checksum_calc = checksum_calc + ((UINT32) bfr_ptr[i]);
333
 
334
   checksum_recv = (UINT32) 0;
335
   checksum_recv = (UINT32) (checksum_recv | ((UINT32) bfr_ptr[total_length] << 24));
336
   checksum_recv = (UINT32) (checksum_recv | ((UINT32) bfr_ptr[total_length+1] << 16));
337
   checksum_recv = (UINT32) (checksum_recv | ((UINT32) bfr_ptr[total_length+2] << 8));
338
   checksum_recv = (UINT32) (checksum_recv | ((UINT32) bfr_ptr[total_length+3] << 0));
339
 
340
        /* Poll for user interrupt */
341
           SIGINT_POLL
342
   /* Compare Checksums */
343
   if (checksum_calc != checksum_recv) {
344
          (void) reset_comm_serial ((INT32) -1, (INT32) -1);
345
        send_nack(port_base);
346
        goto    again;  /* retry */
347
        }
348
 
349
   /* send checksum hdr & ack */
350
   AckMsg.ack_msg.code = (INT32) ACK_HDR_CODE;
351
   AckMsg.ack_msg.passfail = CHECKSUM_PASS;
352
   result = (INT32) 0;
353
   comm_err = (INT32) 0;
354
#ifdef MSDOS
355
   if (use_parport) {
356
     result = par_write ((char *) AckMsg.buf, 8);
357
   } else {
358
     result = send_bfr_serial((BYTE *) AckMsg.buf, 2 * sizeof(INT32),
359
                                port_base, &comm_err);
360
     if (comm_err != (INT32) 0) {
361
          (void) reset_comm_serial ((INT32) -1, (INT32) -1);
362
          send_nack(port_base);
363
          goto  again;  /* retry */
364
     }
365
     if (result != (INT32) 0)  {
366
       if (MsgFile) {
367
         fprintf(MsgFile, "Couldn't send checksum to acknowledge.\n");
368
         fflush (MsgFile);
369
       }
370
       (void) reset_comm_serial((INT32) -1, (INT32) -1);
371
       send_nack(port_base);
372
       goto     again;  /* retry */
373
     }
374
   }
375
#else
376
     result = send_bfr_serial((BYTE *) AckMsg.buf, 2 * sizeof(INT32),
377
                                port_base, &comm_err);
378
     if (comm_err != (INT32) 0) {
379
          (void) reset_comm_serial ((INT32) -1, (INT32) -1);
380
          send_nack(port_base);
381
          goto  again;  /* retry */
382
     }
383
     if (result != (INT32) 0)  {
384
       if (MsgFile) {
385
         fprintf(MsgFile, "Couldn't send checksum to acknowledge.\n");
386
         fflush (MsgFile);
387
       }
388
       (void) reset_comm_serial((INT32) -1, (INT32) -1);
389
       send_nack(port_base);
390
       goto     again;  /* retry */
391
     }
392
#endif
393
 
394
   return(msg_ptr->generic_msg.code);   /* passed */
395
}
396
 
397
void
398
SendACK(port_base)
399
   INT32  port_base;
400
   {
401
   union ack_msg_buf_t  AckMsg;
402
   INT32 result, comm_err;
403
   INT32 ack_hdr = (INT32) ACK_HDR_CODE;
404
   INT32 ack = CHECKSUM_FAIL;
405
 
406
   AckMsg.ack_msg.code = (INT32) ACK_HDR_CODE;
407
   AckMsg.ack_msg.passfail = CHECKSUM_PASS;
408
   result = (INT32) 0;
409
   comm_err = (INT32) 0;
410
#ifdef MSDOS
411
   if (use_parport) {
412
     result = par_write((char *) AckMsg.buf, 8);
413
     return;
414
   } else {
415
      result = send_bfr_serial((BYTE *) AckMsg.buf, 2*sizeof(INT32),
416
                                    port_base, &comm_err);
417
      if ((result != (INT32) 0) || (comm_err != (INT32) 0)) {
418
        if (MsgFile) {
419
          fprintf(MsgFile, "Couldn't send ACK to remote.\n");
420
          fflush (MsgFile);
421
        }
422
        return ;
423
      }
424
   }
425
#else
426
      result = send_bfr_serial((BYTE *) AckMsg.buf, 2*sizeof(INT32),
427
                                    port_base, &comm_err);
428
      if ((result != (INT32) 0) || (comm_err != (INT32) 0)) {
429
        if (MsgFile) {
430
          fprintf(MsgFile, "Couldn't send ACK to remote.\n");
431
          fflush (MsgFile);
432
        }
433
        return ;
434
      }
435
#endif
436
}
437
 
438
void
439
send_nack(port_base)
440
   INT32  port_base;
441
   {
442
   union ack_msg_buf_t  NAckMsg;
443
   INT32 result, comm_err;
444
   INT32 ack_hdr = (INT32) ACK_HDR_CODE;
445
   INT32 ack = CHECKSUM_FAIL;
446
 
447
   /* eat up any incoming characters */
448
   result = reset_comm_serial(port_base, port_base);    /* reset buffer */
449
 
450
   if (MsgFile) {       /* log the error */
451
        fprintf(MsgFile,
452
          "\n** Checksum: Receive failed, sending Nack.\n");
453
        fflush(MsgFile);
454
        };
455
 
456
        /* Poll for user interrupt */
457
           SIGINT_POLL
458
   NAckMsg.ack_msg.code = (INT32) ACK_HDR_CODE;
459
   NAckMsg.ack_msg.passfail = CHECKSUM_FAIL;
460
   result = (INT32) 0;
461
   comm_err = (INT32) 0;
462
#ifdef MSDOS
463
   if (use_parport) {
464
     result = par_write((char *) NAckMsg.buf, 8);
465
     return;
466
   } else {
467
      result = send_bfr_serial((BYTE *) NAckMsg.buf, 2*sizeof(INT32),
468
                                    port_base, &comm_err);
469
      if ((result != (INT32) 0) || (comm_err != (INT32) 0)) {
470
        if (MsgFile) {
471
          fprintf(MsgFile, "Couldn't send NACK to remote.\n");
472
          fflush (MsgFile);
473
        }
474
        return ;
475
      }
476
   }
477
#else
478
      result = send_bfr_serial((BYTE *) NAckMsg.buf, 2*sizeof(INT32),
479
                                    port_base, &comm_err);
480
      if ((result != (INT32) 0) || (comm_err != (INT32) 0)) {
481
        if (MsgFile) {
482
          fprintf(MsgFile, "Couldn't send NACK to remote.\n");
483
          fflush (MsgFile);
484
        }
485
        return ;
486
      }
487
#endif
488
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.