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

Subversion Repositories or1k

[/] [or1k/] [branches/] [oc/] [gdb-5.0/] [gdb/] [rdi-share/] [serdrv.c] - Blame information for rev 106

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:45 $
13
 *
14
 *
15
 * serdrv.c - Synchronous Serial Driver for Angel.
16
 *            This is nice and simple just to get something going.
17
 */
18
 
19
#ifdef __hpux
20
#  define _POSIX_SOURCE 1
21
#endif
22
 
23
#include <stdio.h>
24
#include <stdlib.h>
25
#include <string.h>
26
 
27
#include "crc.h"
28
#include "devices.h"
29
#include "buffers.h"
30
#include "rxtx.h"
31
#include "hostchan.h"
32
#include "params.h"
33
#include "logging.h"
34
 
35
extern int baud_rate;   /* From gdb/top.c */
36
 
37
#ifdef COMPILING_ON_WINDOWS
38
#  undef   ERROR
39
#  undef   IGNORE
40
#  include <windows.h>
41
#  include "angeldll.h"
42
#  include "comb_api.h"
43
#else
44
#  ifdef __hpux
45
#    define _TERMIOS_INCLUDED
46
#    include <sys/termio.h>
47
#    undef _TERMIOS_INCLUDED
48
#  else
49
#    include <termios.h>
50
#  endif
51
#  include "unixcomm.h"
52
#endif
53
 
54
#ifndef UNUSED
55
#  define UNUSED(x) (x = x)      /* Silence compiler warnings */
56
#endif
57
 
58
#define MAXREADSIZE 512
59
#define MAXWRITESIZE 512
60
 
61
#define SERIAL_FC_SET  ((1<<serial_XON)|(1<<serial_XOFF))
62
#define SERIAL_CTL_SET ((1<<serial_STX)|(1<<serial_ETX)|(1<<serial_ESC))
63
#define SERIAL_ESC_SET (SERIAL_FC_SET|SERIAL_CTL_SET)
64
 
65
static const struct re_config config = {
66
    serial_STX, serial_ETX, serial_ESC, /* self-explanatory?               */
67
    SERIAL_FC_SET,                      /* set of flow-control characters  */
68
    SERIAL_ESC_SET,                     /* set of characters to be escaped */
69
    NULL /* serial_flow_control */, NULL  ,    /* what to do with FC chars */
70
    angel_DD_RxEng_BufferAlloc, NULL                /* how to get a buffer */
71
};
72
 
73
static struct re_state rxstate;
74
 
75
typedef struct writestate {
76
  unsigned int wbindex;
77
  /*  static te_status testatus;*/
78
  unsigned char writebuf[MAXWRITESIZE];
79
  struct te_state txstate;
80
} writestate;
81
 
82
static struct writestate wstate;
83
 
84
/*
85
 * The set of parameter options supported by the device
86
 */
87
static unsigned int baud_options[] = {
88
#if defined(B115200) || defined(__hpux)
89
    115200,
90
#endif
91
#if defined(B57600) || defined(__hpux)
92
    57600,
93
#endif
94
    38400, 19200, 9600
95
};
96
 
97
static ParameterList param_list[] = {
98
    { AP_BAUD_RATE,
99
      sizeof(baud_options)/sizeof(unsigned int),
100
      baud_options }
101
};
102
 
103
static const ParameterOptions serial_options = {
104
    sizeof(param_list)/sizeof(ParameterList), param_list };
105
 
106
/*
107
 * The default parameter config for the device
108
 */
109
static Parameter param_default[] = {
110
    { AP_BAUD_RATE, 9600 }
111
};
112
 
113
static ParameterConfig serial_defaults = {
114
    sizeof(param_default)/sizeof(Parameter), param_default };
115
 
116
/*
117
 * The user-modified options for the device
118
 */
119
static unsigned int user_baud_options[sizeof(baud_options)/sizeof(unsigned)];
120
 
121
static ParameterList param_user_list[] = {
122
    { AP_BAUD_RATE,
123
      sizeof(user_baud_options)/sizeof(unsigned),
124
      user_baud_options }
125
};
126
 
127
static ParameterOptions user_options = {
128
    sizeof(param_user_list)/sizeof(ParameterList), param_user_list };
129
 
130
static bool user_options_set;
131
 
132
/* forward declarations */
133
static int serial_reset( void );
134
static int serial_set_params( const ParameterConfig *config );
135
static int SerialMatch(const char *name, const char *arg);
136
 
