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

Subversion Repositories or1k

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

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 106 markom
static char _[] = "@(#)serial.c 5.21 93/10/26 09:47:06, 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
 * This module contains the functions to initialize, read, and write to the
30
 * serial ports (COM1, COM2,...) on a PC.
31
 *****************************************************************************
32
 */
33
 
34
#include <stdio.h>
35
#include <conio.h>
36
#include <bios.h>
37
#include <dos.h>  
38
#include <string.h>
39
#include "types.h"
40
#include "memspcs.h"
41
#include "messages.h"
42
#include "mtip.h"
43
#include "tdfunc.h"
44
 
45
/* Serial Port Defs */
46
 /*
47
 * Divisors for different baud rates to be used to initialize DLA
48
 * register.
49
 */
50
#define _DIV_COM_110    1047
51
#define _DIV_COM_150    768
52
#define _DIV_COM_300    384
53
#define _DIV_COM_600    192
54
#define _DIV_COM_1200   96
55
#define _DIV_COM_2400   48
56
#define _DIV_COM_4800   24
57
#define _DIV_COM_9600   12
58
#define _DIV_COM_19200  6
59
#define _DIV_COM_38400  3
60
#define _DIV_COM_115200 1
61
 
62
#define LCR_DLAB        0x80
63
 
64
#define DLA_LOW_OFFSET  0x0
65
 
66
 
67
/*
68
** Definitions
69
*/
70
 
71
#define BUF_SIZE               2048
72
 
73
/*
74
** This data structure is used by the interrupt driven
75
** serial I/O.
76
*/
77
 
78
struct serial_io_t {
79
   int error;                      /* Error code */
80
   unsigned int    port;           /* Port number */
81
   unsigned int    port_code;      /* Port code (for bios calls) */
82
   unsigned int    int_number;     /* Port interrupt number      */
83
   unsigned int    int_mask;       /* Port interrupt mask        */
84
   unsigned int    baud;           /* Port baud rate             */
85
   unsigned int    old_vector_ds;  /* Interrupt vector (old)     */
86
   unsigned int    old_vector_dx;
87
   volatile
88
   unsigned char  *start;          /* Start of ring buffer       */
89
   volatile
90
   unsigned char  *end;            /* End of ring buffer         */
91
   };
92
 
93
static unsigned char   serial_io_buffer[BUF_SIZE];
94
 
95
/* These definitions are from bios.h */
96
#define CHAR_SIZE         _COM_CHR8
97
#define STOP_BITS        _COM_STOP1
98
#define PARITY        _COM_NOPARITY
99
 
100
/*
101
** Serial port definitions
102
*/
103
 
104
#define INTR_MASK    0x21    /* 8259 Interrupt Mask Port */
105
#define INTR_EOI     0x20    /* 8259 EOI Port */
106
 
107
#define COM1         0x3f8   /* COM1 Port Base */
108
#define COM1_CODE    0x00    /* COM1 Port Code */
109
#define COM1_INT     0x0c    /* COM1 Interrupt Number */
110
#define COM1_MASK    0x10    /* COM1 Interrupt Mask (IRQ4) */
111
 
112
#define COM2         0x2f8   /* COM2 Port Base */
113
#define COM2_CODE    0x01    /* COM2 Port Code */
114
#define COM2_INT     0x0b    /* COM2 Interrupt Number */
115
#define COM2_MASK    0x08    /* COM2 Interrupt Mask (IRQ3) */
116
 
117
#define MSR_OFFSET   0x6     /* Modem Status Register offset */
118
#define LSR_OFFSET   0x5     /* Line status Register offset */
119
#define MCR_OFFSET   0x4     /* Modem Control Register offset */
120
#define LCR_OFFSET   0x3     /* Line Control Register offest */
121
#define IID_OFFSET   0x2     /* Interrupt pending register */
122
#define IER_OFFSET   0x1     /* Interrupt Enable Register offest */
123
 
124
/* Bits in Line Status Register (LSR) */
125
#define AC1   0x80    /* Always clear */
126
#define TSRE  0x40    /* Transmitter Shift Register Empty */
127
#define THRE  0x20    /* Transmitter Holding Register Empty */
128
#define BI    0x10    /* Break Interrupt */
129
#define FE    0x08    /* Framing Error */
130
#define PE    0x04    /* Parity Error */
131
#define OE    0x02    /* Overrun Error */
132
#define DR    0x01    /* Data Ready */
133
 
