OpenCores
URL https://opencores.org/ocsvn/openrisc_2011-10-31/openrisc_2011-10-31/trunk

Subversion Repositories openrisc_2011-10-31

[/] [openrisc/] [trunk/] [rtos/] [ecos-2.0/] [packages/] [devs/] [serial/] [generic/] [16x5x/] [v2_0/] [src/] [ser_16x5x.c] - Blame information for rev 174

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 27 unneback
//==========================================================================
2
//
3
//      io/serial/generic/16x5x/ser_16x5x.c
4
//
5
//      Generic 16x5x serial driver
6
//
7
//==========================================================================
8
//####ECOSGPLCOPYRIGHTBEGIN####
9
// -------------------------------------------
10
// This file is part of eCos, the Embedded Configurable Operating System.
11
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
12
//
13
// eCos is free software; you can redistribute it and/or modify it under
14
// the terms of the GNU General Public License as published by the Free
15
// Software Foundation; either version 2 or (at your option) any later version.
16
//
17
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
18
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
19
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
20
// for more details.
21
//
22
// You should have received a copy of the GNU General Public License along
23
// with eCos; if not, write to the Free Software Foundation, Inc.,
24
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
25
//
26
// As a special exception, if other files instantiate templates or use macros
27
// or inline functions from this file, or you compile this file and link it
28
// with other works to produce a work based on this file, this file does not
29
// by itself cause the resulting work to be covered by the GNU General Public
30
// License. However the source code for this file must still be made available
31
// in accordance with section (3) of the GNU General Public License.
32
//
33
// This exception does not invalidate any other reasons why a work based on
34
// this file might be covered by the GNU General Public License.
35
//
36
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
37
// at http://sources.redhat.com/ecos/ecos-license/
38
// -------------------------------------------
39
//####ECOSGPLCOPYRIGHTEND####
40
//==========================================================================
41
//#####DESCRIPTIONBEGIN####
42
//
43
// Author(s):    gthomas
44
// Contributors: gthomas, jlarmour, jskov
45
// Date:         1999-02-04
46
// Purpose:      16x5x generic serial driver
47
// Description: 
48
//
49
//####DESCRIPTIONEND####
50
//
51
//==========================================================================
52
 
53
#include <pkgconf/system.h>
54
#include <pkgconf/io_serial.h>
55
#include <pkgconf/io.h>
56
 
57
#include <cyg/io/io.h>
58
#include <cyg/hal/hal_intr.h>
59
#include <cyg/io/devtab.h>
60
#include <cyg/io/serial.h>
61
#include <cyg/infra/diag.h>
62
#include <cyg/infra/cyg_ass.h>
63
#include <cyg/hal/hal_io.h>
64
 
65
// Only compile driver if an inline file with driver details was selected.
66
#ifdef CYGDAT_IO_SERIAL_GENERIC_16X5X_INL
67
 
68
#ifndef CYGPRI_IO_SERIAL_GENERIC_16X5X_STEP
69
#define CYGPRI_IO_SERIAL_GENERIC_16X5X_STEP 1
70
#endif
71
 
72
#define SER_REG(_x_) ((_x_)*CYGPRI_IO_SERIAL_GENERIC_16X5X_STEP)
73
 
74
// Receive control Registers
75
#define REG_rhr SER_REG(0)    // Receive holding register
76
#define REG_isr SER_REG(2)    // Interrupt status register
77
#define REG_lsr SER_REG(5)    // Line status register
78
#define REG_msr SER_REG(6)    // Modem status register
79
#define REG_scr SER_REG(7)    // Scratch register
80
 
81
// Transmit control Registers
82
#define REG_thr SER_REG(0)    // Transmit holding register
83
#define REG_ier SER_REG(1)    // Interrupt enable register
84
#define REG_fcr SER_REG(2)    // FIFO control register
85
#define REG_lcr SER_REG(3)    // Line control register
86
#define REG_mcr SER_REG(4)    // Modem control register
87
#define REG_ldl SER_REG(0)    // LSB of baud rate
88
#define REG_mdl SER_REG(1)    // MSB of baud rate
89
 
