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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [gdb-5.0/] [gdb/] [rdi-share/] [hostchan.c] - Blame information for rev 1774

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 106 markom
/*
2
 * Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
3
 *
4
 * This software may be freely used, copied, modified, and distributed
5
 * provided that the above copyright notice is preserved in all copies of the
6
 * software.
7
 */
8
 
9
/* -*-C-*-
10
 *
11
 * $Revision: 1.1.1.1 $
12
 *     $Date: 2001-05-18 11:16:42 $
13
 *
14
 *
15
 * hostchan.c - Semi Synchronous Host side channel interface for Angel.
16
 */
17
 
18
#include <stdio.h>
19
 
20
#ifdef HAVE_SYS_TIME_H
21
#  include <sys/time.h>
22
#else
23
#  include "winsock.h"
24
#  include "time.h"
25
#endif
26
#include "hsys.h"
27
#include "host.h"
28
#include "logging.h"
29
#include "chandefs.h"
30
#include "chanpriv.h"
31
#include "devclnt.h"
32
#include "buffers.h"
33
#include "drivers.h"
34
#include "adperr.h"
35
#include "devsw.h"
36
#include "hostchan.h"
37
 
38
#ifndef UNUSED
39
#define UNUSED(x) (x = x)  /* Silence compiler warnings for unused arguments */
40
#endif
41
 
42
#define HEARTRATE 5000000
43
 
44
/*
45
 * list of available drivers, declared in drivers.c
46
 */
47
extern DeviceDescr *devices[];
48
 
49
static DeviceDescr *deviceToUse = NULL;
50
 
51
static struct Channel {
52
    ChannelCallback callback;
53
    void *callback_state;
54
} channels[CI_NUM_CHANNELS];
55
 
56
static unsigned char HomeSeq;
57
static unsigned char OppoSeq;
58
 
59
/*
60
 * Handler for DC_APPL packets
61
 */
62
static DC_Appl_Handler dc_appl_handler = NULL;
63
 
64
/*
65
 * slots for registered asynchronous processing callback procedures
66
 */
67
#define MAX_ASYNC_CALLBACKS 8
68
static unsigned int             num_async_callbacks = 0;
69
static Adp_Async_Callback       async_callbacks[MAX_ASYNC_CALLBACKS];
70
 
71
/*
72
 * writeQueueRoot is the queue of write requests pending acknowledgement
73
 * writeQueueSend is the queue of pending write requests which will
74
 * be a subset of the list writeQueueRoot
75
 */
76
static Packet *writeQueueRoot = NULL;
77
static Packet *writeQueueSend = NULL;
78
static Packet *resend_pkt = NULL;
79
static int resending = FALSE;
80
 
81
/* heartbeat_enabled is a flag used to indicate whether the heartbeat is
82
 * currently turned on, heartbeat_enabled will be false in situations
83
 * where even though a heartbeat is being used it is problematical or
84
 * dis-advantageous to have it turned on, for instance during the
85
 * initial stages of boot up
86
 */
87
unsigned int heartbeat_enabled = FALSE;
88
/* heartbeat_configured is set up by the device driver to indicate whether
89
 * the heartbeat is being used during this debug session.  In contrast to
90
 * heartbeat_enabled it must not be changed during a session.  The logic for
91
 * deciding whether to send a heartbeat is: Is heartbeat_configured for this
92
 * session? if and only if it is then if heartbeat[is currently]_enabled and
93
 * we are due to send a pulse then send it
94
 */
95
unsigned int heartbeat_configured = TRUE;
96
 
97
void Adp_initSeq( void ) {
98
  Packet *tmp_pkt = writeQueueSend;
99
 
100
  HomeSeq = 0;
101
  OppoSeq = 0;
102
  if ( writeQueueSend != NULL) {
103
    while (writeQueueSend->pk_next !=NULL) {
104
      tmp_pkt = writeQueueSend;
105
      writeQueueSend = tmp_pkt->pk_next;
106
      DevSW_FreePacket(tmp_pkt);
107
    }
108
  }
109
  tmp_pkt = writeQueueRoot;
110
  if ( writeQueueRoot == NULL)
111
    return;
112
 
113
  while (writeQueueRoot->pk_next !=NULL) {
114
    tmp_pkt = writeQueueRoot;
115
    writeQueueRoot = tmp_pkt->pk_next;
116
    DevSW_FreePacket(tmp_pkt);
117
  }
118
  return;
119
}
120
 
121
/**********************************************************************/
122
 
123
/*
124
 *  Function: DummyCallback
125
 *   Purpose: Default callback routine to handle unexpected input
126
 *              on a channel
127
 *
128
 *    Params:
129
 *       Input: packet  The received packet
130
 *
131
 *              state   Contains nothing of significance
132
 *
133
 *   Returns: Nothing
134
 */
