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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [insight/] [gdb/] [rdi-share/] [serpardr.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 578 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: 2002-01-16 10:24:34 $
13
 *
14
 *
15
 * serpardv.c - Serial/Parallel Driver for Angel.
16
 */
17
#include <stdio.h>
18
#include <stdlib.h>
19
#include <string.h>
20
 
21
#include "crc.h"
22
#include "devices.h"
23
#include "buffers.h"
24
#include "rxtx.h"
25
#include "hostchan.h"
26
#include "params.h"
27
#include "logging.h"
28
#include "hsys.h"
29
 
30
#ifdef COMPILING_ON_WINDOWS
31
#  undef   ERROR
32
#  undef   IGNORE
33
#  include <windows.h>
34
#  include "angeldll.h"
35
#  include "comb_api.h"
36
#else
37
#  ifdef __hpux
38
#    define _TERMIOS_INCLUDED
39
#    include <sys/termio.h>
40
#    undef _TERMIOS_INCLUDED
41
#  else
42
#    include <termios.h>
43
#  endif
44
#  include "unixcomm.h"
45
#endif
46
 
47
#ifndef UNUSED
48
#  define UNUSED(x) (x = x)     /* Silence compiler warnings */
49
#endif
50
 
51
#define MAXREADSIZE     512
52
#define MAXWRITESIZE    512
53
 
54
#define SERPAR_FC_SET  ((1 << serial_XON) | (1 << serial_XOFF))
55
#define SERPAR_CTL_SET ((1 << serial_STX) | (1 << serial_ETX) | \
56
                        (1 << serial_ESC))
57
#define SERPAR_ESC_SET (SERPAR_FC_SET | SERPAR_CTL_SET)
58
 
59
static const struct re_config config = {
60
    serial_STX, serial_ETX, serial_ESC, /* self-explanatory?               */
61
    SERPAR_FC_SET,                      /* set of flow-control characters  */
62
    SERPAR_ESC_SET,                     /* set of characters to be escaped */
63
    NULL,                               /* serial_flow_control */
64
    NULL,                               /* what to do with FC chars */
65
    angel_DD_RxEng_BufferAlloc, NULL    /* how to get a buffer */
66
};
67
 
68
static struct re_state rxstate;
69
 
70
/*
71
 * structure used for manipulating transmit data
72
 */
73
typedef struct TxState
74
{
75
    struct te_state state;
76
    unsigned int    index;
77
    unsigned char   writebuf[MAXWRITESIZE];
78
} TxState;
79
 
80
/*
81
 * The set of parameter options supported by the device
82
 */
83
static unsigned int baud_options[] =
84
{
85
#ifdef __hpux
86
    115200, 57600,
87
#endif
88
    38400, 19200, 9600
89
};
90
 
91
static ParameterList param_list[] =
92
{
93
    {
94
        AP_BAUD_RATE,
95
        sizeof(baud_options) / sizeof(unsigned int),
96
        baud_options
97
    }
98
};
99
 
100
static const ParameterOptions serpar_options =
101
{
102
    sizeof(param_list) / sizeof(ParameterList),
103
    param_list
104
};
105
 
106
/*
107
 * The default parameter config for the device
108
 */
109
static Parameter param_default[] =
110
{
111
    { AP_BAUD_RATE, 9600 }
112
};
113
 
114
static const ParameterConfig serpar_defaults =
115
{
116
    sizeof(param_default)/sizeof(Parameter),
117
    param_default
118
};
119
 
120
/*
121
 * The user-modified options for the device
122
 */
123
static unsigned int user_baud_options[sizeof(baud_options) /
124
                                     sizeof(unsigned int)];
125
 
126
static ParameterList param_user_list[] =
127
{
128
    {
129
        AP_BAUD_RATE,
130
        sizeof(user_baud_options) / sizeof(unsigned),
131
        user_baud_options
132
    }
133
};
134
 
135
static ParameterOptions user_options =
136
{
137
    sizeof(param_user_list) / sizeof(ParameterList),
138
    param_user_list
139
};
140
 
141
static bool user_options_set;
142
 
143
/* forward declarations */
144
static int serpar_reset(void);
145
static int serpar_set_params(const ParameterConfig *config);
146
static int SerparMatch(const char *name, const char *arg);
147
 