90
// Interrupt Enable Register
91
#define IER_RCV 0x01
92
#define IER_XMT 0x02
93
#define IER_LS  0x04
94
#define IER_MS  0x08
95
 
96
// Line Control Register
97
#define LCR_WL5 0x00    // Word length
98
#define LCR_WL6 0x01
99
#define LCR_WL7 0x02
100
#define LCR_WL8 0x03
101
#define LCR_SB1 0x00    // Number of stop bits
102
#define LCR_SB1_5 0x04  // 1.5 -> only valid with 5 bit words
103
#define LCR_SB2 0x04
104
#define LCR_PN  0x00    // Parity mode - none
105
#define LCR_PE  0x18    // Parity mode - even
106
#define LCR_PO  0x08    // Parity mode - odd
107
#define LCR_PM  0x28    // Forced "mark" parity
108
#define LCR_PS  0x38    // Forced "space" parity
109
#define LCR_DL  0x80    // Enable baud rate latch
110
 
111
// Line Status Register
112
#define LSR_RSR 0x01
113
#define LSR_OE  0x02
114
#define LSR_PE  0x04
115
#define LSR_FE  0x08
116
#define LSR_BI  0x10
117
#define LSR_THE 0x20
118
#define LSR_TEMT 0x40
119
#define LSR_FIE 0x80
120
 
121
// Modem Control Register
122
#define MCR_DTR  0x01
123
#define MCR_RTS  0x02
124
#define MCR_INT  0x08   // Enable interrupts
125
#define MCR_LOOP 0x10   // Loopback mode
126
 
127
// Interrupt status Register
128
#define ISR_MS        0x00
129
#define ISR_nIP       0x01
130
#define ISR_Tx        0x02
131
#define ISR_Rx        0x04
132
#define ISR_LS        0x06
133
#define ISR_RxTO      0x0C
134
#define ISR_64BFIFO   0x20
135
#define ISR_FIFOworks 0x40
136
#define ISR_FIFOen    0x80
137
 
138
// Modem Status Register
139
#define MSR_DCTS 0x01
140
#define MSR_DDSR 0x02
141
#define MSR_TERI 0x04
142
#define MSR_DDCD 0x08
143
#define MSR_CTS  0x10
144
#define MSR_DSR  0x20
145
#define MSR_RI   0x40
146
#define MSR_CD   0x80
147
 
148
// FIFO Control Register
149
#define FCR_FE   0x01    // FIFO enable
150
#define FCR_CRF  0x02    // Clear receive FIFO
151
#define FCR_CTF  0x04    // Clear transmit FIFO
152
#define FCR_DMA  0x08    // DMA mode select
153
#define FCR_F64  0x20    // Enable 64 byte fifo (16750+)
154
#define FCR_RT14 0xC0    // Set Rx trigger at 14
155
#define FCR_RT8  0x80    // Set Rx trigger at 8
156
#define FCR_RT4  0x40    // Set Rx trigger at 4
157
#define FCR_RT1  0x00    // Set Rx trigger at 1
158
 
159
static unsigned char select_word_length[] = {
160
    LCR_WL5,    // 5 bits / word (char)
161
    LCR_WL6,
162
    LCR_WL7,
163
    LCR_WL8
164
};
165
 
166
static unsigned char select_stop_bits[] = {
167
    0,
168
    LCR_SB1,    // 1 stop bit
169
    LCR_SB1_5,  // 1.5 stop bit
170
    LCR_SB2     // 2 stop bits
171
};
172
 
173
static unsigned char select_parity[] = {
174
    LCR_PN,     // No parity
175
    LCR_PE,     // Even parity
176
    LCR_PO,     // Odd parity
177
    LCR_PM,     // Mark parity
178
    LCR_PS,     // Space parity
179
};
180
 
