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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-2.0/] [packages/] [devs/] [serial/] [loop/] [v2_0/] [src/] [loop_serial.c] - Blame information for rev 773

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

Line No. Rev Author Line
1 27 unneback
//==========================================================================
2
//
3
//      loop_serial.c
4
//
5
//      Loopback serial device 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):   nickg
44
// Contributors: nickg
45
// Date:        1999-02-25
46
// Purpose:     Loopback serial device driver
47
// Description: This device driver implements a pair of serial lines that are
48
//              connected back-to-back. Data output to one will appear as
49
//              input on the other. This process in in part driven by an alarm
50
//              object which provides a degree of separation between the two
51
//              channels.
52
//
53
//####DESCRIPTIONEND####
54
//
55
//==========================================================================
56
 
57
#include <pkgconf/hal.h>
58
#include <pkgconf/io_serial.h>
59
#include <pkgconf/io_serial_loop.h>
60
#include <cyg/hal/hal_io.h>
61
 
62
#include <cyg/io/io.h>
63
#include <cyg/io/devtab.h>
64
#include <cyg/io/serial.h>
65
#include <cyg/hal/hal_intr.h>
66
#include <cyg/kernel/kapi.h>
67
 
68
#ifdef CYGPKG_IO_SERIAL_LOOP
69
 
70
//-------------------------------------------------------------------------
71
 
72
extern void diag_printf(const char *fmt, ...);
73
 
74
//-------------------------------------------------------------------------
75
// Forward definitions
76
 
77
static bool loop_serial_init(struct cyg_devtab_entry *tab);
78
static bool loop_serial_putc(serial_channel *chan, unsigned char c);
79
static Cyg_ErrNo loop_serial_lookup(struct cyg_devtab_entry **tab,
80
                                   struct cyg_devtab_entry *sub_tab,
81
                                   const char *name);
82
static unsigned char loop_serial_getc(serial_channel *chan);
83
static Cyg_ErrNo loop_serial_set_config(serial_channel *chan, cyg_uint32 key,
84
                                        const void *xbuf, cyg_uint32 *len);
85
static void loop_serial_start_xmit(serial_channel *chan);
86
static void loop_serial_stop_xmit(serial_channel *chan);
87
 
88
#ifndef CYGPKG_IO_SERIAL_LOOP_POLLED_MODE
89
static void alarm_handler(cyg_handle_t alarm, cyg_addrword_t data);
90
#endif
91
 
92
//-------------------------------------------------------------------------
93
// Alarm object for feeding data back into serial channels
94
 
95
static cyg_alarm alarm_obj;
96
 
97
static cyg_handle_t alarm_handle;
98
 
99
//-------------------------------------------------------------------------
100
// Transfer FIFOs
101
 
102
#define FIFO_SIZE 16
103
 
104
struct fifo
105
{
106
    cyg_bool            tx_enable;
107
    volatile int        head;
108
    volatile int        tail;
109
    volatile int        num;
110
    volatile char       buf[FIFO_SIZE+1];
111
};
112
 
113
static struct fifo fifo0 = { false, 0, 0, 0 };   // from serial0 to serial1
114
static struct fifo fifo1 = { false, 0, 0, 0 };   // from serial1 to serial0
115
 
116
//-------------------------------------------------------------------------
117
 
118
#define BUFSIZE 128
119
 
120
//-------------------------------------------------------------------------
121
// Info for each serial device controlled
122
 
123
typedef struct loop_serial_info {
124
    struct fifo         *write_fifo;
125
    struct fifo         *read_fifo;
126
} loop_serial_info;
127
 
128
//-------------------------------------------------------------------------
129
// Callback functions exported by this driver
130
 
131
static SERIAL_FUNS(loop_serial_funs,
132
                   loop_serial_putc,
133
                   loop_serial_getc,
134
                   loop_serial_set_config,
135
                   loop_serial_start_xmit,
136
                   loop_serial_stop_xmit
137
    );
138
 
139
//-------------------------------------------------------------------------
140
// Hardware info for each serial line
141
 