135
static void DummyCallback(Packet *packet, void *state)
136
{
137
    ChannelID chan;
138
    const char fmt[] = "Unexpected read on channel %u, length %d\n";
139
    char fmtbuf[sizeof(fmt) + 24];
140
 
141
    UNUSED(state);
142
 
143
    chan = *(packet->pk_buffer);
144
    sprintf(fmtbuf, fmt, chan, packet->pk_length);
145
    printf(fmtbuf);
146
 
147
    /*
148
     * junk this packet
149
     */
150
    DevSW_FreePacket(packet);
151
}
152
 
153
/*
154
 *  Function: BlockingCallback
155
 *   Purpose: Callback routine used to implement a blocking read call
156
 *
157
 *    Params:
158
 *       Input: packet  The received packet.
159
 *
160
 *      Output: state   Address of higher level's pointer to the received
161
 *                      packet.
162
 *
163
 *   Returns: Nothing
164
 */
165
static void BlockingCallback(Packet *packet, void *state)
166
{
167
    /*
168
     * Pass the packet back to the caller which requested a packet
169
     * from this channel.  This also flags the completion of the I/O
170
     * request to the blocking read call.
171
     */
172
    *((Packet **)state) = packet;
173
}
174
 
175
/*
176
 *  Function: FireCallback
177
 *   Purpose: Pass received packet along to the callback routine for
178
 *              the appropriate channel
179
 *
180
 *    Params:
181
 *       Input: packet  The received packet.
182
 *
183
 *   Returns: Nothing
184
 *
185
 * Post-conditions: The Target-to-Host sequence number for the channel
186
 *                      will have been incremented.
187
 */
188
static void FireCallback(Packet *packet)
189
{
190
    ChannelID chan;
191
    struct Channel *ch;
192
 
193
    /*
194
     * is this a sensible channel number?
195
     */
196
    chan = *(packet->pk_buffer);
197
    if (invalidChannelID(chan))
198
    {
199
        printf("ERROR: invalid ChannelID received from target\n");
200
 
201
        /*
202
         * free the packet's resources, 'cause no-one else will
203
         */
204
        DevSW_FreePacket(packet);
205
        return;
206
    }
207
 
208
    /*
209
     * looks OK - increment sequence number, and pass packet to callback
210
     */
211
    ch = channels + chan;
212
    (ch->callback)(packet, ch->callback_state);
213
}
214
 
215
/**********************************************************************/
216
 
217
/*
218
 * These are the externally visible functions.  They are documented
219
 * in hostchan.h
220
 */
221
void Adp_addToQueue(Packet **head, Packet *newpkt)
222
{
223
    /*
224
     * this is a bit of a hack
225
     */
226
    Packet *pk;
227
 
228
    /*
229
     * make sure that the hack we are about to use will work as expected
230
     */
231
    ASSERT(&(((Packet *)0)->pk_next) == 0, "bad struct Packet layout");
232
 
233
#if defined(DEBUG) && 0
234
    printf("Adp_addToQueue(%p, %p)\n", head, newpkt);
235
#endif
236
 
237
    /*
238
     * here's the hack - it relies upon the next
239
     * pointer being at the start of Packet.
240
     */
241
    pk = (Packet *)(head);
242
 
243
    /*
244
     * skip to the end of the queue
245
     */
246
    while (pk->pk_next != NULL)
247
        pk = pk->pk_next;
248
 
249
    /*
250
     * now add the new element
251
     */
252
    newpkt->pk_next = NULL;
253
    pk->pk_next = newpkt;
254
}
255
 
256
Packet *Adp_removeFromQueue(Packet **head)
257
{
258
    struct Packet *pk;
259
 
260
    pk = *head;
261
 
262
    if (pk != NULL)
263
        *head = pk->pk_next;
264
 
265
    return pk;
266
}
267
 
268
void Adp_SetLogEnable(int logEnableFlag)
269
{
270
  DevSW_SetLogEnable(logEnableFlag);
271
}
272
 
273
void Adp_SetLogfile(const char *filename)
274
{
275
  DevSW_SetLogfile(filename);
276
}
277
 
278
AdpErrs Adp_OpenDevice(const char *name, const char *arg,
279
                       unsigned int heartbeat_on)