137
static void process_baud_rate( unsigned int target_baud_rate )
138
{
139
    const ParameterList *full_list;
140
    ParameterList       *user_list;
141
 
142
    /* create subset of full options */
143
    full_list = Angel_FindParamList( &serial_options, AP_BAUD_RATE );
144
    user_list = Angel_FindParamList( &user_options,   AP_BAUD_RATE );
145
 
146
    if ( full_list != NULL && user_list != NULL )
147
    {
148
        unsigned int i, j;
149
        unsigned int def_baud = 0;
150
 
151
        /* find lower or equal to */
152
        for ( i = 0; i < full_list->num_options; ++i )
153
           if ( target_baud_rate >= full_list->option[i] )
154
           {
155
               /* copy remaining */
156
               for ( j = 0; j < (full_list->num_options - i); ++j )
157
                  user_list->option[j] = full_list->option[i+j];
158
               user_list->num_options = j;
159
 
160
               /* check this is not the default */
161
               Angel_FindParam( AP_BAUD_RATE, &serial_defaults, &def_baud );
162
               if ( (j == 1) && (user_list->option[0] == def_baud) )
163
               {
164
#ifdef DEBUG
165
                   printf( "user selected default\n" );
166
#endif
167
               }
168
               else
169
               {
170
                   user_options_set = TRUE;
171
#ifdef DEBUG
172
                   printf( "user options are: " );
173
                   for ( j = 0; j < user_list->num_options; ++j )
174
                      printf( "%u ", user_list->option[j] );
175
                   printf( "\n" );
176
#endif
177
               }
178
 
179
               break;   /* out of i loop */
180
           }
181
 
182
#ifdef DEBUG
183
        if ( i >= full_list->num_options )
184
           printf( "couldn't match baud rate %u\n", target_baud_rate );
185
#endif
186
    }
187
#ifdef DEBUG
188
    else
189
       printf( "failed to find lists\n" );
190
#endif
191
}
192
 
193
static int SerialOpen(const char *name, const char *arg)
194
{
195
    const char *port_name = name;
196
 
197
#ifdef DEBUG
198
    printf("SerialOpen: name %s arg %s\n", name, arg ? arg : "<NULL>");
199
#endif
200
 
201
#ifdef COMPILING_ON_WINDOWS
202
    if (IsOpenSerial()) return -1;
203
#else
204
    if (Unix_IsSerialInUse()) return -1;
205
#endif
206
 
207
#ifdef COMPILING_ON_WINDOWS
208
    if (SerialMatch(name, arg) != adp_ok)
209
        return adp_failed;
210
#else
211
    port_name = Unix_MatchValidSerialDevice(port_name);
212
# ifdef DEBUG
213
    printf("translated port to %s\n", port_name == 0 ? "NULL" : port_name);
214
# endif
215
    if (port_name == 0) return adp_failed;
216
#endif
217
 
218
    user_options_set = FALSE;
219
 
220
    /* interpret and store the arguments */
221
    if ( arg != NULL )
222
    {
223
        unsigned int target_baud_rate;
224
        target_baud_rate = (unsigned int)strtoul(arg, NULL, 10);
225
        if (target_baud_rate > 0)
226
        {
227
#ifdef DEBUG
228
            printf( "user selected baud rate %u\n", target_baud_rate );
229
#endif
230
            process_baud_rate( target_baud_rate );
231
        }
232
#ifdef DEBUG
233
        else
234
           printf( "could not understand baud rate %s\n", arg );
235
#endif
236
    }
237
    else if (baud_rate > 0)
238
    {
239
      /* If the user specified a baud rate on the command line "-b" or via
240
         the "set remotebaud" command then try to use that one */
241
      process_baud_rate( baud_rate );
242
    }
243
 
244
#ifdef COMPILING_ON_WINDOWS
245
    {
246
        int port = IsValidDevice(name);
247
        if (OpenSerial(port, FALSE) != COM_OK)
248
            return -1;
249
    }
250
#else
251
    if (Unix_OpenSerial(port_name) < 0)
252
      return -1;
253
#endif
254
 
255
    serial_reset();
256
 
257
#if defined(__unix) || defined(__CYGWIN32__)
258
    Unix_ioctlNonBlocking();
259
#endif
260
 
261
    Angel_RxEngineInit(&config, &rxstate);
262
    /*
263
     * DANGER!: passing in NULL as the packet is ok for now as it is just
264
     * IGNOREd but this may well change
265
     */
266
    Angel_TxEngineInit(&config, NULL, &wstate.txstate);
267
    return 0;
268
}
269
 