134
/* Bits in Modem Control Register */
135
#define CD    0x80
136
#define RI    0x40
137
#define DSR   0x20
138
#define CTS   0x10
139
#define OUT2  0x08
140
#define RTS   0x02
141
#define DTR   0x01
142
 
143
#define MAX_BLOCK       1000    
144
 
145
/*  function prototypes */
146
 
147
void   endian_cvt PARAMS((union msg_t *, int));
148
void   tip_convert32 PARAMS((BYTE *));
149
INT32   init_parport (char *);
150
 
151
void   interrupt far serial_int PARAMS((void));
152
void    (interrupt far *OldVector)();
153
int    get_byte_serial PARAMS((void));
154
 
155
extern  int     BlockCount;
156
extern  int     lpt_initialize;
157
/* globals */
158
 
159
struct serial_io_t serial_io;
160
 
161
INT32  in_msg_length=0;
162
INT32  in_byte_count=0;
163
 
164
/*
165
** Serial Port functions
166
*/
167
 
168
/*
169
** This function is used to initialize the communication
170
** channel.  First the serial_io data structure is
171
** initialized.  Then the new interrupt vector is installed.
172
** Finally, the port is initialized, with DTR, RTS and OUT2
173
** set.
174
**
175
*/
176
 
177
INT32 write_memory_serial (ignore1, ignore2, ignore3, ignore4, ignore5, ignore6)
178
        INT32 ignore1;
179
        ADDR32 ignore2;
180
        BYTE *ignore3;
181
        INT32 ignore4;
182
        INT32 ignore5;
183
        INT32 ignore6;
184
{
185
        return(-1); }
186
 
187
INT32 read_memory_serial (ignore1, ignore2, ignore3, ignore4, ignore5, ignore6)
188
        INT32 ignore1;
189
        ADDR32 ignore2;
190
        BYTE *ignore3;
191
        INT32 ignore4;
192
        INT32 ignore5;
193
        INT32 ignore6;
194
{ return(-1); }
195
 
196
INT32 fill_memory_serial() { return(-1); }
197
 