280
{
281
    int i;
282
    AdpErrs retc;
283
    ChannelID chan;
284
 
285
#ifdef DEBUG
286
    printf("Adp_OpenDevice(%s, %s)\n", name, arg ? arg : "<NULL>");
287
#endif
288
 
289
    heartbeat_configured = heartbeat_on;
290
    if (deviceToUse != NULL)
291
        return adp_device_already_open;
292
 
293
    for (i = 0; (deviceToUse = devices[i]) != NULL; ++i)
294
        if (DevSW_Match(deviceToUse, name, arg) == adp_ok)
295
            break;
296
 
297
    if (deviceToUse == NULL)
298
        return adp_device_not_found;
299
 
300
    /*
301
     * we seem to have found a suitable device driver, so try to open it
302
     */
303
    if ((retc = DevSW_Open(deviceToUse, name, arg, DC_DBUG)) != adp_ok)
304
    {
305
        /* we don't have a device to use */
306
        deviceToUse = NULL;
307
        return retc;
308
    }
309
 
310
    /*
311
     * there is no explicit open on channels any more, so
312
     * initialise state for all channels.
313
     */
314
    for (chan = 0; chan < CI_NUM_CHANNELS; ++chan)
315
    {
316
        struct Channel *ch = channels + chan;
317
 
318
        ch->callback = DummyCallback;
319
        ch->callback_state = NULL;
320
        OppoSeq = 0;
321
        HomeSeq = 0;
322
    }
323
 
324
    return adp_ok;
325
}
326
 
327
AdpErrs Adp_CloseDevice(void)
328
{
329
    AdpErrs retc;
330
 
331
#ifdef DEBUG
332
    printf("Adp_CloseDevice\n");
333
#endif
334
 
335
    if (deviceToUse == NULL)
336
        return adp_device_not_open;
337
 
338
    heartbeat_enabled = FALSE;
339
 
340
    retc = DevSW_Close(deviceToUse, DC_DBUG);
341
 
342
    /*
343
     * we have to clear deviceToUse, even when the lower layers
344
     * faulted the close, otherwise the condition will never clear
345
     */
346
    if (retc != adp_ok)
347
        WARN("DevSW_Close faulted the call");
348
 
349
    deviceToUse = NULL;
350
    return retc;
351
}
352
 
353
AdpErrs Adp_Ioctl(int opcode, void *args)
354
{
355
#ifdef DEBUG
356
    printf("Adp_Ioctl\n");
357
#endif
358
 
359
    if (deviceToUse == NULL)
360
        return adp_device_not_open;
361
 
362
    return DevSW_Ioctl(deviceToUse, opcode, args);
363
}
364
 
365
AdpErrs Adp_ChannelRegisterRead(const ChannelID chan,
366
                                const ChannelCallback cbfunc,
367
                                void *cbstate)
368
{
369
#ifdef DEBUG
370
    printf("Adp_ChannelRegisterRead(%d, %p, %x)\n", chan, cbfunc, cbstate);
371
#endif
372
 
373
    if (deviceToUse == NULL)
374
        return adp_device_not_open;
375
 
376
    if (invalidChannelID(chan))
377
        return adp_bad_channel_id;
378
 
379
    if (cbfunc == NULL)
380
    {
381
        channels[chan].callback = DummyCallback;
382
        channels[chan].callback_state = NULL;
383
    }
384
    else
385
    {
386
        channels[chan].callback = cbfunc;
387
        channels[chan].callback_state = cbstate;
388
    }
389
 
390
    return adp_ok;
391
}
392
 
393
AdpErrs Adp_ChannelRead(const ChannelID chan, Packet **packet)
394
{
395
    struct Channel *ch;
396
 
397
#ifdef DEBUG
398
    printf("Adp_ChannelRead(%d, %x)\n", chan, *packet);
399
#endif
400
 
401
    if (deviceToUse == NULL)
402
        return adp_device_not_open;
403
 
404
    if (invalidChannelID(chan))
405
        return adp_bad_channel_id;
406
 
407
    /*
408
     * if a callback has already been registered for this
409
     * channel, then we do not allow this blocking read.
410
     */
411
    ch = channels + chan;
412
    if (ch->callback != DummyCallback)
413
        return adp_callback_already_registered;
414
 
415
    /*
416
     * OK, use our own callback to wait for a packet to arrive
417
     * on this channel
418
     */
419
    ch->callback = BlockingCallback;
420
    ch->callback_state = packet;
421
    *packet = NULL;
422
 
423
    /*
424
     * keep polling until a packet appears for this channel
425
     */
426
    while (((volatile Packet *)(*packet)) == NULL)
427
        /*
428
         * this call will block until a packet is read on any channel
429
         */
430
        Adp_AsynchronousProcessing(async_block_on_read);
431
 
432
    /*
433
     * OK, the packet has arrived: clear the callback
434
     */
435
    ch->callback = DummyCallback;
436
    ch->callback_state = NULL;
437
 
438
    return adp_ok;
439
}
440
 
441
static AdpErrs ChannelWrite(
442
    const ChannelID chan, Packet *packet, AsyncMode mode)