148
static void process_baud_rate(unsigned int target_baud_rate)
149
{
150
    const ParameterList *full_list;
151
    ParameterList       *user_list;
152
 
153
    /* create subset of full options */
154
    full_list = Angel_FindParamList(&serpar_options, AP_BAUD_RATE);
155
    user_list = Angel_FindParamList(&user_options,   AP_BAUD_RATE);
156
 
157
    if (full_list != NULL && user_list != NULL)
158
    {
159
        unsigned int i, j;
160
        unsigned int def_baud = 0;
161
 
162
        /* find lower or equal to */
163
        for (i = 0; i < full_list->num_options; ++i)
164
           if (target_baud_rate >= full_list->option[i])
165
           {
166
               /* copy remaining */
167
               for (j = 0; j < (full_list->num_options - i); ++j)
168
                  user_list->option[j] = full_list->option[i+j];
169
               user_list->num_options = j;
170
 
171
               /* check this is not the default */
172
               Angel_FindParam(AP_BAUD_RATE, &serpar_defaults, &def_baud);
173
               if ((j == 1) && (user_list->option[0] == def_baud))
174
               {
175
#ifdef DEBUG
176
                   printf("user selected default\n");
177
#endif
178
               }
179
               else
180
               {
181
                   user_options_set = TRUE;
182
#ifdef DEBUG
183
                   printf("user options are: ");
184
                   for (j = 0; j < user_list->num_options; ++j)
185
                      printf("%u ", user_list->option[j]);
186
                   printf("\n");
187
#endif
188
               }
189
 
190
               break;   /* out of i loop */
191
           }
192
 
193
#ifdef DEBUG
194
        if (i >= full_list->num_options)
195
           printf("couldn't match baud rate %u\n", target_baud_rate);
196
#endif
197
    }
198
#ifdef DEBUG
199
    else
200
       printf("failed to find lists\n");
201
#endif
202
}
203
 
204
static int SerparOpen(const char *name, const char *arg)
205
{
206
    char *sername = NULL;
207
    char *parname = NULL;
208
 
209
#ifdef DEBUG
210
    printf("SerparOpen: name %s arg %s\n", name, arg ? arg : "<NULL>");
211
#endif
212
 
213
#ifdef COMPILING_ON_WINDOWS
214
    if (IsOpenSerial() || IsOpenParallel()) return -1;
215
#else
216
    if (Unix_IsSerialInUse() || Unix_IsParallelInUse()) return -1;
217
#endif
218
 
219
#ifdef COMPILING_ON_WINDOWS
220
    if (SerparMatch(name, arg) == -1)
221
        return -1;
222
#else
223
    Unix_IsValidParallelDevice(name,&sername,&parname);
224
# ifdef DEBUG
225
    printf("translated %s to serial %s and parallel %s\n",
226
           name==0 ? "NULL" : name,
227
           sername==0 ? "NULL" : sername,
228
           parname==0 ? "NULL" : parname);
229
# endif
230
    if (sername==NULL || parname==NULL) return -1;
231
#endif
232
 
233
    user_options_set = FALSE;
234
 
235
    /* interpret and store the arguments */
236
    if (arg != NULL)
237
    {
238
        unsigned int target_baud_rate;
239
 
240
        target_baud_rate = (unsigned int)strtoul(arg, NULL, 10);
241
 
242
        if (target_baud_rate > 0)
243
        {
244
#ifdef DEBUG
245
            printf("user selected baud rate %u\n", target_baud_rate);
246
#endif
247
            process_baud_rate(target_baud_rate);
248
        }
249
#ifdef DEBUG
250
        else
251
            printf("could not understand baud rate %s\n", arg);
252
#endif
253
    }
254
 
255
#ifdef COMPILING_ON_WINDOWS
256
    {
257
        /*
258
         * The serial port number is in name[0] followed by
259
         * the parallel port number in name[1]
260
         */
261
 
262
        int sport = name[0] - '0';
263
        int pport = name[1] - '0';
264
 
265
        if (OpenParallel(pport) != COM_OK)
266
            return -1;
267
 
268
        if (OpenSerial(sport, FALSE) != COM_OK)
269
        {
270
            CloseParallel();
271
            return -1;
272
        }
273
    }
274
#else
275
    Unix_OpenParallel(parname);
276
    Unix_OpenSerial(sername);
277
#endif
278
 
279
    serpar_reset();
280
 
281
#if defined(__unix) || defined(__CYGWIN32__)
282
    Unix_ioctlNonBlocking();
283
#endif
284
 
285
    Angel_RxEngineInit(&config, &rxstate);
286
 
287
    return 0;
288
}
289
 