142
#ifdef CYGPKG_IO_SERIAL_LOOP_SERIAL0
143
static loop_serial_info loop_serial_info0 = {
144
    &fifo0,
145
    &fifo1
146
};
147
#if CYGNUM_IO_SERIAL_LOOP_SERIAL0_BUFSIZE > 0
148
static unsigned char loop_serial_out_buf0[CYGNUM_IO_SERIAL_LOOP_SERIAL0_BUFSIZE];
149
static unsigned char loop_serial_in_buf0[CYGNUM_IO_SERIAL_LOOP_SERIAL0_BUFSIZE];
150
#endif
151
#endif // CYGPKG_IO_SERIAL_LOOP_SERIAL0
152
 
153
#ifdef CYGPKG_IO_SERIAL_LOOP_SERIAL1
154
static loop_serial_info loop_serial_info1 = {
155
    &fifo1,
156
    &fifo0
157
};
158
#if CYGNUM_IO_SERIAL_LOOP_SERIAL1_BUFSIZE > 0
159
static unsigned char loop_serial_out_buf1[CYGNUM_IO_SERIAL_LOOP_SERIAL1_BUFSIZE];
160
static unsigned char loop_serial_in_buf1[CYGNUM_IO_SERIAL_LOOP_SERIAL1_BUFSIZE];
161
#endif
162
#endif // CYGPKG_IO_SERIAL_LOOP_SERIAL1
163
 
164
//-------------------------------------------------------------------------
165
// Channel descriptions:
166
 
167
#ifdef CYGPKG_IO_SERIAL_LOOP_POLLED_MODE
168
#define SIZEOF_BUF(_x_) 0
169
#else
170
#define SIZEOF_BUF(_x_) sizeof(_x_)
171
#endif
172
 
173
#ifdef CYGPKG_IO_SERIAL_LOOP_SERIAL0
174
#if CYGNUM_IO_SERIAL_LOOP_SERIAL0_BUFSIZE > 0
175
static SERIAL_CHANNEL_USING_INTERRUPTS(loop_serial_channel0,
176
                                       loop_serial_funs,
177
                                       loop_serial_info0,
178
                                       CYG_SERIAL_BAUD_RATE(CYGNUM_IO_SERIAL_LOOP_SERIAL0_BAUD),
179
                                       CYG_SERIAL_STOP_DEFAULT,
180
                                       CYG_SERIAL_PARITY_DEFAULT,
181
                                       CYG_SERIAL_WORD_LENGTH_DEFAULT,
182
                                       CYG_SERIAL_FLAGS_DEFAULT,
183
                                       &loop_serial_out_buf0[0],
184
                                       SIZEOF_BUF(loop_serial_out_buf0),
185
                                       &loop_serial_in_buf0[0],
186
                                       SIZEOF_BUF(loop_serial_in_buf0)
187
    );
188
#else
189
static SERIAL_CHANNEL(loop_serial_channel0,
190
                      loop_serial_funs,
191
                      loop_serial_info0,
192
                      CYG_SERIAL_BAUD_RATE(CYGNUM_IO_SERIAL_LOOP_SERIAL0_BAUD),
193
                      CYG_SERIAL_STOP_DEFAULT,
194
                      CYG_SERIAL_PARITY_DEFAULT,
195
                      CYG_SERIAL_WORD_LENGTH_DEFAULT,
196
                      CYG_SERIAL_FLAGS_DEFAULT
197
    );
198
#endif
199
#endif // CYGPKG_IO_SERIAL_LOOP_SERIAL0
200
 
201
#ifdef CYGPKG_IO_SERIAL_LOOP_SERIAL1
202
#if CYGNUM_IO_SERIAL_LOOP_SERIAL1_BUFSIZE > 0
203
static SERIAL_CHANNEL_USING_INTERRUPTS(loop_serial_channel1,
204
                                       loop_serial_funs,
205
                                       loop_serial_info1,
206
                                       CYG_SERIAL_BAUD_RATE(CYGNUM_IO_SERIAL_LOOP_SERIAL1_BAUD),
207
                                       CYG_SERIAL_STOP_DEFAULT,
208
                                       CYG_SERIAL_PARITY_DEFAULT,
209
                                       CYG_SERIAL_WORD_LENGTH_DEFAULT,
210
                                       CYG_SERIAL_FLAGS_DEFAULT,
211
                                       &loop_serial_out_buf1[0],
212
                                       SIZEOF_BUF(loop_serial_out_buf1),
213
                                       &loop_serial_in_buf1[0],
214
                                       SIZEOF_BUF(loop_serial_in_buf1)
215
    );