443
{
444
    struct Channel *ch;
445
    unsigned char *cptr;
446
 
447
#ifdef DEBUG
448
    printf( "Adp_ChannelWrite(%d, %x)\n", chan, packet );
449
#endif
450
 
451
    if (deviceToUse == NULL)
452
        return adp_device_not_open;
453
 
454
    if (invalidChannelID(chan))
455
        return adp_bad_channel_id;
456
 
457
    /*
458
     * fill in the channels header at the start of this buffer
459
     */
460
    ch = channels + chan;
461
    cptr = packet->pk_buffer;
462
    *cptr++ = chan;
463
    *cptr = 0;
464
    packet->pk_length += CHAN_HEADER_SIZE;
465
 
466
    /*
467
     * OK, add this packet to the write queue, and try to flush it out
468
     */
469
 
470
    Adp_addToQueue(&writeQueueSend, packet);
471
    Adp_AsynchronousProcessing(mode);
472
 
473
    return adp_ok;
474
}
475
 
476
AdpErrs Adp_ChannelWrite(const ChannelID chan, Packet *packet) {
477
  return ChannelWrite(chan, packet, async_block_on_write);
478
}
479
 
480
AdpErrs Adp_ChannelWriteAsync(const ChannelID chan, Packet *packet) {
481
  return ChannelWrite(chan, packet, async_block_on_nothing);
482
}
483
 
484
static AdpErrs send_resend_msg(DeviceID devid) {
485
 
486
  /*
487
   * Send a resend message, usually in response to a bad packet or
488
   * a resend request */
489
  Packet * packet;
490
  packet = DevSW_AllocatePacket(CF_DATA_BYTE_POS);
491
  packet->pk_buffer[CF_CHANNEL_BYTE_POS] = CI_PRIVATE;
492
  packet->pk_buffer[CF_HOME_SEQ_BYTE_POS] = HomeSeq;
493
  packet->pk_buffer[CF_OPPO_SEQ_BYTE_POS] = OppoSeq;
494
  packet->pk_buffer[CF_FLAGS_BYTE_POS] = CF_RELIABLE | CF_RESEND;
495
  packet->pk_length = CF_DATA_BYTE_POS;
496
  return DevSW_Write(deviceToUse, packet, devid);
497
}
498
 
499
static AdpErrs check_seq(unsigned char msg_home, unsigned char msg_oppo) {
500
  Packet *tmp_pkt;
501
 
502
  UNUSED(msg_oppo);
503
  /*
504
   * check if we have got an ack for anything and if so remove it from the
505
   * queue
506
   */
507
  if (msg_home == (unsigned char)(OppoSeq+1)) {
508
    /*
509
     * arrived in sequence can increment our opposing seq number and remove
510
     * the relevant packet from our queue
511
     * check that the packet we're going to remove really is the right one
512
     */
513
    tmp_pkt = writeQueueRoot;
514
    while ((tmp_pkt->pk_next != NULL) &&
515
           (tmp_pkt->pk_next->pk_buffer[CF_HOME_SEQ_BYTE_POS]
516
            != OppoSeq)){
517
      tmp_pkt = tmp_pkt->pk_next;
518
    }
519
    OppoSeq++;
520
    if (tmp_pkt->pk_next == NULL) {
521
#ifdef DEBUG
522
      printf("trying to remove a non existant packet\n");
523
#endif
524
      return adp_bad_packet;
525
    }
526
    else {
527
      Packet *tmp = tmp_pkt->pk_next;
528
#ifdef RET_DEBUG
529
      printf("removing a packet from the root queue\n");
530
#endif
531
      tmp_pkt->pk_next = tmp_pkt->pk_next->pk_next;
532
      /* remove the appropriate packet */
533
      DevSW_FreePacket(tmp);
534
    return adp_ok;
535
    }
536
  }
537
  else if (msg_home < (unsigned char) (OppoSeq+1)){
538
    /* already received this message */
539
#ifdef RET_DEBUG
540
    printf("sequence numbers low\n");
541
#endif   
542
    return adp_seq_low;
543
  }
544
  else {  /* we've missed something */
545
#ifdef RET_DEBUG
546
    printf("sequence numbers high\n");
547
#endif   
548
    return adp_seq_high;
549
  }
550
}
551
 
552
static unsigned long tv_diff(const struct timeval *time_now,
553
                             const struct timeval *time_was)
554
{
555
    return (  ((time_now->tv_sec * 1000000) + time_now->tv_usec)
556
            - ((time_was->tv_sec * 1000000) + time_was->tv_usec) );
557
}
558
 