181
// selec_baud[] must be define by the client
182
 
183
typedef struct pc_serial_info {
184
    cyg_addrword_t base;
185
    int            int_num;
186
    cyg_interrupt  serial_interrupt;
187
    cyg_handle_t   serial_interrupt_handle;
188
#ifdef CYGPKG_IO_SERIAL_GENERIC_16X5X_FIFO
189
    enum {
190
        sNone = 0,
191
        s8250,
192
        s16450,
193
        s16550,
194
        s16550a
195
    } deviceType;
196
#endif
197
} pc_serial_info;
198
 
199
static bool pc_serial_init(struct cyg_devtab_entry *tab);
200
static bool pc_serial_putc(serial_channel *chan, unsigned char c);
201
static Cyg_ErrNo pc_serial_lookup(struct cyg_devtab_entry **tab,
202
                                  struct cyg_devtab_entry *sub_tab,
203
                                  const char *name);
204
static unsigned char pc_serial_getc(serial_channel *chan);
205
static Cyg_ErrNo pc_serial_set_config(serial_channel *chan, cyg_uint32 key,
206
                                      const void *xbuf, cyg_uint32 *len);
207
static void pc_serial_start_xmit(serial_channel *chan);
208
static void pc_serial_stop_xmit(serial_channel *chan);
209
 
210
static cyg_uint32 pc_serial_ISR(cyg_vector_t vector, cyg_addrword_t data);
211
static void       pc_serial_DSR(cyg_vector_t vector, cyg_ucount32 count,
212
                                cyg_addrword_t data);
213
 
214
static SERIAL_FUNS(pc_serial_funs,
215
                   pc_serial_putc,
216
                   pc_serial_getc,
217
                   pc_serial_set_config,
218
                   pc_serial_start_xmit,
219
                   pc_serial_stop_xmit
220
    );
221
 
222
#include CYGDAT_IO_SERIAL_GENERIC_16X5X_INL
223
 
224
// Internal function to actually configure the hardware to desired
225
// baud rate, etc.
226
static bool
227
serial_config_port(serial_channel *chan,
228
                   cyg_serial_info_t *new_config, bool init)