216
#else
217
static SERIAL_CHANNEL(loop_serial_channel1,
218
                      loop_serial_funs,
219
                      loop_serial_info1,
220
                      CYG_SERIAL_BAUD_RATE(CYGNUM_IO_SERIAL_LOOP_SERIAL1_BAUD),
221
                      CYG_SERIAL_STOP_DEFAULT,
222
                      CYG_SERIAL_PARITY_DEFAULT,
223
                      CYG_SERIAL_WORD_LENGTH_DEFAULT,
224
                      CYG_SERIAL_FLAGS_DEFAULT
225
    );
226
#endif
227
#endif // CYGPKG_IO_SERIAL_LOOP_SERIAL1
228
 
229
//-------------------------------------------------------------------------
230
// And finally, the device table entries:
231
 
232
#ifdef CYGPKG_IO_SERIAL_LOOP_SERIAL0
233
DEVTAB_ENTRY(loop_serial_io0,
234
             CYGDAT_IO_SERIAL_LOOP_SERIAL0_NAME,
235
             0,                     // Does not depend on a lower level interface
236
             &cyg_io_serial_devio,
237
             loop_serial_init,
238
             loop_serial_lookup,     // Serial driver may need initializing
239
             &loop_serial_channel0
240
    );
241
#endif // CYGPKG_IO_SERIAL_LOOP_SERIAL0
242
 
243
#ifdef CYGPKG_IO_SERIAL_LOOP_SERIAL1
244
DEVTAB_ENTRY(loop_serial_io1,
245
             CYGDAT_IO_SERIAL_LOOP_SERIAL1_NAME,
246
             0,                     // Does not depend on a lower level interface
247
             &cyg_io_serial_devio,
248
             loop_serial_init,
249
             loop_serial_lookup,     // Serial driver may need initializing
250
             &loop_serial_channel1
251
    );
252
#endif // CYGPKG_IO_SERIAL_LOOP_SERIAL1
253
 
254
//-------------------------------------------------------------------------
255
 
256
static bool
257
loop_serial_config_port(serial_channel *chan, cyg_serial_info_t *new_config, bool init)
258
{
259
//    loop_serial_info *loop_chan = (loop_serial_info *)chan->dev_priv;
260
 
261
    if (new_config != &chan->config) {
262
        chan->config = *new_config;
263
    }
264
    return true;
265
}
266
 
267
//-------------------------------------------------------------------------
268
// Function to initialize the device.  Called at bootstrap time.
269
 
270
bool loop_serial_init(struct cyg_devtab_entry *tab)
271
{
272
    serial_channel *chan = (serial_channel *)tab->priv;
273
//    loop_serial_info *loop_chan = (loop_serial_info *)chan->dev_priv;
274
 
275
    (chan->callbacks->serial_init)(chan);  // Really only required for interrupt driven devices
276
 
277
#ifndef CYGPKG_IO_SERIAL_LOOP_POLLED_MODE    
278
 
279
    // Set up alarm for feeding data back into channels
280
 
281
    cyg_alarm_create( cyg_real_time_clock(),
282
                      alarm_handler,
283
                      0,
284
                      &alarm_handle,
285
                      &alarm_obj);
286
 
287
    cyg_alarm_initialize( alarm_handle, 1, 1 );
288
 
289
#endif
290
 
291
    loop_serial_config_port(chan, &chan->config, true);
292
 
293
    return true;
294
}
295
 
296
//-------------------------------------------------------------------------
297
// This routine is called when the device is "looked" up (i.e. attached)
298
 
299
static Cyg_ErrNo
300
loop_serial_lookup(struct cyg_devtab_entry **tab,
301
                  struct cyg_devtab_entry *sub_tab,
302
                  const char *name)
303
{
304
    serial_channel *chan = (serial_channel *)(*tab)->priv;
305
    (chan->callbacks->serial_init)(chan);  // Really only required for interrupt driven devices
306
    return ENOERR;
307
}
308
 
309
//-------------------------------------------------------------------------
310
// Return 'true' if character is sent to device
311
 
312
bool
313
loop_serial_putc(serial_channel *chan, unsigned char c)
314
{
315
    loop_serial_info *loop_chan = (loop_serial_info *)chan->dev_priv;
316
 
317
    struct fifo *f = loop_chan->write_fifo;
318
 
319
    if( f->num == FIFO_SIZE )
320
        return false;
321
 
322
    f->buf[f->tail] = c;
323
    f->num++;
324
    f->tail++;
325
    if( f->tail == sizeof(f->buf) )
326
        f->tail = 0;
327
 
328
    return true;
329
}
330
 