198
INT32
199
init_comm_serial(ignore1, ignore2)
200
INT32 ignore1;
201
INT32 ignore2;
202
   {
203
   unsigned result;
204
   unsigned config;
205
   unsigned   int comm_status;
206
 
207
   /* Initialize serial_io */
208
   serial_io.error = FALSE;
209
 
210
   /* Set up port number */
211
   if ((strcmp(tip_config.comm_port, "com1") == 0) ||
212
       (strcmp(tip_config.comm_port, "com1:") == 0)) {
213
      serial_io.port = COM1;
214
      serial_io.port_code = COM1_CODE;
215
      serial_io.int_number = COM1_INT;
216
      serial_io.int_mask = COM1_MASK;
217
      }
218
   else
219
   if ((strcmp(tip_config.comm_port, "com2") == 0) ||
220
       (strcmp(tip_config.comm_port, "com2:") == 0)) {
221
      serial_io.port = COM2;
222
      serial_io.port_code = COM2_CODE;
223
      serial_io.int_number = COM2_INT;
224
      serial_io.int_mask = COM2_MASK;
225
      }
226
   else
227
      return((INT32) -1);
228
 
229
    /* Check status */
230
    comm_status = inp(serial_io.port+LSR_OFFSET);
231
#if 0
232
    /* reset any communication errors */
233
    outp(serial_io.port+LSR_OFFSET,
234
                       (unsigned int) (comm_status & ~(FE|PE|OE)));
235
#endif
236
 
237
 
238
   /* Get baud rate (Note: MS-DOS only goes to 9600) */
239
   outp (serial_io.port+LCR_OFFSET, LCR_DLAB);
240
 
241
   if (strcmp(tip_config.baud_rate, "110") == 0)
242
      outpw (serial_io.port+DLA_LOW_OFFSET, _DIV_COM_110);
243
   else
244
   if (strcmp(tip_config.baud_rate, "150") == 0)
245
      outpw (serial_io.port+DLA_LOW_OFFSET, _DIV_COM_150);
246
   else
247
   if (strcmp(tip_config.baud_rate, "300") == 0)
248
      outpw (serial_io.port+DLA_LOW_OFFSET, _DIV_COM_300);
249
   else
250
   if (strcmp(tip_config.baud_rate, "600") == 0)
251
      outpw (serial_io.port+DLA_LOW_OFFSET, _DIV_COM_600);
252
   else
253
   if (strcmp(tip_config.baud_rate, "1200") == 0)
254
      outpw (serial_io.port+DLA_LOW_OFFSET, _DIV_COM_1200);
255
   else
256
   if (strcmp(tip_config.baud_rate, "2400") == 0)
257
      outpw (serial_io.port+DLA_LOW_OFFSET, _DIV_COM_2400);
258
   else
259
   if (strcmp(tip_config.baud_rate, "4800") == 0)
260
      outpw (serial_io.port+DLA_LOW_OFFSET, _DIV_COM_4800);
261
   else
262
   if (strcmp(tip_config.baud_rate, "9600") == 0)
263
      outpw (serial_io.port+DLA_LOW_OFFSET, _DIV_COM_9600);
264
   else
265
   if (strcmp(tip_config.baud_rate, "19200") == 0)
266
      outpw (serial_io.port+DLA_LOW_OFFSET, _DIV_COM_19200);
267
   else
268
   if (strcmp(tip_config.baud_rate, "38400") == 0)
269
      outpw (serial_io.port+DLA_LOW_OFFSET, _DIV_COM_38400);
270
   else
271
   if (strcmp(tip_config.baud_rate, "115200") == 0)
272
      outpw (serial_io.port+DLA_LOW_OFFSET, _DIV_COM_115200);
273
   else
274
      return((INT32) -1);  /* EMBAUD); */
275
 
276
   /* Set LCR */
277
   outp (serial_io.port+LCR_OFFSET,
278
                (unsigned int) (_COM_CHR8|_COM_STOP1|_COM_NOPARITY));
279
 
280
   /* Save old interrupt vector */
281
   OldVector = _dos_getvect (serial_io.int_number);
282
 
283
   /* Initialize ring buffer */
284
   serial_io.start = serial_io_buffer;
285
   serial_io.end = serial_io_buffer;
286
 
287
   /* Install interrupt vector */
288
   /* Note:  the interrupt handler should be in the same code */
289
   /*        segment as this function.  We will use CS for    */
290
   /*        the segment offset value.                        */
291
 
292
   _dos_setvect(serial_io.int_number, serial_int); /* new handler */
293
 
294
   /* Turn on DTR, RTS and OUT2 */
295
   result = outp((serial_io.port+MCR_OFFSET), (DTR | RTS | OUT2));
296
 
297
   /* Enable interrupt on serial port controller */
298
   result = outp((serial_io.port+IER_OFFSET), 0x01);
299
 
300
   /* Set interrupt mask on 8259 */
301
   config = inp(INTR_MASK);  /* Get current 8259 mask */
302
   result = outp(INTR_MASK, (config & ~serial_io.int_mask));
303
 
304
   /* Set global message indices */
305
   in_msg_length = 0;
306
   in_byte_count = 0;
307
 
308
   /* initialize parallel port */
309
   if (lpt_initialize)
310
      return (init_parport(tip_config.par_port));
311
 
312
   return((INT32) 0);
313
   }  /* end init_comm_serial() */
314
 
315
/*
316
** This function is used to send bytes over the serial line.
317
** If the bytes are successfully sent, a zero is returned.
318
** If the bytes are not sent, a -1 is returned.
319
*/
320
 
321
INT32
322
send_bfr_serial(bfr_ptr, length, port_base, comm_err)
323
   BYTE   *bfr_ptr;
324
   INT32  length;
325
   INT32  port_base;
326
   INT32  *comm_err;