229
{
230
    pc_serial_info *ser_chan = (pc_serial_info *)chan->dev_priv;
231
    cyg_addrword_t base = ser_chan->base;
232
    unsigned short baud_divisor = select_baud[new_config->baud];
233
    unsigned char _lcr, _ier;
234
    if (baud_divisor == 0) return false;  // Invalid configuration
235
 
236
    // Disable port interrupts while changing hardware
237
    HAL_READ_UINT8(base+REG_ier, _ier);
238
    HAL_WRITE_UINT8(base+REG_ier, 0);
239
 
240
    _lcr = select_word_length[new_config->word_length - CYGNUM_SERIAL_WORD_LENGTH_5] |
241
        select_stop_bits[new_config->stop] |
242
        select_parity[new_config->parity];
243
    HAL_WRITE_UINT8(base+REG_lcr, _lcr | LCR_DL);
244
    HAL_WRITE_UINT8(base+REG_mdl, baud_divisor >> 8);
245
    HAL_WRITE_UINT8(base+REG_ldl, baud_divisor & 0xFF);
246
    HAL_WRITE_UINT8(base+REG_lcr, _lcr);
247
    if (init) {
248
#ifdef CYGPKG_IO_SERIAL_GENERIC_16X5X_FIFO
249
        unsigned char _fcr_thresh;
250
        cyg_uint8 b;
251
 
252
        /* First, find out what kind of device it is. */
253
        ser_chan->deviceType = sNone;
254
        HAL_WRITE_UINT8(base+REG_mcr, MCR_LOOP); // enable loopback mode
255
        HAL_READ_UINT8(base+REG_msr, b);
256
        if (0 == (b & 0xF0)) {   // see if MSR had CD, RI, DSR or CTS set
257
            HAL_WRITE_UINT8(base+REG_mcr, MCR_LOOP|MCR_DTR|MCR_RTS);
258
            HAL_READ_UINT8(base+REG_msr, b);
259
            if (0xF0 != (b & 0xF0))  // check that all of CD,RI,DSR and CTS set
260
                ser_chan->deviceType = s8250;
261
        }
262
        HAL_WRITE_UINT8(base+REG_mcr, 0); // disable loopback mode
263
 
264
        if (ser_chan->deviceType == s8250) {
265
            // Check for a scratch register; scratch register 
266
            // indicates 16450 or above.
267
            HAL_WRITE_UINT8(base+REG_scr, 0x55);
268
            HAL_READ_UINT8(base+REG_scr, b);
269
            if (b == 0x55) {
270
                HAL_WRITE_UINT8(base+REG_scr, 0xAA);
271
                HAL_READ_UINT8(base+REG_scr, b);
272
                if (b == 0xAA)
273
                    ser_chan->deviceType = s16450;
274
            }
275
        }
276
 
277
        if (ser_chan->deviceType == s16450) {
278
            // Check for a FIFO
279
            HAL_WRITE_UINT8(base+REG_fcr, FCR_FE);
280
            HAL_READ_UINT8(base+REG_isr, b);
281
            if (b & ISR_FIFOen)
282
                ser_chan->deviceType = s16550; // but FIFO doesn't 
283
                                               // necessarily work
284
            if (b & ISR_FIFOworks)
285
                ser_chan->deviceType = s16550a; // 16550a FIFOs work
286
        }
287
 
288
        if (ser_chan->deviceType == s16550a) {
289
            switch(CYGPKG_IO_SERIAL_GENERIC_16X5X_FIFO_RX_THRESHOLD) {
290
            default:
291
            case 1:
292
                _fcr_thresh=FCR_RT1; break;
293
            case 4:
294
                _fcr_thresh=FCR_RT4; break;
295
            case 8:
296
                _fcr_thresh=FCR_RT8; break;
297
            case 14:
298
                _fcr_thresh=FCR_RT14; break;
299
            }
300
            _fcr_thresh|=FCR_FE|FCR_CRF|FCR_CTF;
301
            HAL_WRITE_UINT8(base+REG_fcr, _fcr_thresh); // Enable and clear FIFO
302
        }
303
        else
304
            HAL_WRITE_UINT8(base+REG_fcr, 0); // make sure it's disabled
305
#endif
306
        if (chan->out_cbuf.len != 0) {
307
            _ier = IER_RCV;
308
        } else {
309
            _ier = 0;
310
        }
311
        // Master interrupt enable
312
        HAL_WRITE_UINT8(base+REG_mcr, MCR_INT|MCR_DTR|MCR_RTS);
313
    }
314
#ifdef CYGOPT_IO_SERIAL_SUPPORT_LINE_STATUS
315
    _ier |= (IER_LS|IER_MS);
316
#endif
317
    HAL_WRITE_UINT8(base+REG_ier, _ier);
318
 
319
    if (new_config != &chan->config) {
320
        chan->config = *new_config;
321
    }
322
    return true;
323
}
324
 
325
// Function to initialize the device.  Called at bootstrap time.
326
static bool
327
pc_serial_init(struct cyg_devtab_entry *tab)
328
{
329
    serial_channel *chan = (serial_channel *)tab->priv;
330
    pc_serial_info *ser_chan = (pc_serial_info *)chan->dev_priv;
331
#ifdef CYGDBG_IO_INIT
332
    diag_printf("16x5x SERIAL init - dev: %x.%d\n",
333
                ser_chan->base, ser_chan->int_num);
334
#endif
335
    // Really only required for interrupt driven devices
336
    (chan->callbacks->serial_init)(chan);
337
 
338
    if (chan->out_cbuf.len != 0) {
339
        cyg_drv_interrupt_create(ser_chan->int_num,
340
                                 99,
341
                                 (cyg_addrword_t)chan,
342
                                 pc_serial_ISR,
343
                                 pc_serial_DSR,
344
                                 &ser_chan->serial_interrupt_handle,
345
                                 &ser_chan->serial_interrupt);
346
        cyg_drv_interrupt_attach(ser_chan->serial_interrupt_handle);
347
        cyg_drv_interrupt_unmask(ser_chan->int_num);
348
    }
349
    serial_config_port(chan, &chan->config, true);
350
    return true;
351
}
352
 