559
#if !defined(__unix) && !defined(__CYGWIN32__)
560
static void gettimeofday( struct timeval *time_now, void *dummy )
561
{
562
    time_t t = clock();
563
    UNUSED(dummy);
564
    time_now->tv_sec = t/CLOCKS_PER_SEC;
565
    time_now->tv_usec = (t%CLOCKS_PER_SEC)*(1000000/CLOCKS_PER_SEC);
566
}
567
#endif
568
 
569
static AdpErrs pacemaker(void)
570
{
571
  Packet *packet;
572
 
573
  packet = DevSW_AllocatePacket(CF_DATA_BYTE_POS);
574
  if (packet == NULL) {
575
    printf("ERROR: could not allocate a packet in pacemaker()\n");
576
    return adp_malloc_failure;
577
  }
578
  packet->pk_buffer[CF_CHANNEL_BYTE_POS] = CI_PRIVATE;
579
  packet->pk_buffer[CF_HOME_SEQ_BYTE_POS] = HomeSeq;
580
  packet->pk_buffer[CF_OPPO_SEQ_BYTE_POS] = OppoSeq;
581
  packet->pk_buffer[CF_FLAGS_BYTE_POS] = CF_RELIABLE | CF_HEARTBEAT;
582
  packet->pk_length = CF_DATA_BYTE_POS;
583
  return DevSW_Write(deviceToUse, packet, DC_DBUG);
584
}
585
 
586
#ifdef FAKE_BAD_LINE_RX
587
static AdpErrs fake_bad_line_rx( const Packet *const packet, AdpErrs adp_err )
588
{
589
    static unsigned int bl_num = 0;
590
 
591
    if (     (packet != NULL)
592
          && (bl_num++ >= 20 )
593
          && ((bl_num % FAKE_BAD_LINE_RX) == 0))
594
    {
595
        printf("DEBUG: faking a bad packet\n");
596
        return adp_bad_packet;
597
    }
598
    return adp_err;
599
}
600
#endif /* def FAKE_BAD_LINE_RX */
601
 
602
#ifdef FAKE_BAD_LINE_TX
603
static unsigned char tmp_ch;
604
 
605
static void fake_bad_line_tx( void )
606
{
607
    static unsigned int bl_num = 0;
608
 
609
    /* give the thing a chance to boot then try corrupting stuff */
610
    if ( (bl_num++ >= 20) && ((bl_num % FAKE_BAD_LINE_TX) == 0))
611
    {
612
        printf("DEBUG: faking a bad packet for tx\n");
613
        tmp_ch = writeQueueSend->pk_buffer[CF_FLAGS_BYTE_POS];
614
        writeQueueSend->pk_buffer[CF_FLAGS_BYTE_POS] = 77;
615
    }
616
}
617
 
618
static void unfake_bad_line_tx( void )
619
{
620
    static unsigned int bl_num = 0;
621
 
622
    /*
623
     * must reset the packet so that its not corrupted when we
624
     *  resend it
625
     */
626
    if ( (bl_num >= 20) && ((bl_num % FAKE_BAD_LINE_TX) != 0))
627
    {
628
        writeQueueSend->pk_buffer[CF_FLAGS_BYTE_POS] = tmp_ch;
629
    }
630
}
631
#endif /* def FAKE_BAD_LINE_TX */
632
 
633
/*
634
 * NOTE: we are assuming that a resolution of microseconds will
635
 * be good enough for the purporses of the heartbeat.  If this proves
636
 * not to be the case then we may need a rethink, possibly using
637
 * [get,set]itimer
638
 */
639
static struct timeval time_now;
640
static struct timeval time_lastalive;
641
 
642
static void async_process_dbug_read( const AsyncMode mode,
643
                                     bool *const finished  )