290
#ifdef COMPILING_ON_WINDOWS
291
static int SerparMatch(const char *name, const char *arg)
292
{
293
    char sername[2];
294
    char parname[2];
295
 
296
    UNUSED(arg);
297
 
298
    sername[0] = name[0];
299
    parname[0] = name[1];
300
    sername[1] = parname[1] = 0;
301
 
302
    if (IsValidDevice(sername) == COM_DEVICENOTVALID ||
303
        IsValidDevice(parname) == COM_DEVICENOTVALID)
304
        return -1;
305
    else
306
        return 0;
307
}
308
#else
309
static int SerparMatch(const char *portstring, const char *arg)
310
{
311
    char *sername=NULL, *parname=NULL;
312
    UNUSED(arg);
313
 
314
    Unix_IsValidParallelDevice(portstring,&sername,&parname);
315
 
316
      /* Match failed if either sername or parname are still NULL */
317
    if (sername==NULL || parname==NULL) return -1;
318
    return 0;
319
}
320
#endif
321
 
322
static void SerparClose(void)
323
{
324
#ifdef COMPILING_ON_WINDOWS
325
    CloseParallel();
326
    CloseSerial();
327
#else
328
    Unix_CloseParallel();
329
    Unix_CloseSerial();
330
#endif
331
}
332
 
333
static int SerparRead(DriverCall *dc, bool block)
334
{
335
    static unsigned char readbuf[MAXREADSIZE];
336
    static int rbindex = 0;
337
 
338
    int nread;
339
    int read_errno;
340
    int c = 0;
341
    re_status restatus;
342
    int ret_code = -1;            /* assume bad packet or error */
343
 
344
    /*
345
     * we must not overflow buffer, and must start after
346
     * the existing data
347
     */
348
#ifdef COMPILING_ON_WINDOWS
349
    {
350
        BOOL dummy = FALSE;
351
        nread = BytesInRXBufferSerial();
352
 
353
        if (nread > MAXREADSIZE - rbindex)
354
            nread = MAXREADSIZE - rbindex;
355
        read_errno = ReadSerial(readbuf+rbindex, nread, &dummy);
356
        if (pfnProgressCallback != NULL && read_errno == COM_OK)
357
        {
358
            progressInfo.nRead += nread;
359
            (*pfnProgressCallback)(&progressInfo);
360
        }
361
    }
362
#else
363
    nread = Unix_ReadSerial(readbuf+rbindex, MAXREADSIZE-rbindex, block);
364
    read_errno = errno;
365
#endif
366
 
367
    if ((nread > 0) || (rbindex > 0))
368
    {
369
#ifdef DO_TRACE
370
        printf("[%d@%d] ", nread, rbindex);
371
#endif
372
 
373
        if (nread > 0)
374
            rbindex = rbindex + nread;
375
 
376
        do
377
        {
378
            restatus = Angel_RxEngine(readbuf[c], &(dc->dc_packet), &rxstate);
379
 
380
#ifdef DO_TRACE
381
            printf("<%02X ",readbuf[c]);
382
#endif
383
            c++;
384
        } while (c < rbindex &&
385
                 ((restatus == RS_IN_PKT) || (restatus == RS_WAIT_PKT)));
386
 
387
#ifdef DO_TRACE
388
        printf("\n");
389
#endif
390
 
391
        switch(restatus)
392
        {
393
          case RS_GOOD_PKT:
394
              ret_code = 1;
395
              /* fall through to: */
396
 
397
          case RS_BAD_PKT:
398
              /*
399
               * We now need to shuffle any left over data down to the
400
               * beginning of our private buffer ready to be used
401
               *for the next packet
402
               */
403
#ifdef DO_TRACE
404
              printf("SerparRead() processed %d, moving down %d\n",
405
                     c, rbindex - c);
406
#endif
407
 
408
              if (c != rbindex)
409
                  memmove((char *) readbuf, (char *) (readbuf + c), rbindex - c);
410
 
411
              rbindex -= c;
412
 
413
              break;
414
 
415
          case RS_IN_PKT:
416
          case RS_WAIT_PKT:
417
              rbindex = 0;            /* will have processed all we had */
418
              ret_code = 0;
419
              break;
420
 
421
          default:
422
#ifdef DEBUG
423
              printf("Bad re_status in SerparRead()\n");
424
#endif
425
              break;
426
        }
427
    }
428
    else if (nread == 0)
429
        /* nothing to read */
430
        ret_code = 0;
431
    else if (read_errno == ERRNO_FOR_BLOCKED_IO) /* nread < 0 */
432
        ret_code = 0;
433
 
434
#ifdef DEBUG
435
    if ((nread < 0) && (read_errno != ERRNO_FOR_BLOCKED_IO))
436
        perror("read() error in SerparRead()");
437
#endif
438
 
439
    return ret_code;
440
}
441
 