353
// This routine is called when the device is "looked" up (i.e. attached)
354
static Cyg_ErrNo
355
pc_serial_lookup(struct cyg_devtab_entry **tab,
356
                 struct cyg_devtab_entry *sub_tab,
357
                 const char *name)
358
{
359
    serial_channel *chan = (serial_channel *)(*tab)->priv;
360
 
361
    // Really only required for interrupt driven devices
362
    (chan->callbacks->serial_init)(chan);
363
    return ENOERR;
364
}
365
 
366
// Send a character to the device output buffer.
367
// Return 'true' if character is sent to device
368
static bool
369
pc_serial_putc(serial_channel *chan, unsigned char c)
370
{
371
    cyg_uint8 _lsr;
372
    pc_serial_info *ser_chan = (pc_serial_info *)chan->dev_priv;
373
    cyg_addrword_t base = ser_chan->base;
374
 
375
    HAL_READ_UINT8(base+REG_lsr, _lsr);
376
    if (_lsr & LSR_THE) {
377
        // Transmit buffer is empty
378
        HAL_WRITE_UINT8(base+REG_thr, c);
379
        return true;
380
    }
381
    // No space
382
    return false;
383
}
384
 
385
// Fetch a character from the device input buffer, waiting if necessary
386
static unsigned char
387
pc_serial_getc(serial_channel *chan)
388
{
389
    unsigned char c;
390
    cyg_uint8 _lsr;
391
    pc_serial_info *ser_chan = (pc_serial_info *)chan->dev_priv;
392
    cyg_addrword_t base = ser_chan->base;
393
 
394
    // Wait for char
395
    do {
396
        HAL_READ_UINT8(base+REG_lsr, _lsr);
397
    } while ((_lsr & LSR_RSR) == 0);
398
 
399
    HAL_READ_UINT8(base+REG_rhr, c);
400
    return c;
401
}
402
 
403
// Set up the device characteristics; baud rate, etc.
404
static Cyg_ErrNo
405
pc_serial_set_config(serial_channel *chan, cyg_uint32 key, const void *xbuf,
406
                     cyg_uint32 *len)
407
{
408
    switch (key) {
409
    case CYG_IO_SET_CONFIG_SERIAL_INFO:
410
      {
411
        cyg_serial_info_t *config = (cyg_serial_info_t *)xbuf;
412
        if ( *len < sizeof(cyg_serial_info_t) ) {
413
            return -EINVAL;
414
        }
415
        *len = sizeof(cyg_serial_info_t);
416
        if ( true != serial_config_port(chan, config, false) )
417
            return -EINVAL;
418
      }
419
      break;
420
#ifdef CYGOPT_IO_SERIAL_FLOW_CONTROL_HW
421
    case CYG_IO_SET_CONFIG_SERIAL_HW_RX_FLOW_THROTTLE:
422
      {
423
          cyg_uint8 _mcr;
424
          pc_serial_info *ser_chan = (pc_serial_info *)chan->dev_priv;
425
          cyg_addrword_t base = ser_chan->base;
426
          cyg_uint8 *f = (cyg_uint8 *)xbuf;
427
          unsigned char mask=0;
428
          if ( *len < sizeof(*f) )
429
              return -EINVAL;
430
 
431
          if ( chan->config.flags & CYGNUM_SERIAL_FLOW_RTSCTS_RX )
432
              mask = MCR_RTS;
433
          if ( chan->config.flags & CYGNUM_SERIAL_FLOW_DSRDTR_RX )
434
              mask |= MCR_DTR;
435
          HAL_READ_UINT8(base+REG_mcr, _mcr);
436
          if (*f) // we should throttle
437
              _mcr &= ~mask;
438
          else // we should no longer throttle
439
              _mcr |= mask;
440
          HAL_WRITE_UINT8(base+REG_mcr, _mcr);
441
      }
442
      break;
443
    case CYG_IO_SET_CONFIG_SERIAL_HW_FLOW_CONFIG:
444
        // Nothing to do because we do support both RTSCTS and DSRDTR flow
445
        // control.
446
        // Other targets would clear any unsupported flags here.
447
        // We just return ENOERR.
448
      break;
449
#endif
450
    default:
451
        return -EINVAL;
452
    }
453
    return ENOERR;
454
}
455
 
