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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-3.0/] [packages/] [devs/] [serial/] [sparclite/] [sleb/] [current/] [src/] [sleb_sdtr.c] - Blame information for rev 786

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 786 skrzyp
//==========================================================================
2
//
3
//      io/serial/sparclite/sleb_sdtr.c
4
//
5
//      Serial I/O interface module for SPARClite Eval Board (SLEB)
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 Free Software Foundation, 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      
16
// version.                                                                 
17
//
18
// eCos is distributed in the hope that it will be useful, but WITHOUT      
19
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or    
20
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License    
21
// for more details.                                                        
22
//
23
// You should have received a copy of the GNU General Public License        
24
// along with eCos; if not, write to the Free Software Foundation, Inc.,    
25
// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.            
26
//
27
// As a special exception, if other files instantiate templates or use      
28
// macros or inline functions from this file, or you compile this file      
29
// and link it with other works to produce a work based on this file,       
30
// this file does not by itself cause the resulting work to be covered by   
31
// the GNU General Public License. However the source code for this file    
32
// must still be made available in accordance with section (3) of the GNU   
33
// General Public License v2.                                               
34
//
35
// This exception does not invalidate any other reasons why a work based    
36
// on this file might be covered by the GNU General Public License.         
37
// -------------------------------------------                              
38
// ####ECOSGPLCOPYRIGHTEND####                                              
39
//==========================================================================
40
//#####DESCRIPTIONBEGIN####
41
//
42
// Author(s):   gthomas
43
// Contributors:  gthomas
44
// Date:        1999-02-04
45
// Purpose:     SLEB serial I/O module
46
// Description: 
47
//
48
//####DESCRIPTIONEND####
49
//
50
//==========================================================================
51
 
52
#include <pkgconf/io.h>
53
#include <pkgconf/io_serial.h>
54
#include <cyg/io/io.h>
55
#include <cyg/hal/hal_intr.h>
56
#include <cyg/io/devtab.h>
57
#include <cyg/io/serial.h>
58
 
59
#ifdef  CYGPKG_IO_SERIAL_SPARCLITE_SLEB
60
 
61
#include "sleb_sdtr.h"
62
 
63
extern void diag_printf(const char *fmt, ...);
64
 
65
#define BUFSIZE 128
66
 
67
typedef struct sleb_sdtr_info {
68
    CYG_ADDRWORD   base;
69
    CYG_WORD       tx_int_num;
70
    CYG_WORD       rx_int_num;
71
    cyg_interrupt  tx_serial_interrupt;
72
    cyg_handle_t   tx_serial_interrupt_handle;
73
    cyg_interrupt  rx_serial_interrupt;
74
    cyg_handle_t   rx_serial_interrupt_handle;
75
    cyg_uint8      cmd_reg;
76
    bool           xmit_enabled;
77
} sleb_sdtr_info;
78
 
79
static bool sleb_sdtr_init(struct cyg_devtab_entry *tab);
80
static bool sleb_sdtr_putc(serial_channel *chan, unsigned char c);
81
static Cyg_ErrNo sleb_sdtr_lookup(struct cyg_devtab_entry **tab,
82
                                   struct cyg_devtab_entry *sub_tab,
83
                                   const char *name);
84
static unsigned char sleb_sdtr_getc(serial_channel *chan);
85
static Cyg_ErrNo sleb_sdtr_set_config(serial_channel *chan, cyg_uint32 key,
86
                                      const void *xbuf, cyg_uint32 *len);
87
static void sleb_sdtr_start_xmit(serial_channel *chan);
88
static void sleb_sdtr_stop_xmit(serial_channel *chan);
89
 
90
static cyg_uint32 sleb_sdtr_tx_ISR(cyg_vector_t vector, cyg_addrword_t data);
91
static void       sleb_sdtr_tx_DSR(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data);
92
static cyg_uint32 sleb_sdtr_rx_ISR(cyg_vector_t vector, cyg_addrword_t data);
93
static void       sleb_sdtr_rx_DSR(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data);
94
 
95
static SERIAL_FUNS(sleb_sdtr_funs,
96
                   sleb_sdtr_putc,
97
                   sleb_sdtr_getc,
98
                   sleb_sdtr_set_config,
99
                   sleb_sdtr_start_xmit,
100
                   sleb_sdtr_stop_xmit
101
    );