644
{
645
    Packet *packet;
646
    unsigned int msg_home, msg_oppo;
647
    AdpErrs adp_err;
648
 
649
    adp_err = DevSW_Read(deviceToUse, DC_DBUG, &packet,
650
                         mode == async_block_on_read    );
651
 
652
#ifdef FAKE_BAD_LINE_RX
653
    adp_err = fake_bad_line_rx( packet, adp_err );
654
#endif
655
 
656
    if (adp_err == adp_bad_packet) {
657
        /* We got a bad packet, ask for a resend, send a resend message */
658
#ifdef DEBUG
659
        printf("received a bad packet\n");
660
#endif
661
        send_resend_msg(DC_DBUG);
662
    }
663
    else if (packet != NULL)
664
    {
665
        /* update the heartbeat clock */
666
        gettimeofday(&time_lastalive, NULL);
667
 
668
            /*
669
             * we got a live one here - were we waiting for it?
670
             */
671
        if (mode == async_block_on_read)
672
           /* not any more */
673
           *finished = TRUE;
674
#ifdef RETRANS
675
 
676
        if (packet->pk_length < CF_DATA_BYTE_POS) {
677
            /* we've got a packet with no header information! */
678
            printf("ERROR: packet with no transport header\n");
679
            send_resend_msg(DC_DBUG);
680
        }
681
        else {
682
#ifdef RET_DEBUG
683
            unsigned int c;
684
#endif
685
            /*
686
             * TODO: Check to see if its acknowledgeing anything, remove
687
             * those packets it is from the queue.  If its a retrans add the
688
             * packets to the queue
689
             */
690
            msg_home = packet->pk_buffer[CF_HOME_SEQ_BYTE_POS];
691
            msg_oppo = packet->pk_buffer[CF_OPPO_SEQ_BYTE_POS];
692
#ifdef RET_DEBUG
693
            printf("msg seq numbers are hseq 0x%x oseq 0x%x\n",
694
                   msg_home, msg_oppo);
695
            for (c=0;c<packet->pk_length;c++)
696
               printf("%02.2x", packet->pk_buffer[c]);
697
            printf("\n");
698
#endif
699
            /* now was it a resend request? */
700
            if ((packet->pk_buffer[CF_FLAGS_BYTE_POS])
701
                & CF_RESEND) {
702
                /* we've been asked for a resend so we had better resend */
703
                /*
704
                 * I don't think we can use a resend as acknowledgement for
705
                 * anything so lets not do this for the moment
706
                 * check_seq(msg_home, msg_oppo);
707
                 */
708
#ifdef RET_DEBUG
709
                printf("received a resend request\n");
710
#endif
711
                if (HomeSeq != msg_oppo) {
712
                    int found = FALSE;
713
                    /* need to resend from msg_oppo +1 upwards */
714
                    DevSW_FreePacket(packet);
715
                    resending = TRUE;
716
                    /* find the correct packet to resend from */
717
                    packet = writeQueueRoot;
718
                    while (((packet->pk_next) != NULL) && !found) {
719
                        if ((packet->pk_buffer[CF_OPPO_SEQ_BYTE_POS])
720
                            != msg_oppo+1) {
721
                            resend_pkt = packet;
722
                            found = TRUE;
723
                        }
724
                        packet = packet->pk_next;
725
                    }
726
                    if (!found) {
727
                        panic("trying to resend non-existent packets\n");
728
                    }
729
                }
730
                else if (OppoSeq != msg_home) {
731
                    /*
732
                     * send a resend request telling the target where we think
733
                     * the world is at
734
                     */
735
                    DevSW_FreePacket(packet);
736
                    send_resend_msg(DC_DBUG);
737
                }
738
            }
739
            else {
740
                /* not a resend request, lets check the sequence numbers */
741
 
742
                if ((packet->pk_buffer[CF_CHANNEL_BYTE_POS] != CI_HBOOT) &&
743
                    (packet->pk_buffer[CF_CHANNEL_BYTE_POS] != CI_TBOOT)) {
744
                    adp_err = check_seq(msg_home, msg_oppo);
745
                    if (adp_err == adp_seq_low) {
746
                        /* we have already received this packet so discard */
747
                        DevSW_FreePacket(packet);
748
                    }
749
                    else if (adp_err == adp_seq_high) {
750
                        /*
751
                         * we must have missed a packet somewhere, discard this
752
                         * packet and tell the target where we are
753
                         */
754
                        DevSW_FreePacket(packet);
755
                        send_resend_msg(DC_DBUG);
756
                    }
757
                    else
758
                       /*
759
                        * now pass the packet to whoever is waiting for it
760
                        */
761
                       FireCallback(packet);
762
                }
763
                else
764
                   FireCallback(packet);
765
            }
766
        }
767
#else
768
        /*
769
             * now pass the packet to whoever is waiting for it
770
             */
771
        FireCallback(packet);
772
#endif
773
    }
774
}
775
 
776
static void async_process_appl_read(void)
777
{
778
    Packet *packet;
779
    AdpErrs adp_err;
780
 
781
    /* see if there is anything for the DC_APPL channel */
782
    adp_err = DevSW_Read(deviceToUse, DC_APPL, &packet, FALSE);
783
 
784
    if (adp_err == adp_ok && packet != NULL)
785
    {
786
        /* got an application packet on a shared device */
787
 
788
#ifdef DEBUG
789
        printf("GOT DC_APPL PACKET: len %d\nData: ", packet->pk_length);
790
        {
791
            unsigned int c;
792
            for ( c = 0; c < packet->pk_length; ++c )
793
               printf( "%02X ", packet->pk_buffer[c] );
794
        }
795
        printf("\n");
796
#endif
797
 
798
        if (dc_appl_handler != NULL)
799
        {
800
            dc_appl_handler( deviceToUse, packet );
801
        }
802
        else
803
        {
804
            /* for now, just free it!! */
805
#ifdef DEBUG
806
            printf("no handler - dropping DC_APPL packet\n");
807
#endif
808
            DevSW_FreePacket( packet );
809
        }
810
    }
811
}
812
 