442
/*
443
 *  Function: send_packet
444
 *   Purpose: Send a stream of bytes to Angel through the parallel port
445
 *
446
 * Algorithm: We need to present the data in a form that all boards can
447
 *            swallow.  With the PID board, this is a problem: for reasons
448
 *            described in the driver (angel/pid/st16c552.c), data are
449
 *            sent a nybble at a time on D0-D2 and D4; D3 is wired to ACK,
450
 *            which generates an interrupt when it goes low.  This routine
451
 *            fills in an array of nybbles, with ACK clear in all but the
452
 *            last one.  If, for whatever reason, the write fails, then
453
 *            ACK is forced high (thereby enabling the next write a chance
454
 *            to be noticed when the falling edge of ACK generates an
455
 *            interrupt (hopefully).
456
 *
457
 *    Params:
458
 *       Input: txstate Contains the packet to be sent
459
 *
460
 *   Returns: Number of *complete* bytes written
461
 */
462
 
463
static int SerparWrite(DriverCall *dc)
464
{
465
    te_status status;
466
    int nwritten = 0;
467
    static TxState txstate;
468
 
469
    /*
470
     * is this a new packet?
471
     */
472
    if (dc->dc_context == NULL)
473
    {
474
        /*
475
         * yes - initialise TxEngine
476
         */
477
        Angel_TxEngineInit(&config, &dc->dc_packet, &txstate.state);
478
 
479
        txstate.index = 0;
480
        dc->dc_context = &txstate;
481
    }
482
 
483
    /*
484
     * fill the buffer using the Tx Engine
485
     */
486
    do
487
    {
488
        status = Angel_TxEngine(&dc->dc_packet, &txstate.state,
489
                                &txstate.writebuf[txstate.index]);
490
        if (status != TS_IDLE) txstate.index++;
491
 
492
    } while (status == TS_IN_PKT && txstate.index < MAXWRITESIZE);
493
 
494
#ifdef DO_TRACE
495
    {
496
        unsigned int i = 0;
497
 
498
        while (i < txstate.index)
499
        {
500
            printf(">%02X ", txstate.writebuf[i]);
501
 
502
            if (!(++i % 16))
503
                putc('\n', stdout);
504
        }
505
 
506
        if (i % 16)
507
            putc('\n', stdout);
508
    }
509
#endif
510
 
511
    /*
512
     * the data are ready, all we need now is to send them out
513
     * in a form that Angel can swallow.
514
     */
515
#ifdef COMPILING_ON_WINDOWS
516
  if (WriteParallel(txstate.writebuf, txstate.index) == COM_OK)
517
  {
518
    nwritten = txstate.index;
519
    if (pfnProgressCallback != NULL)
520
    {
521
      progressInfo.nWritten += nwritten;
522
      (*pfnProgressCallback)(&progressInfo);
523
    }
524
  }
525
  else
526
  {
527
      MessageBox(GetFocus(), "Write error\n", "Angel", MB_OK | MB_ICONSTOP);
528
      return -1;   /* SJ - This really needs to return a value, which is picked up in */
529
                   /*      DevSW_Read as meaning stop debugger but don't kill. */
530
  }
531
#else
532
    nwritten = Unix_WriteParallel(txstate.writebuf, txstate.index);
533
#endif
534
 
535
    if (nwritten < 0) nwritten = 0;
536
 
537
#ifdef DO_TRACE
538
    printf("SerparWrite: wrote %d out of %d bytes\n",
539
           nwritten, txstate.index);
540
#endif
541
 
542
    /*
543
     * has the whole packet gone?
544
     */
545
    if (nwritten == (int)txstate.index &&
546
        (status == TS_DONE_PKT || status == TS_IDLE))
547
        /*
548
         * yes it has
549
         */
550
        return 1;
551
    else
552
    {
553
        /*
554
         * if some data are left, shuffle them
555
         * to the start of the buffer
556
         */
557
        if (nwritten != (int)txstate.index && nwritten != 0)
558
        {
559
            txstate.index -= nwritten;
560
            (void)memmove((char *) txstate.writebuf,
561
                          (char *) (txstate.writebuf + nwritten),
562
                          txstate.index);
563
        }
564
        else if (nwritten == (int)txstate.index)
565
            txstate.index = 0;
566
 
567
        return 0;
568
    }
569
}
570
 