270
static int SerialMatch(const char *name, const char *arg)
271
{
272
    UNUSED(arg);
273
#ifdef COMPILING_ON_WINDOWS
274
    if (IsValidDevice(name) == COM_DEVICENOTVALID)
275
        return -1;
276
    else
277
        return 0;
278
#else
279
    return Unix_MatchValidSerialDevice(name) == 0 ? -1 : 0;
280
#endif
281
}
282
 
283
static void SerialClose(void)
284
{
285
#ifdef DO_TRACE
286
    printf("SerialClose()\n");
287
#endif
288
 
289
#ifdef COMPILING_ON_WINDOWS
290
    CloseSerial();
291
#else
292
    Unix_CloseSerial();
293
#endif
294
}
295
 
296
static int SerialRead(DriverCall *dc, bool block) {
297
  static unsigned char readbuf[MAXREADSIZE];
298
  static int rbindex=0;
299
 
300
  int nread;
301
  int read_errno;
302
  int c=0;
303
  re_status restatus;
304
  int ret_code = -1;            /* assume bad packet or error */
305
 
306
  /* must not overflow buffer and must start after the existing data */
307
#ifdef COMPILING_ON_WINDOWS
308
  {
309
    BOOL dummy = FALSE;
310
    nread = BytesInRXBufferSerial();
311
 
312
    if (nread > MAXREADSIZE - rbindex)
313
      nread = MAXREADSIZE - rbindex;
314
 
315
    if ((read_errno = ReadSerial(readbuf+rbindex, nread, &dummy)) == COM_READFAIL)
316
    {
317
        MessageBox(GetFocus(), "Read error\n", "Angel", MB_OK | MB_ICONSTOP);
318
        return -1;   /* SJ - This really needs to return a value, which is picked up in */
319
                     /*      DevSW_Read as meaning stop debugger but don't kill. */
320
    }
321
    else if (pfnProgressCallback != NULL && read_errno == COM_OK)
322
    {
323
      progressInfo.nRead += nread;
324
      (*pfnProgressCallback)(&progressInfo);
325
    }
326
  }
327
#else
328
  nread = Unix_ReadSerial(readbuf+rbindex, MAXREADSIZE-rbindex, block);
329
  read_errno = errno;
330
#endif
331
 
332
  if ((nread > 0) || (rbindex > 0)) {
333
 
334
#ifdef DO_TRACE
335
    printf("[%d@%d] ", nread, rbindex);
336
#endif
337
 
338
    if (nread>0)
339
       rbindex = rbindex+nread;
340
 
341
    do {
342
      restatus = Angel_RxEngine(readbuf[c], &(dc->dc_packet), &rxstate);
343
#ifdef DO_TRACE
344
      printf("<%02X ",readbuf[c]);
345
      if (!(++c % 16))
346
          printf("\n");
347
#else
348
      c++;
349
#endif
350
    } while (c<rbindex &&
351
             ((restatus == RS_IN_PKT) || (restatus == RS_WAIT_PKT)));
352
 
353
#ifdef DO_TRACE
354
   if (c % 16)
355
        printf("\n");
356
#endif
357
 
358
    switch(restatus) {
359
 
360
      case RS_GOOD_PKT:
361
        ret_code = 1;
362
        /* fall through to: */
363
 
364
      case RS_BAD_PKT:
365
        /*
366
         * We now need to shuffle any left over data down to the
367
         * beginning of our private buffer ready to be used
368
         *for the next packet
369
         */
370
#ifdef DO_TRACE
371
        printf("SerialRead() processed %d, moving down %d\n", c, rbindex-c);
372
#endif
373
        if (c != rbindex) memmove((char *) readbuf, (char *) (readbuf+c),
374
                                  rbindex-c);
375
        rbindex -= c;
376
        break;
377
 
378
      case RS_IN_PKT:
379
      case RS_WAIT_PKT:
380
        rbindex = 0;            /* will have processed all we had */
381
        ret_code = 0;
382
        break;
383
 
384
      default:
385
#ifdef DEBUG
386
        printf("Bad re_status in serialRead()\n");
387
#endif
388
        break;
389
    }
390
  } else if (nread == 0)
391
    ret_code = 0;               /* nothing to read */
392
  else if (read_errno == ERRNO_FOR_BLOCKED_IO) /* nread < 0 */
393
    ret_code = 0;
394
 
395
#ifdef DEBUG
396
  if ((nread<0) && (read_errno!=ERRNO_FOR_BLOCKED_IO))
397
    perror("read() error in serialRead()");
398
#endif
399
 
400
  return ret_code;
401
}
402
 