813
static void async_process_write( const AsyncMode mode,
814
                                 bool *const finished  )
815
{
816
    Packet *packet;
817
 
818
#ifdef DEBUG
819
    static unsigned int num_written = 0;
820
#endif
821
 
822
    /*
823
     * NOTE: here we rely in the fact that any packet in the writeQueueSend
824
     * section of the queue will need its sequence number setting up while
825
     * and packet in the writeQueueRoot section will have its sequence
826
     * numbers set up from when it was first sent so we can easily look
827
     * up the packet numbers when(if) we want to resend the packet.
828
     */
829
 
830
#ifdef DEBUG
831
    if (writeQueueSend!=NULL)
832
       printf("written 0x%x\n",num_written += writeQueueSend->pk_length);
833
#endif
834
    /*
835
     * give the switcher a chance to complete any partial writes
836
     */
837
    if (DevSW_FlushPendingWrite(deviceToUse) == adp_write_busy)
838
    {
839
        /* no point trying a new write */
840
        return;
841
    }
842
 
843
    /*
844
     * now see whether there is anything to write
845
     */
846
    packet = NULL;
847
    if (resending) {
848
        packet = resend_pkt;
849
#ifdef RET_DEBUG
850
        printf("resending hseq 0x%x oseq 0x%x\n",
851
               packet->pk_buffer[CF_HOME_SEQ_BYTE_POS],
852
               packet->pk_buffer[CF_OPPO_SEQ_BYTE_POS]);
853
#endif
854
    }
855
    else if (writeQueueSend != NULL) {
856
#ifdef RETRANS
857
        /* set up the sequence number on the packet */
858
        packet = writeQueueSend;
859
        HomeSeq++;
860
        (writeQueueSend->pk_buffer[CF_OPPO_SEQ_BYTE_POS])
861
            = OppoSeq;
862
        (writeQueueSend->pk_buffer[CF_HOME_SEQ_BYTE_POS])
863
            = HomeSeq;
864
        (writeQueueSend->pk_buffer[CF_FLAGS_BYTE_POS])
865
            = CF_RELIABLE;
866
# ifdef RET_DEBUG
867
        printf("sending packet with hseq 0x%x oseq 0x%x\n",
868
               writeQueueSend->pk_buffer[CF_HOME_SEQ_BYTE_POS],
869
               writeQueueSend->pk_buffer[CF_OPPO_SEQ_BYTE_POS]);
870
# endif
871
#endif /* RETRANS */
872
    }
873
 
874
    if (packet != NULL) {
875
        AdpErrs dev_err;
876
 
877
#ifdef FAKE_BAD_LINE_TX
878
        fake_bad_line_tx();
879
#endif
880
 
881
        dev_err = DevSW_Write(deviceToUse, packet, DC_DBUG);
882
        if (dev_err == adp_ok) {
883
#ifdef RETRANS
884
            if (resending) {
885
                /* check to see if we've recovered yet */
886
                if ((packet->pk_next) == NULL){
887
# ifdef RET_DEBUG
888
                    printf("we have recovered\n");
889
# endif
890
                    resending = FALSE;
891
                }
892
                else {
893
                    resend_pkt = resend_pkt->pk_next;
894
                }
895
            }
896
            else {
897
                /*
898
                 * move the packet we just sent from the send queue to the root
899
                 */
900
                Packet *tmp_pkt, *tmp;
901
 
902
# ifdef FAKE_BAD_LINE_TX
903
                unfake_bad_line_tx();
904
# endif
905
 
906
                tmp_pkt = writeQueueSend;
907
                writeQueueSend = writeQueueSend->pk_next;
908
                tmp_pkt->pk_next = NULL;
909
                if (writeQueueRoot == NULL)
910
                   writeQueueRoot = tmp_pkt;
911
                else {
912
                    tmp = writeQueueRoot;
913
                    while (tmp->pk_next != NULL) {
914
                        tmp = tmp->pk_next;
915
                    }
916
                    tmp->pk_next = tmp_pkt;
917
                }
918
            }
919
#else  /* not RETRANS */
920
            /*
921
             * switcher has taken the write, so remove it from the
922
             * queue, and free its resources
923
             */
924
            DevSW_FreePacket(Adp_removeFromQueue(&writeQueueSend));
925
#endif /* if RETRANS ... else ... */
926
 
927
            if (mode == async_block_on_write)
928
               *finished = DevSW_WriteFinished(deviceToUse);
929
 
930
        } /* endif write ok */
931
    }
932
    else /* packet == NULL */
933
    {
934
        if (mode == async_block_on_write)
935
           *finished = DevSW_WriteFinished(deviceToUse);
936
    }
937
}
938
 