571
static int serpar_reset(void)
572
{
573
#ifdef COMPILING_ON_WINDOWS
574
    FlushParallel();
575
    FlushSerial();
576
#else
577
    Unix_ResetParallel();
578
    Unix_ResetSerial();
579
#endif
580
 
581
    return serpar_set_params(&serpar_defaults);
582
}
583
 
584
static int find_baud_rate(unsigned int *speed)
585
{
586
    static struct
587
    {
588
        unsigned int baud;
589
        int termiosValue;
590
    } possibleBaudRates[] =
591
      {
592
#if defined(__hpux)
593
          {115200, _B115200}, {57600, _B57600},
594
#endif
595
#ifdef COMPILING_ON_WINDOWS
596
        {38400, CBR_38400}, {19200, CBR_19200}, {9600, CBR_9600}, {0, 0}
597
#else
598
        {38400, B38400}, {19200, B19200}, {9600, B9600}, {0, 0}
599
#endif
600
    };
601
    unsigned int i;
602
 
603
    /* look for lower or matching -- will always terminate at 0 end marker */
604
    for (i = 0; possibleBaudRates[i].baud > *speed; ++i)
605
        /* do nothing */
606
        ;
607
 
608
    if (possibleBaudRates[i].baud > 0)
609
       *speed = possibleBaudRates[i].baud;
610
 
611
    return possibleBaudRates[i].termiosValue;
612
}
613
 
614
static int serpar_set_params(const ParameterConfig *config)
615
{
616
    unsigned int speed;
617
    int termios_value;
618
 
619
#ifdef DEBUG
620
    printf("serpar_set_params\n");
621
#endif
622
 
623
    if (!Angel_FindParam(AP_BAUD_RATE, config, &speed))
624
    {
625
#ifdef DEBUG
626
        printf("speed not found in config\n");
627
#endif
628
        return DE_OKAY;
629
    }
630
 
631
    termios_value = find_baud_rate(&speed);
632
    if (termios_value == 0)
633
    {
634
#ifdef DEBUG
635
        printf("speed not valid: %u\n", speed);
636
#endif
637
        return DE_OKAY;
638
    }
639
 
640
#ifdef DEBUG
641
    printf("setting speed to %u\n", speed);
642
#endif
643
 
644
#ifdef COMPILING_ON_WINDOWS
645
    SetBaudRate((WORD)termios_value);
646
#else
647
    Unix_SetSerialBaudRate(termios_value);
648
#endif
649
 
650
    return DE_OKAY;
651
}
652
 
653
 
654
static int serpar_get_user_params(ParameterOptions **p_options)
655
{
656
#ifdef DEBUG
657
    printf("serpar_get_user_params\n");
658
#endif
659
 
660
    if (user_options_set)
661
    {
662
        *p_options = &user_options;
663
    }
664
    else
665
    {
666
        *p_options = NULL;
667
    }
668
 
669
    return DE_OKAY;
670
}
671
 
672
 
673
static int serial_get_default_params( const ParameterConfig **p_config )
674
{
675
#ifdef DEBUG
676
    printf( "serial_get_default_params\n" );
677
#endif
678
 
679
    *p_config = &serpar_defaults;
680
    return DE_OKAY;
681
}
682
 
683
 
684
static int SerparIoctl(const int opcode, void *args)
685
{
686
    int ret_code;
687
 
688
#ifdef DEBUG
689
    printf("SerparIoctl: op %d arg %p\n", opcode, args ? args : "<NULL>");
690
#endif
691
 
692
    switch (opcode)
693
    {
694
       case DC_RESET:
695
           ret_code = serpar_reset();
696
           break;
697
 
698
       case DC_SET_PARAMS:
699
           ret_code = serpar_set_params((const ParameterConfig *)args);
700
           break;
701
 
702
       case DC_GET_USER_PARAMS:
703
           ret_code = serpar_get_user_params((ParameterOptions **)args);
704
           break;
705
 
706
       case DC_GET_DEFAULT_PARAMS:
707
           ret_code =
708
               serial_get_default_params((const ParameterConfig **)args);
709
           break;
710
 
711
       default:
712
           ret_code = DE_BAD_OP;
713
           break;
714
    }
715
 
716
  return ret_code;
717
}
718
 
719
DeviceDescr angel_SerparDevice =
720
{
721
    "SERPAR",
722
    SerparOpen,
723
    SerparMatch,
724
    SerparClose,
725
    SerparRead,
726
    SerparWrite,
727
    SerparIoctl
728
};
729
 
730
/* EOF serpardr.c */

powered by: WebSVN 2.1.0

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