456
// Enable the transmitter on the device
457
static void
458
pc_serial_start_xmit(serial_channel *chan)
459
{
460
    pc_serial_info *ser_chan = (pc_serial_info *)chan->dev_priv;
461
    cyg_addrword_t base = ser_chan->base;
462
    cyg_uint8 _ier;
463
 
464
    HAL_READ_UINT8(base+REG_ier, _ier);
465
    _ier |= IER_XMT;                    // Enable xmit interrupt
466
    HAL_WRITE_UINT8(base+REG_ier, _ier);
467
}
468
 
469
// Disable the transmitter on the device
470
static void
471
pc_serial_stop_xmit(serial_channel *chan)
472
{
473
    pc_serial_info *ser_chan = (pc_serial_info *)chan->dev_priv;
474
    cyg_addrword_t base = ser_chan->base;
475
    cyg_uint8 _ier;
476
 
477
    HAL_READ_UINT8(base+REG_ier, _ier);
478
    _ier &= ~IER_XMT;                   // Disable xmit interrupt
479
    HAL_WRITE_UINT8(base+REG_ier, _ier);
480
}
481
 
482
// Serial I/O - low level interrupt handler (ISR)
483
static cyg_uint32
484
pc_serial_ISR(cyg_vector_t vector, cyg_addrword_t data)
485
{
486
    serial_channel *chan = (serial_channel *)data;
487
    pc_serial_info *ser_chan = (pc_serial_info *)chan->dev_priv;
488
    cyg_drv_interrupt_mask(ser_chan->int_num);
489
    cyg_drv_interrupt_acknowledge(ser_chan->int_num);
490
    return CYG_ISR_CALL_DSR;  // Cause DSR to be run
491
}
492
 