327
   {
328
   int        retries;
329
   INT32      byte_count = 0;
330
   unsigned   int comm_status;
331
   unsigned   int result;
332
 
333
   /* Send message */
334
   retries = 0;
335
   do {
336
 
337
      /* check user interrupt */
338
      SIGINT_POLL
339
      /* Check if data ready */
340
      comm_status = inp(serial_io.port+LSR_OFFSET);
341
 
342
      /* Check for communication errors */
343
      if ((comm_status & (FE | PE | OE)) != 0) {
344
          *comm_err = 1;
345
          return (-1);
346
      }
347
 
348
      /* If Transmitter Holding Register Empty (THRE) */
349
      /* send out data */
350
      if ((comm_status & THRE) != 0) {
351
         result = outp(serial_io.port, bfr_ptr[byte_count]);
352
         byte_count = byte_count + 1;
353
         retries = 0;
354
         } else {
355
            retries = retries + 1;
356
            if (retries >= 20000)
357
               return (-1);   /* EMNOSEND); */
358
            }
359
 
360
      } while (byte_count < length );
361
 
362
   return(0);
363
   }  /* end send_bfr_serial() */
364
 
365
/*
366
** This function is used to receive bytes over a serial line.
367
**
368
** If block equals NONBLOCK then the function returns as soon
369
** there are no bytes remaining in the UART.
370
** If block equals BLOCK then the function waits until all
371
** bytes are gotten before returning.
372
**
373
** If all bytes requested are gotten, 0 is returned, else -1.
374
*/
375
 
376
INT32
377
recv_bfr_serial(bfr_ptr, length, block, port_base, comm_err)
378
   BYTE   *bfr_ptr;
379
   INT32  length;
380
   INT32  block;
381
   INT32  port_base;
382
   INT32  *comm_err;
383
   {
384
   int        comm_status;
385
   int        c;
386
   int        result;
387
   int        bytes_free;
388
 
389
   int      block_count = 0;
390
 
391
   /* Loop as long as characters keep coming */
392
   for (;;) {
393
 
394
      /* Check for communication errors */
395
      comm_status = inp(serial_io.port+LSR_OFFSET);
396
      if ((comm_status & (FE | PE | OE)) != 0)
397
          {
398
          *comm_err = 1;
399
          return (-1);
400
          }
401
 
402
      /* Check for buffer overflow */
403
      if (serial_io.error == TRUE)
404
          {
405
          *comm_err = 1;
406
          return (-1);
407
          }
408
 
409
      /* Do flow control.  If the buffer is 9/10 full, */
410
      /* deassert DTR and RTS.  If the buffer becomes */
411
      /* 1/10 full, reassert DTR and RTS.              */
412
      bytes_free = (int) (serial_io.start - serial_io.end);
413
      if (bytes_free <= 0)
414
         bytes_free = BUF_SIZE + bytes_free;
415
 
416
      comm_status = inp(serial_io.port+MCR_OFFSET);
417
      if (bytes_free <= (BUF_SIZE/10))
418
         result = outp((serial_io.port+MCR_OFFSET),
419
                       (comm_status & ~DTR & ~RTS));
420
 
421
      if (bytes_free >= ((9*BUF_SIZE)/10))
422
         result = outp((serial_io.port+MCR_OFFSET),
423
                       (comm_status | DTR | RTS));
424
 
425
      /* Get character */
426
      c = get_byte_serial();
427
 
428
      /* return if no char & not blocking */
429
      if ((c == -1) && (block == NONBLOCK))
430
         return (-1);
431
 
432
      /* return if no char, blocking, and past block count */
433
      if ((c == -1) && (block == BLOCK) && (block_count++ > BlockCount))
434
         return (-1);
435
 
436
      /* Save byte in bfr_ptr buffer */
437
      if (c != -1) {
438
          bfr_ptr[in_byte_count] = (BYTE) c;
439
          block_count = 0;
440
          in_byte_count = in_byte_count + 1;
441
          }
442
 
443
      /* Message received ? */
444
      if (in_byte_count == length) {
445
         in_byte_count = 0;
446
         return(0);
447
         }
448
      }         /* end for(;;) */
449
   }            /* end recv_bfr_serial() */
450
 
451
 
452
/*
453
** This function is used to reset the communication
454
** channel.  This is used when resyncing the host and
455
** target and when exiting the monitor.
456
*/
457
 