403
 
404
static int SerialWrite(DriverCall *dc) {
405
  int nwritten = 0;
406
  te_status testatus = TS_IN_PKT;
407
 
408
  if (dc->dc_context == NULL) {
409
    Angel_TxEngineInit(&config, &(dc->dc_packet), &(wstate.txstate));
410
    wstate.wbindex = 0;
411
    dc->dc_context = &wstate;
412
  }
413
 
414
  while ((testatus == TS_IN_PKT) && (wstate.wbindex < MAXWRITESIZE))
415
  {
416
    /* send the raw data through the tx engine to escape and encapsulate */
417
    testatus = Angel_TxEngine(&(dc->dc_packet), &(wstate.txstate),
418
                              &(wstate.writebuf)[wstate.wbindex]);
419
    if (testatus != TS_IDLE) wstate.wbindex++;
420
  }
421
 
422
  if (testatus == TS_IDLE) {
423
#ifdef DEBUG
424
    printf("SerialWrite: testatus is TS_IDLE during preprocessing\n");
425
#endif
426
  }
427
 
428
#ifdef DO_TRACE
429
  {
430
    int i = 0;
431
 
432
    while (i<wstate.wbindex)
433
    {
434
        printf(">%02X ",wstate.writebuf[i]);
435
 
436
        if (!(++i % 16))
437
            printf("\n");
438
    }
439
    if (i % 16)
440
        printf("\n");
441
  }
442
#endif
443
 
444
#ifdef COMPILING_ON_WINDOWS
445
  if (WriteSerial(wstate.writebuf, wstate.wbindex) == COM_OK)
446
  {
447
    nwritten = wstate.wbindex;
448
    if (pfnProgressCallback != NULL)
449
    {
450
      progressInfo.nWritten += nwritten;
451
      (*pfnProgressCallback)(&progressInfo);
452
    }
453
  }
454
  else
455
  {
456
      MessageBox(GetFocus(), "Write error\n", "Angel", MB_OK | MB_ICONSTOP);
457
      return -1;   /* SJ - This really needs to return a value, which is picked up in */
458
                   /*      DevSW_Read as meaning stop debugger but don't kill. */
459
  }
460
#else
461
  nwritten = Unix_WriteSerial(wstate.writebuf, wstate.wbindex);
462
 
463
  if (nwritten < 0) {
464
    nwritten=0;
465
  }
466
#endif
467
 
468
#ifdef DEBUG
469
  if (nwritten > 0)
470
    printf("Wrote %#04x bytes\n", nwritten);
471
#endif
472
 
473
  if ((unsigned) nwritten == wstate.wbindex &&
474
      (testatus == TS_DONE_PKT || testatus == TS_IDLE)) {
475
 
476
    /* finished sending the packet */
477
 
478
#ifdef DEBUG
479
    printf("SerialWrite: calling Angel_TxEngineInit after sending packet (len=%i)\n",wstate.wbindex);
480
#endif
481
    testatus = TS_IN_PKT;
482
    wstate.wbindex = 0;
483
    return 1;
484
  }
485
  else {
486
#ifdef DEBUG
487
    printf("SerialWrite: Wrote part of packet wbindex=%i, nwritten=%i\n",
488
           wstate.wbindex, nwritten);
489
#endif
490
 
491
    /*
492
     *  still some data left to send shuffle whats left down and reset
493
     * the ptr
494
     */
495
    memmove((char *) wstate.writebuf, (char *) (wstate.writebuf+nwritten),
496
            wstate.wbindex-nwritten);
497
    wstate.wbindex -= nwritten;
498
    return 0;
499
  }
500
  return -1;
501
}
502
 
503
 
504
static int serial_reset( void )
505
{
506
#ifdef DEBUG
507
    printf( "serial_reset\n" );
508
#endif
509
 
510
#ifdef COMPILING_ON_WINDOWS
511
    FlushSerial();
512
#else
513
    Unix_ResetSerial();
514
#endif
515
 
516
    return serial_set_params( &serial_defaults );
517
}
518
 