331
//-------------------------------------------------------------------------
332
 
333
unsigned char
334
loop_serial_getc(serial_channel *chan)
335
{
336
    unsigned char c;
337
    loop_serial_info *loop_chan = (loop_serial_info *)chan->dev_priv;
338
 
339
    struct fifo *f = loop_chan->read_fifo;
340
 
341
    while( f->num == 0 )
342
        continue;
343
 
344
    c = f->buf[f->head];
345
    f->num--;
346
    f->head++;
347
    if( f->head == sizeof(f->buf) )
348
        f->head = 0;
349
 
350
    return c;
351
}
352
 
353
//-------------------------------------------------------------------------
354
 
355
static Cyg_ErrNo
356
loop_serial_set_config(serial_channel *chan, cyg_uint32 key,
357
                       const void *xbuf, cyg_uint32 *len)
358
{
359
    switch (key) {
360
    case CYG_IO_SET_CONFIG_SERIAL_INFO:
361
      {
362
        cyg_serial_info_t *config = (cyg_serial_info_t *)xbuf;
363
        if ( *len < sizeof(cyg_serial_info_t) ) {
364
            return -EINVAL;
365
        }
366
        *len = sizeof(cyg_serial_info_t);
367
        if ( true != loop_serial_config_port(chan, config, false) )
368
            return -EINVAL;
369
      }
370
      break;
371
    default:
372
        return -EINVAL;
373
    }
374
    return ENOERR;
375
}
376
 
377
//-------------------------------------------------------------------------
378
// Enable the transmitter on the device
379
 
380
static void
381
loop_serial_start_xmit(serial_channel *chan)
382
{
383
#ifndef CYGPKG_IO_SERIAL_LOOP_POLLED_MODE    
384
    loop_serial_info *loop_chan = (loop_serial_info *)chan->dev_priv;
385
 
386
    loop_chan->write_fifo->tx_enable = true;
387
 
388
    (chan->callbacks->xmt_char)(chan);
389
#endif    
390
}
391
 
392
//-------------------------------------------------------------------------
393
// Disable the transmitter on the device
394
 
395
static void
396
loop_serial_stop_xmit(serial_channel *chan)
397
{
398
#ifndef CYGPKG_IO_SERIAL_LOOP_POLLED_MODE    
399
    loop_serial_info *loop_chan = (loop_serial_info *)chan->dev_priv;
400
 
401
    loop_chan->write_fifo->tx_enable = false;
402
 
403
#endif    
404
}
405
 
406
//-------------------------------------------------------------------------
407
 
408
static void alarm_handler(cyg_handle_t alarm, cyg_addrword_t data)
409
{
410
    serial_channel *chan0 = &loop_serial_channel0;
411
    serial_channel *chan1 = &loop_serial_channel1;
412
 
413
    while( fifo0.num )
414
    {
415
        // Data ready for delivery to serial1
416
 
417
        struct fifo *f = &fifo0;
418
        char c;
419
 
420
        c = f->buf[f->head];
421
        f->num--;
422
        f->head++;
423
        if( f->head == sizeof(f->buf) )
424
            f->head = 0;
425
 
426
        (chan1->callbacks->rcv_char)(chan1, c);
427
        if( f->tx_enable )
428
            (chan0->callbacks->xmt_char)(chan0);
429
    }
430
 
431
    while( fifo1.num )
432
    {
433
        // Data ready for delivery to serial0
434
 
435
        struct fifo *f = &fifo1;
436
        char c;
437
 
438
        c = f->buf[f->head];
439
        f->num--;
440
        f->head++;
441
        if( f->head == sizeof(f->buf) )
442
            f->head = 0;
443
 
444
        (chan0->callbacks->rcv_char)(chan0, c);
445
        if( f->tx_enable )
446
            (chan1->callbacks->xmt_char)(chan1);
447
    }
448
 
449
 
450
 
451
}
452
 
453
 
454
#endif // CYGPKG_IO_SERIAL_LOOP
455
 
456
//-------------------------------------------------------------------------
457
// EOF loop.c

powered by: WebSVN 2.1.0

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