102
 
103
#ifdef CYGPKG_IO_SERIAL_SPARCLITE_SLEB_CON1
104
static sleb_sdtr_info sleb_sdtr_info0 = {SLEB_SDTR0_BASE, SLEB_SDTR0_TX_INT, SLEB_SDTR0_RX_INT};
105
#if CYGNUM_IO_SERIAL_SPARCLITE_SLEB_CON1_BUFSIZE > 0
106
static unsigned char sleb_sdtr_out_buf0[CYGNUM_IO_SERIAL_SPARCLITE_SLEB_CON1_BUFSIZE];
107
static unsigned char sleb_sdtr_in_buf0[CYGNUM_IO_SERIAL_SPARCLITE_SLEB_CON1_BUFSIZE];
108
 
109
static SERIAL_CHANNEL_USING_INTERRUPTS(sleb_sdtr_channel0,
110
                                       sleb_sdtr_funs,
111
                                       sleb_sdtr_info0,
112
                                       CYG_SERIAL_BAUD_RATE(CYGNUM_IO_SERIAL_SPARCLITE_SLEB_CON1_BAUD),
113
                                       CYG_SERIAL_STOP_DEFAULT,
114
                                       CYG_SERIAL_PARITY_DEFAULT,
115
                                       CYG_SERIAL_WORD_LENGTH_DEFAULT,
116
                                       CYG_SERIAL_FLAGS_DEFAULT,
117
                                       &sleb_sdtr_out_buf0[0], sizeof(sleb_sdtr_out_buf0),
118
                                       &sleb_sdtr_in_buf0[0], sizeof(sleb_sdtr_in_buf0)
119
    );
120
#else
121
static SERIAL_CHANNEL(sleb_sdtr_channel0,
122
                      sleb_sdtr_funs,
123
                      sleb_sdtr_info0,
124
                      CYG_SERIAL_BAUD_RATE(CYGNUM_IO_SERIAL_SPARCLITE_SLEB_CON1_BAUD),
125
                      CYG_SERIAL_STOP_DEFAULT,
126
                      CYG_SERIAL_PARITY_DEFAULT,
127
                      CYG_SERIAL_WORD_LENGTH_DEFAULT,
128
                      CYG_SERIAL_FLAGS_DEFAULT
129
    );
130
#endif
131
 
132
DEVTAB_ENTRY(sleb_sdtr_io0,
133
             CYGDAT_IO_SERIAL_SPARCLITE_SLEB_CON1_NAME,
134
             0,                     // Does not depend on a lower level interface
135
             &cyg_io_serial_devio,
136
             sleb_sdtr_init,
137
             sleb_sdtr_lookup,     // Serial driver may need initializing
138
             &sleb_sdtr_channel0
139
    );
140
#endif // CYGPKG_IO_SERIAL_SPARCLITE_SLEB_CON1
141
 
142
#ifdef  CYGPKG_IO_SERIAL_SPARCLITE_SLEB_CON2
143
static sleb_sdtr_info sleb_sdtr_info1 = {SLEB_SDTR1_BASE, SLEB_SDTR1_TX_INT, SLEB_SDTR1_RX_INT};
144
#if CYGNUM_IO_SERIAL_SPARCLITE_SLEB_CON2_BUFSIZE > 0
145
static unsigned char sleb_sdtr_out_buf1[CYGNUM_IO_SERIAL_SPARCLITE_SLEB_CON2_BUFSIZE];
146
static unsigned char sleb_sdtr_in_buf1[CYGNUM_IO_SERIAL_SPARCLITE_SLEB_CON2_BUFSIZE];
147
 
148
static SERIAL_CHANNEL_USING_INTERRUPTS(sleb_sdtr_channel1,
149
                                       sleb_sdtr_funs,
150
                                       sleb_sdtr_info1,
151
                                       CYG_SERIAL_BAUD_RATE(CYGNUM_IO_SERIAL_SPARCLITE_SLEB_CON2_BAUD),
152
                                       CYG_SERIAL_STOP_DEFAULT,
153
                                       CYG_SERIAL_PARITY_DEFAULT,
154
                                       CYG_SERIAL_WORD_LENGTH_DEFAULT,
155
                                       CYG_SERIAL_FLAGS_DEFAULT,
156
                                       &sleb_sdtr_out_buf1[0], sizeof(sleb_sdtr_out_buf1),
157
                                       &sleb_sdtr_in_buf1[0], sizeof(sleb_sdtr_in_buf1)
158
    );