458
INT32
459
reset_comm_serial(ignore1, ignore2)
460
INT32   ignore1;
461
INT32   ignore2;
462
   {
463
   unsigned   int status;
464
 
465
#define CLEAR_STAT      (int) 1
466
 
467
  do {
468
    /* Clear LSR */
469
    inp(serial_io.port+LSR_OFFSET);
470
    /* Clear RX reg */
471
    inp (serial_io.port);
472
    /* Clear MSR */
473
    inp (serial_io.port+MSR_OFFSET);
474
    /* interrupt pending ? */
475
    status = inp(serial_io.port+IID_OFFSET);
476
  } while (status != CLEAR_STAT);
477
 
478
#if 0
479
    /* reset any communication errors */
480
    outp(serial_io.port+LSR_OFFSET,
481
                       (unsigned int) (comm_status & ~(FE|PE|OE)));
482
#endif
483
 
484
   /* Initialize serial_io */
485
   serial_io.error = FALSE;
486
 
487
   /* Initialize ring buffer */
488
   serial_io.start = serial_io_buffer;
489
   serial_io.end = serial_io_buffer;
490
 
491
   /* Set global message indices */
492
   in_msg_length = 0;
493
   in_byte_count = 0;
494
 
495
   return((INT32) 0);
496
   }  /* end reset_comm_serial() */
497
 
498
 
499
INT32
500
exit_comm_serial(ignore1, ignore2)
501
INT32   ignore1;
502
INT32   ignore2;
503
   {
504
   /* Initialize serial_io */
505
   serial_io.error = FALSE;
506
 
507
   /* Initialize ring buffer */
508
   serial_io.start = serial_io_buffer;
509
   serial_io.end = serial_io_buffer;
510
 
511
   /* Set global message indices */
512
   in_msg_length = 0;
513
   in_byte_count = 0;
514
 
515
   /* install old handler back */
516
   _dos_setvect(serial_io.int_number, OldVector);
517
 
518
   return((INT32) 0);
519
   }  /* end reset_comm_serial() */
520
 
521
/*
522
** This function is usually used to "kick-start" the target.
523
** This is nesessary when targets are shared memory boards.
524
** With serial communications, this function does nothing.
525
*/
526
 
527
void
528
go_serial(ignore1, ignore2)
529
INT32 ignore1;
530
INT32 ignore2;
531
   {
532
   return;
533
   }  /* end go_serial() */
534
 
535
 
536
 
537
/*
538
** This function is used to get a byte from the the
539
** serial_io_buffer.  The data in this buffer is written
540
** by the interrupt handler.
541
**
542
** If no data is available, a -1 is returned.  Otherwise
543
** a character is returned.
544
*/
545
 
546
int
547
get_byte_serial()
548
   {
549
   int result=-1;
550
 
551
      /* Turn interrupts off while reading buffer */
552
     _disable();
553
 
554
   /* No bytes available */
555
   if (serial_io.start == serial_io.end)
556
      result = -1;
557
   else {
558
 
559
      /* Return character */
560
      result = (int) *serial_io.start;
561
      serial_io.start++;
562
      /* Check for wrap around */
563
      if (serial_io.start >= (serial_io_buffer+BUF_SIZE)) {
564
         serial_io.start = serial_io_buffer;
565
      }
566
 
567
    }
568
      /* Turn interrupts back on */
569
      _enable();
570
 
571
   return (result);
572
   }  /* end get_byte_serial() */
573
 
574
 
575
 
576
/*
577
** This function is the interrupt handler which buffers
578
** incoming characters.
579
**
580
** Note:  The "interrupt" keyword is not well documented.
581
**        It produces a procedure which returns with an
582
**        "iret" instead of the usual "ret".
583
*/
584
 
585
void interrupt serial_int()
586
   {
587
   int c;
588
 
589
   /* Get character */
590
   c = inp(serial_io.port);
591
 
592
   *serial_io.end = (unsigned char) c;
593
   serial_io.end++;
594
   /* Check for wrap around */
595
   if (serial_io.end >= (serial_io_buffer+BUF_SIZE))
596
      serial_io.end = serial_io_buffer;
597
 
598
   /* Has the buffer overflowed? */
599
   if (serial_io.start == serial_io.end)
600
      serial_io.error = TRUE;
601
 
602
   /* Send EOI to 8259 */
603
   (void) outp(INTR_EOI, 0x20);
604
 
605
   }  /* end serial_int() */
606
 
607
 

powered by: WebSVN 2.1.0

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