493
// Serial I/O - high level interrupt handler (DSR)
494
static void
495
pc_serial_DSR(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data)
496
{
497
    serial_channel *chan = (serial_channel *)data;
498
    pc_serial_info *ser_chan = (pc_serial_info *)chan->dev_priv;
499
    cyg_addrword_t base = ser_chan->base;
500
    cyg_uint8 _isr;
501
 
502
    // Check if we have an interrupt pending - note that the interrupt
503
    // is pending of the low bit of the isr is *0*, not 1.
504
    HAL_READ_UINT8(base+REG_isr, _isr);
505
    while ((_isr & ISR_nIP) == 0) {
506
        switch (_isr&0xE) {
507
        case ISR_Rx:
508
        case ISR_RxTO:
509
        {
510
            cyg_uint8 _lsr;
511
            unsigned char c;
512
            HAL_READ_UINT8(base+REG_lsr, _lsr);
513
            while(_lsr & LSR_RSR) {
514
                HAL_READ_UINT8(base+REG_rhr, c);
515
                (chan->callbacks->rcv_char)(chan, c);
516
                HAL_READ_UINT8(base+REG_lsr, _lsr);
517
            }
518
            break;
519
        }
520
        case ISR_Tx:
521
            (chan->callbacks->xmt_char)(chan);
522
            break;
523
 
524
#ifdef CYGOPT_IO_SERIAL_SUPPORT_LINE_STATUS
525
        case ISR_LS:
526
            {
527
                cyg_serial_line_status_t stat;
528
                cyg_uint8 _lsr;
529
                HAL_READ_UINT8(base+REG_lsr, _lsr);
530
 
531
                // this might look expensive, but it is rarely the case that
532
                // more than one of these is set
533
                stat.value = 1;
534
                if ( _lsr & LSR_OE ) {
535
                    stat.which = CYGNUM_SERIAL_STATUS_OVERRUNERR;
536
                    (chan->callbacks->indicate_status)(chan, &stat );
537
                }
538
                if ( _lsr & LSR_PE ) {
539
                    stat.which = CYGNUM_SERIAL_STATUS_PARITYERR;
540
                    (chan->callbacks->indicate_status)(chan, &stat );
541
                }
542
                if ( _lsr & LSR_FE ) {
543
                    stat.which = CYGNUM_SERIAL_STATUS_FRAMEERR;
544
                    (chan->callbacks->indicate_status)(chan, &stat );
545
                }
546
                if ( _lsr & LSR_BI ) {
547
                    stat.which = CYGNUM_SERIAL_STATUS_BREAK;
548
                    (chan->callbacks->indicate_status)(chan, &stat );
549
                }
550
            }
551
            break;
552
 
553
        case ISR_MS:
554
            {
555
                cyg_serial_line_status_t stat;
556
                cyg_uint8 _msr;
557
 
558
                HAL_READ_UINT8(base+REG_msr, _msr);
559
#ifdef CYGOPT_IO_SERIAL_FLOW_CONTROL_HW
560
                if ( _msr & MSR_DDSR )
561
                    if ( chan->config.flags & CYGNUM_SERIAL_FLOW_DSRDTR_TX ) {
562
                        stat.which = CYGNUM_SERIAL_STATUS_FLOW;
563
                        stat.value = (0 != (_msr & MSR_DSR));
564
                        (chan->callbacks->indicate_status)(chan, &stat );
565
                    }
566
                if ( _msr & MSR_DCTS )
567
                    if ( chan->config.flags & CYGNUM_SERIAL_FLOW_RTSCTS_TX ) {
568
                        stat.which = CYGNUM_SERIAL_STATUS_FLOW;
569
                        stat.value = (0 != (_msr & MSR_CTS));
570
                        (chan->callbacks->indicate_status)(chan, &stat );
571
                    }
572
#endif
573
                if ( _msr & MSR_DDCD ) {
574
                    stat.which = CYGNUM_SERIAL_STATUS_CARRIERDETECT;
575
                    stat.value = (0 != (_msr & MSR_CD));
576
                    (chan->callbacks->indicate_status)(chan, &stat );
577
                }
578
                if ( _msr & MSR_RI ) {
579
                    stat.which = CYGNUM_SERIAL_STATUS_RINGINDICATOR;
580
                    stat.value = 1;
581
                    (chan->callbacks->indicate_status)(chan, &stat );
582
                }
583
                if ( _msr & MSR_TERI ) {
584
                    stat.which = CYGNUM_SERIAL_STATUS_RINGINDICATOR;
585
                    stat.value = 0;
586
                    (chan->callbacks->indicate_status)(chan, &stat );
587
                }
588
            }
589
            break;
590
#endif
591
        default:
592
            // Yes, this assertion may well not be visible. *But*
593
            // if debugging, we may still successfully hit a breakpoint
594
            // on cyg_assert_fail, which _is_ useful
595
            CYG_FAIL("unhandled serial interrupt state");
596
        }
597
 
598
        HAL_READ_UINT8(base+REG_isr, _isr);
599
    } // while
600
 
601
    cyg_drv_interrupt_unmask(ser_chan->int_num);
602
}
603
#endif
604
 
605
// EOF ser_16x5x.c

powered by: WebSVN 2.1.0

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