159
#else
160
static SERIAL_CHANNEL(sleb_sdtr_channel1,
161
                      sleb_sdtr_funs,
162
                      sleb_sdtr_info1,
163
                      CYG_SERIAL_BAUD_RATE(CYGNUM_IO_SERIAL_SPARCLITE_SLEB_CON2_BAUD),
164
                      CYG_SERIAL_STOP_DEFAULT,
165
                      CYG_SERIAL_PARITY_DEFAULT,
166
                      CYG_SERIAL_WORD_LENGTH_DEFAULT,
167
                      CYG_SERIAL_FLAGS_DEFAULT
168
    );
169
#endif
170
 
171
DEVTAB_ENTRY(sleb_sdtr_io1,
172
             CYGDAT_IO_SERIAL_SPARCLITE_SLEB_CON2_NAME,
173
             0,                     // Does not depend on a lower level interface
174
             &cyg_io_serial_devio,
175
             sleb_sdtr_init,
176
             sleb_sdtr_lookup,     // Serial driver may need initializing
177
             &sleb_sdtr_channel1
178
    );
179
#endif // CYGPKG_IO_SERIAL_SPARCLITE_SLEB_CON2
180
 
181
// Internal function to actually configure the hardware to desired baud rate, etc.
182
static bool
183
sleb_sdtr_config_port(serial_channel *chan, cyg_serial_info_t *new_config, bool init)
184
{
185
    sleb_sdtr_info *sdtr_chan = (sleb_sdtr_info *)chan->dev_priv;
186
    CYG_ADDRWORD port = sdtr_chan->base;
187
    cyg_int32 baud_divisor;
188
    cyg_int32 clk, tval;
189
    unsigned char mode;
190
#if 0
191
    if ((new_config->baud < CYGNUM_SERIAL_BAUD_MIN) || (new_config->baud > CYGNUM_SERIAL_BAUD_MAX))
192
        return false;  // Invalid baud rate
193
#endif
194
    baud_divisor = select_baud[new_config->baud];
195
    if (baud_divisor == 0)
196
        return false; // Unsupported baud rate
197
    // Reset the port
198
    HAL_SPARC_86940_WRITE(SDTR_CONTROL(port), SDTR_CMD_RST);
199
    // Write the mode
200
    mode = SDTR_MODE_MODE_ASYNC16 |
201
        select_word_length[new_config->word_length - CYGNUM_SERIAL_WORD_LENGTH_5] |
202
        select_stop_bits[new_config->stop] |
203
        select_parity[new_config->parity];
204
    HAL_SPARC_86940_WRITE(SDTR_CONTROL(port), mode);
205
    // Set baud rate clock.
206
    // ***** CAUTION! Both ports use the same time, thus they must both run at the same baud rate!
207
    clk = *SLEB_CLOCK_SWITCH;  // Compute board speed
208
    if (clk & 0x80)  clk = 10;
209
    clk = (clk & 0x3F) * 1000000;  // in MHz
210
    tval = (clk / (baud_divisor * 32)) - 1;
211
    HAL_SPARC_86940_WRITE(SLEB_TIMER3_RELOAD, tval);
212
    // Set up control register
213
    sdtr_chan->cmd_reg = SDTR_CMD_RTS | SDTR_CMD_DTR | SDTR_CMD_TxEN;
214
#ifdef CYGPKG_IO_SERIAL_SPARCLITE_SLEB_CON1
215
    // Cygmon needs the receiver
216
    if ((chan->out_cbuf.len != 0) || (chan == &sleb_sdtr_channel0)) {
217
#else
218
    if (chan->out_cbuf.len != 0) {
219
#endif
220
        sdtr_chan->cmd_reg |= SDTR_CMD_RxEN;
221
    }
222
    if (init) {
223
        sdtr_chan->xmit_enabled = false;
224
    }
225
    HAL_SPARC_86940_WRITE(SDTR_CONTROL(port), sdtr_chan->cmd_reg);
226
    if (new_config != &chan->config)
227
        chan->config = *new_config;
228
    return true;
229
}
230
 
231
// Function to initialize the device.  Called at bootstrap time.
232
static bool
233
sleb_sdtr_init(struct cyg_devtab_entry *tab)
234
{
235
    serial_channel *chan = (serial_channel *)tab->priv;
236
    sleb_sdtr_info *sdtr_chan = (sleb_sdtr_info *)chan->dev_priv;
237
#ifdef CYGDBG_IO_INIT
238
    diag_printf("SLEB SERIAL init - dev: %x.%d.%d\n", sdtr_chan->base, sdtr_chan->tx_int_num, sdtr_chan->rx_int_num);
239
#endif
240
    (chan->callbacks->serial_init)(chan);  // Really only required for interrupt driven devices
241
    if (chan->out_cbuf.len != 0) {
242
        cyg_drv_interrupt_create(sdtr_chan->tx_int_num,
243
                                 99,                     // Priority - unused
244
                                 (cyg_addrword_t)chan,   //  Data item passed to interrupt handler
245
                                 sleb_sdtr_tx_ISR,
246
                                 sleb_sdtr_tx_DSR,
247
                                 &sdtr_chan->tx_serial_interrupt_handle,
248
                                 &sdtr_chan->tx_serial_interrupt);
249
        cyg_drv_interrupt_attach(sdtr_chan->tx_serial_interrupt_handle);
250
        cyg_drv_interrupt_mask(sdtr_chan->tx_int_num);
251
        cyg_drv_interrupt_create(sdtr_chan->rx_int_num,
252
                                 99,                     // Priority - unused
253
                                 (cyg_addrword_t)chan,   //  Data item passed to interrupt handler
254
                                 sleb_sdtr_rx_ISR,
255
                                 sleb_sdtr_rx_DSR,
256
                                 &sdtr_chan->rx_serial_interrupt_handle,
257
                                 &sdtr_chan->rx_serial_interrupt);
258
        cyg_drv_interrupt_attach(sdtr_chan->rx_serial_interrupt_handle);
259
        cyg_drv_interrupt_unmask(sdtr_chan->rx_int_num);
260
    }
261
    sleb_sdtr_config_port(chan, &chan->config, true);
262
    return true;
263
}
264
 
265
// This routine is called when the device is "looked" up (i.e. attached)
266
static Cyg_ErrNo
267
sleb_sdtr_lookup(struct cyg_devtab_entry **tab,
268
                  struct cyg_devtab_entry *sub_tab,
269
                  const char *name)
270
{
271
    serial_channel *chan = (serial_channel *)(*tab)->priv;
272
    (chan->callbacks->serial_init)(chan);  // Really only required for interrupt driven devices
273
    return ENOERR;
274
}
275
 
276
// Send a character to the device output buffer.
277
// Return 'true' if character is sent to device
278
static bool
279
sleb_sdtr_putc(serial_channel *chan, unsigned char c)
280
{
281
    sleb_sdtr_info *sdtr_chan = (sleb_sdtr_info *)chan->dev_priv;
282
    CYG_ADDRWORD port = sdtr_chan->base;
283
    cyg_uint8 status;
284
    HAL_SPARC_86940_READ(SDTR_STATUS(port), status);
285
    if (status & SDTR_STAT_TxRDY) {
286
// Transmit buffer is empty
287
        HAL_SPARC_86940_WRITE(SDTR_TXDATA(port), c);
288
        return true;
289
    } else {
290
// No space
291
        return false;
292
    }
293
}
294
 
295
// Fetch a character from the device input buffer, waiting if necessary
296
static unsigned char
297
sleb_sdtr_getc(serial_channel *chan)
298
{
299
    unsigned char c;
300
    sleb_sdtr_info *sdtr_chan = (sleb_sdtr_info *)chan->dev_priv;
301
    CYG_ADDRWORD port = sdtr_chan->base;
302
    cyg_uint8 status;
303
    HAL_SPARC_86940_READ(SDTR_STATUS(port), status);
304
    while ((status & SDTR_STAT_RxRDY) == 0)
305
        HAL_SPARC_86940_READ(SDTR_STATUS(port), status);  // Wait for char
306
    HAL_SPARC_86940_READ(SDTR_RXDATA(port), c);
307
    return c;
308
}
309
 
310
// Set up the device characteristics; baud rate, etc.
311
static Cyg_ErrNo
312
sleb_sdtr_set_config(serial_channel *chan, cyg_uint32 key,
313
                     const void *xbuf, cyg_uint32 *len)
314
{
315
    switch (key) {
316
    case CYG_IO_SET_CONFIG_SERIAL_INFO:
317
      {
318
        cyg_serial_info_t *config = (cyg_serial_info_t *)xbuf;
319
        if ( *len < sizeof(cyg_serial_info_t) ) {
320
            return -EINVAL;
321
        }
322
        *len = sizeof(cyg_serial_info_t);
323
        if ( true != sleb_sdtr_config_port(chan, config, false) )
324
            return -EINVAL;
325
      }
326
      break;
327
    default:
328
        return -EINVAL;
329
    }
330
    return ENOERR;
331
}
332
 
333
// Enable the transmitter on the device
334
static void
335
sleb_sdtr_start_xmit(serial_channel *chan)
336
{
337
    sleb_sdtr_info *sdtr_chan = (sleb_sdtr_info *)chan->dev_priv;
338
    sdtr_chan->xmit_enabled = true;
339
    cyg_drv_interrupt_unmask(sdtr_chan->tx_int_num);
340
}
341
 
342
// Disable the transmitter on the device
343
static void
344
sleb_sdtr_stop_xmit(serial_channel *chan)
345
{
346
    sleb_sdtr_info *sdtr_chan = (sleb_sdtr_info *)chan->dev_priv;
347
    cyg_drv_interrupt_mask(sdtr_chan->tx_int_num);
348
    sdtr_chan->xmit_enabled = false;
349
}
350
 
351
// Serial I/O - low level interrupt handler (ISR)
352
static cyg_uint32
353
sleb_sdtr_tx_ISR(cyg_vector_t vector, cyg_addrword_t data)
354
{
355
    serial_channel *chan = (serial_channel *)data;
356
    sleb_sdtr_info *sdtr_chan = (sleb_sdtr_info *)chan->dev_priv;
357
    cyg_drv_interrupt_mask(sdtr_chan->tx_int_num);
358
    cyg_drv_interrupt_acknowledge(sdtr_chan->tx_int_num);
359
    return CYG_ISR_CALL_DSR;  // Cause DSR to be run
360
}
361
 
362
// Serial I/O - high level interrupt handler (DSR)
363
static void
364
sleb_sdtr_tx_DSR(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data)
365
{
366
    serial_channel *chan = (serial_channel *)data;
367
    sleb_sdtr_info *sdtr_chan = (sleb_sdtr_info *)chan->dev_priv;
368
    (chan->callbacks->xmt_char)(chan);
369
    if (sdtr_chan->xmit_enabled)
370
        cyg_drv_interrupt_unmask(sdtr_chan->tx_int_num);
371
}
372
 
373
// Serial I/O - low level interrupt handler (ISR)
374
static cyg_uint32
375
sleb_sdtr_rx_ISR(cyg_vector_t vector, cyg_addrword_t data)
376
{
377
    serial_channel *chan = (serial_channel *)data;
378
    sleb_sdtr_info *sdtr_chan = (sleb_sdtr_info *)chan->dev_priv;
379
    cyg_drv_interrupt_mask(sdtr_chan->rx_int_num);
380
    return CYG_ISR_CALL_DSR;  // Cause DSR to be run
381
}
382
 
383
// Serial I/O - high level interrupt handler (DSR)
384
static void
385
sleb_sdtr_rx_DSR(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data)
386
{
387
    serial_channel *chan = (serial_channel *)data;
388
    sleb_sdtr_info *sdtr_chan = (sleb_sdtr_info *)chan->dev_priv;
389
    CYG_ADDRWORD port = sdtr_chan->base;
390
    cyg_uint8 status, c;
391
    HAL_SPARC_86940_READ(SDTR_STATUS(port), status);
392
    if ((status & SDTR_STAT_RxRDY) != 0) {
393
        HAL_SPARC_86940_READ(SDTR_RXDATA(port), c);
394
        (chan->callbacks->rcv_char)(chan, c);
395
    }
396
    cyg_drv_interrupt_acknowledge(sdtr_chan->rx_int_num);
397
    cyg_drv_interrupt_unmask(sdtr_chan->rx_int_num);
398
}
399
 
400
#endif //  CYGPKG_IO_SERIAL_SPARCLITE_SLEB

powered by: WebSVN 2.1.0

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