939
static void async_process_heartbeat( void )
940
{
941
    /* check to see whether we need to send a heartbeat */
942
    gettimeofday(&time_now, NULL);
943
 
944
    if (tv_diff(&time_now, &time_lastalive) >= HEARTRATE)
945
    {
946
        /*
947
         * if we've not booted then don't do send a heartrate the link
948
         * must be reliable enough for us to boot without any clever stuff,
949
         * if we can't do this then theres little chance of the link staying
950
         * together even with the resends etc
951
         */
952
        if (heartbeat_enabled) {
953
            gettimeofday(&time_lastalive, NULL);
954
            pacemaker();
955
        }
956
    }
957
}
958
 
959
static void async_process_callbacks( void )
960
{
961
    /* call any registered asynchronous callbacks */
962
    unsigned int i;
963
    for ( i = 0; i < num_async_callbacks; ++i )
964
       async_callbacks[i]( deviceToUse, &time_now );
965
}
966
 
967
void Adp_AsynchronousProcessing(const AsyncMode mode)
968
{
969
    bool finished = FALSE;
970
#ifdef DEBUG
971
    unsigned int wc = 0, dc = 0, ac = 0, hc = 0;
972
# define INC_COUNT(x) ((x)++)
973
#else
974
# define INC_COUNT(x)
975
#endif
976
 
977
    if ((time_lastalive.tv_sec == 0) && (time_lastalive.tv_usec == 0)) {
978
      /* first time through, needs initing */
979
      gettimeofday(&time_lastalive, NULL);
980
    }
981
 
982
    /* main loop */
983
    do
984
    {
985
        async_process_write( mode, &finished );
986
        INC_COUNT(wc);
987
 
988
        if ( ! finished && mode != async_block_on_write )
989
        {
990
            async_process_dbug_read( mode, &finished );
991
            INC_COUNT(dc);
992
        }
993
 
994
        if ( ! finished && mode != async_block_on_write )
995
        {
996
           async_process_appl_read();
997
           INC_COUNT(ac);
998
        }
999
 
1000
        if ( ! finished )
1001
        {
1002
          if (heartbeat_configured)
1003
            async_process_heartbeat();
1004
          async_process_callbacks();
1005
          INC_COUNT(hc);
1006
        }
1007
 
1008
    } while (!finished && mode != async_block_on_nothing);
1009
 
1010
#ifdef DEBUG
1011
    if ( mode != async_block_on_nothing )
1012
       printf( "Async: %s - w %d, d %d, a %d, h %d\n",
1013
               mode == async_block_on_write ? "blk_write" : "blk_read",
1014
               wc, dc, ac, hc );
1015
#endif
1016
}
1017
 
1018
/*
1019
 * install a handler for DC_APPL packets (can be NULL), returning old one.
1020
 */
1021
DC_Appl_Handler Adp_Install_DC_Appl_Handler(const DC_Appl_Handler handler)
1022
{
1023
    DC_Appl_Handler old_handler = dc_appl_handler;
1024
 
1025
#ifdef DEBUG
1026
    printf( "Installing DC_APPL handler %x (old %x)\n", handler, old_handler );
1027
#endif
1028
 
1029
    dc_appl_handler = handler;
1030
    return old_handler;
1031
}
1032
 
1033
 
1034
/*
1035
 * add an asynchronous processing callback to the list
1036
 * TRUE == okay, FALSE == no more async processing slots
1037
 */
1038
bool Adp_Install_Async_Callback( const Adp_Async_Callback callback_proc )
1039
{
1040
    if ( num_async_callbacks < MAX_ASYNC_CALLBACKS && callback_proc != NULL )
1041
    {
1042
        async_callbacks[num_async_callbacks] = callback_proc;
1043
        ++num_async_callbacks;
1044
        return TRUE;
1045
    }
1046
    else
1047
       return FALSE;
1048
}
1049
 
1050
 
1051
/*
1052
 * delay for a given period (in microseconds)
1053
 */
1054
void Adp_delay(unsigned int period)
1055
{
1056
    struct timeval tv;
1057
 
1058
#ifdef DEBUG
1059
    printf("delaying for %d microseconds\n", period);
1060
#endif
1061
    tv.tv_sec = (period / 1000000);
1062
    tv.tv_usec = (period % 1000000);
1063
 
1064
    (void)select(0, NULL, NULL, NULL, &tv);
1065
}
1066
 
1067
/* EOF hostchan.c */

powered by: WebSVN 2.1.0

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