519
 
520
static int find_baud_rate( unsigned int *speed )
521
{
522
    static struct {
523
          unsigned int baud;
524
          int termiosValue;
525
    } possibleBaudRates[] = {
526
#if defined(__hpux)
527
        {115200,_B115200}, {57600,_B57600},
528
#else
529
#ifdef B115200
530
        {115200,B115200},
531
#endif
532
#ifdef B57600
533
        {57600,B57600},
534
#endif
535
#endif
536
#ifdef COMPILING_ON_WINDOWS
537
        {38400,CBR_38400}, {19200,CBR_19200}, {9600, CBR_9600}, {0,0}
538
#else
539
        {38400,B38400}, {19200,B19200}, {9600, B9600}, {0,0}
540
#endif
541
    };
542
    unsigned int i;
543
 
544
    /* look for lower or matching -- will always terminate at 0 end marker */
545
    for ( i = 0; possibleBaudRates[i].baud > *speed; ++i )
546
       /* do nothing */ ;
547
 
548
    if ( possibleBaudRates[i].baud > 0 )
549
       *speed = possibleBaudRates[i].baud;
550
 
551
    return possibleBaudRates[i].termiosValue;
552
}
553
 
554
 
555
static int serial_set_params( const ParameterConfig *config )
556
{
557
    unsigned int speed;
558
    int termios_value;
559
 
560
#ifdef DEBUG
561
    printf( "serial_set_params\n" );
562
#endif
563
 
564
    if ( ! Angel_FindParam( AP_BAUD_RATE, config, &speed ) )
565
    {
566
#ifdef DEBUG
567
        printf( "speed not found in config\n" );
568
#endif
569
        return DE_OKAY;
570
    }
571
 
572
    termios_value = find_baud_rate( &speed );
573
    if ( termios_value == 0 )
574
    {
575
#ifdef DEBUG
576
        printf( "speed not valid: %u\n", speed );
577
#endif
578
        return DE_OKAY;
579
    }
580
 
581
#ifdef DEBUG
582
    printf( "setting speed to %u\n", speed );
583
#endif
584
 
585
#ifdef COMPILING_ON_WINDOWS
586
    SetBaudRate((WORD)termios_value);
587
#else
588
    Unix_SetSerialBaudRate(termios_value);
589
#endif
590
 
591
    return DE_OKAY;
592
}
593
 
594
 
595
static int serial_get_user_params( ParameterOptions **p_options )
596
{
597
#ifdef DEBUG
598
    printf( "serial_get_user_params\n" );
599
#endif
600
 
601
    if ( user_options_set )
602
    {
603
        *p_options = &user_options;
604
    }
605
    else
606
    {
607
        *p_options = NULL;
608
    }
609
 
610
    return DE_OKAY;
611
}
612
 
613
 
614
static int serial_get_default_params( ParameterConfig **p_config )
615
{
616
#ifdef DEBUG
617
    printf( "serial_get_default_params\n" );
618
#endif
619
 
620
    *p_config = (ParameterConfig *) &serial_defaults;
621
    return DE_OKAY;
622
}
623
 
624
 
625
static int SerialIoctl(const int opcode, void *args) {
626
 
627
    int ret_code;
628
 
629
#ifdef DEBUG
630
    printf( "SerialIoctl: op %d arg %p\n", opcode, args ? args : "<NULL>");
631
#endif
632
 
633
    switch (opcode)
634
    {
635
       case DC_RESET:
636
           ret_code = serial_reset();
637
           break;
638
 
639
       case DC_SET_PARAMS:
640
           ret_code = serial_set_params((const ParameterConfig *)args);
641
           break;
642
 
643
       case DC_GET_USER_PARAMS:
644
           ret_code = serial_get_user_params((ParameterOptions **)args);
645
           break;
646
 
647
       case DC_GET_DEFAULT_PARAMS:
648
           ret_code = serial_get_default_params((ParameterConfig **)args);
649
           break;
650
 
651
       default:
652
           ret_code = DE_BAD_OP;
653
           break;
654
    }
655
 
656
  return ret_code;
657
}
658
 
659
DeviceDescr angel_SerialDevice = {
660
    "SERIAL",
661
    SerialOpen,
662
    SerialMatch,
663
    SerialClose,
664
    SerialRead,
665
    SerialWrite,
666
    SerialIoctl
667
};

powered by: WebSVN 2.1.0

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