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/] [sh/] [scif/] [v2_0/] [src/] [sh_scif_serial.c] - Blame information for rev 174

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 27 unneback
//==========================================================================
2
//
3
//      io/serial/sh/scif/sh_scif_serial.c
4
//
5
//      SH Serial IRDA/SCIF I/O Interface Module (interrupt driven)
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):   jskov
44
// Contributors:gthomas, jskov
45
// Date:        2000-04-04
46
// Purpose:     SH Serial IRDA/SCIF I/O module (interrupt driven version)
47
// Description: 
48
//
49
//####DESCRIPTIONEND####
50
//==========================================================================
51
 
52
#include <pkgconf/io_serial.h>
53
#include <pkgconf/io.h>
54
 
55
// FIXME: This is necessary since the SCI driver may be overriding
56
// CYGDAT_IO_SERIAL_DEVICE_HEADER. Need a better way to include two
57
// different drivers.
58
#include <pkgconf/io_serial_sh_scif.h>
59
 
60
#include <cyg/io/io.h>
61
#include <cyg/hal/hal_intr.h>
62
#include <cyg/io/devtab.h>
63
#include <cyg/infra/diag.h>
64
#include <cyg/infra/cyg_ass.h>
65
#include <cyg/io/serial.h>
66
 
67
#include <cyg/hal/sh_regs.h>
68
#include <cyg/hal/hal_cache.h>
69
 
70
// Only compile driver if an inline file with driver details was selected.
71
#ifdef CYGDAT_IO_SERIAL_SH_SCIF_INL
72
 
73
#if defined(CYGPKG_HAL_SH_SH2)
74
// The SCIF controller register layout on the SH2
75
// The controller base is defined in the board specification file.
76
# define SCIF_SCSMR      0x00      // serial mode register
77
# define SCIF_SCBRR      0x02      // bit rate register     
78
# define SCIF_SCSCR      0x04      // serial control register
79
# define SCIF_SCFTDR     0x06      // transmit data register
80
# define SCIF_SC1SSR     0x08      // serial status register 1
81
# define SCIF_SCSSR      SCIF_SC1SSR
82
# define SCIF_SC2SSR     0x0a      // serial status register 2
83
# define SCIF_SCFRDR     0x0c      // receive data register   
84
# define SCIF_SCFCR      0x0e      // FIFO control            
85
# define SCIF_SCFDR      0x10      // FIFO data count register
86
# define SCIF_SCFER      0x12      // FIFO error register
87
# define SCIF_SCIMR      0x14      // IrDA mode register
88
#elif defined(CYGPKG_HAL_SH_SH3)
89
// The SCIF controller register layout on the SH3
90
// The controller base is defined in the board specification file.
91
# define SCIF_SCSMR      0x00      // serial mode register
92
# define SCIF_SCBRR      0x02      // bit rate register
93
# define SCIF_SCSCR      0x04      // serial control register
94
# define SCIF_SCFTDR     0x06      // transmit data register
95
# define SCIF_SCSSR      0x08      // serial status register
96
# define SCIF_SCFRDR     0x0a      // receive data register
97
# define SCIF_SCFCR      0x0c      // FIFO control
98
# define SCIF_SCFDR      0x0e      // FIFO data count register
99
#else
100
# error "Unsupported variant"
101
#endif
102
 
103
static short select_word_length[] = {
104
    -1,
105
    -1,
106
    CYGARC_REG_SCIF_SCSMR_CHR,               // 7 bits
107
 
108
};
109
 
110
static short select_stop_bits[] = {
111
    -1,
112
    0,                                  // 1 stop bit
113
    -1,
114
    CYGARC_REG_SCIF_SCSMR_STOP               // 2 stop bits
115
};
116
 
117
static short select_parity[] = {
118
    0,                                  // No parity
119
    CYGARC_REG_SCIF_SCSMR_PE,                // Even parity
120
    CYGARC_REG_SCIF_SCSMR_PE|CYGARC_REG_SCIF_SCSMR_OE, // Odd parity
121
    -1,
122
    -1
123
};
124
 
125
static unsigned short select_baud[] = {
126
    0,    // Unused
127
    CYGARC_SCBRR_CKSx(50)<<8 | CYGARC_SCBRR_N(50),
128
    CYGARC_SCBRR_CKSx(75)<<8 | CYGARC_SCBRR_N(75),
129
    CYGARC_SCBRR_CKSx(110)<<8 | CYGARC_SCBRR_N(110),
130
    CYGARC_SCBRR_CKSx(134)<<8 | CYGARC_SCBRR_N(134),
131
    CYGARC_SCBRR_CKSx(150)<<8 | CYGARC_SCBRR_N(150),
132
    CYGARC_SCBRR_CKSx(200)<<8 | CYGARC_SCBRR_N(200),
133
    CYGARC_SCBRR_CKSx(300)<<8 | CYGARC_SCBRR_N(300),
134
    CYGARC_SCBRR_CKSx(600)<<8 | CYGARC_SCBRR_N(600),
135
    CYGARC_SCBRR_CKSx(1200)<<8 | CYGARC_SCBRR_N(1200),
136
    CYGARC_SCBRR_CKSx(1800)<<8 | CYGARC_SCBRR_N(1800),
137
    CYGARC_SCBRR_CKSx(2400)<<8 | CYGARC_SCBRR_N(2400),
138
    CYGARC_SCBRR_CKSx(3600)<<8 | CYGARC_SCBRR_N(3600),
139
    CYGARC_SCBRR_CKSx(4800)<<8 | CYGARC_SCBRR_N(4800),
140
    CYGARC_SCBRR_CKSx(7200)<<8 | CYGARC_SCBRR_N(7200),
141
    CYGARC_SCBRR_CKSx(9600)<<8 | CYGARC_SCBRR_N(9600),
142
    CYGARC_SCBRR_CKSx(14400)<<8 | CYGARC_SCBRR_N(14400),
143
    CYGARC_SCBRR_CKSx(19200)<<8 | CYGARC_SCBRR_N(19200),
144
    CYGARC_SCBRR_CKSx(38400)<<8 | CYGARC_SCBRR_N(38400),
145
    CYGARC_SCBRR_CKSx(57600)<<8 | CYGARC_SCBRR_N(57600),
146
    CYGARC_SCBRR_CKSx(115200)<<8 | CYGARC_SCBRR_N(115200),
147
    CYGARC_SCBRR_CKSx(230400)<<8 | CYGARC_SCBRR_N(230400)
148
};
149
 
150
typedef struct sh_scif_info {
151
    CYG_WORD          er_int_num,       // Error interrupt number
152
#ifdef CYGINT_IO_SERIAL_SH_SCIF_BR_INTERRUPT
153
                      br_int_num,       // Break interrupt number
154
#endif
155
                      rx_int_num,       // Receive interrupt number
156
                      tx_int_num;       // Transmit interrupt number
157
 
158
    CYG_ADDRWORD      ctrl_base;        // Base address of SCI controller
159
 
160
    cyg_interrupt     serial_er_interrupt,
161
#ifdef CYGINT_IO_SERIAL_SH_SCIF_BR_INTERRUPT
162
                      serial_br_interrupt,
163
#endif
164
                      serial_rx_interrupt,
165
                      serial_tx_interrupt;
166
    cyg_handle_t      serial_er_interrupt_handle,
167
#ifdef CYGINT_IO_SERIAL_SH_SCIF_BR_INTERRUPT
168
                      serial_br_interrupt_handle,
169
#endif
170
                      serial_rx_interrupt_handle,
171
                      serial_tx_interrupt_handle;
172
 
173
    volatile bool     tx_enabled;       // expect tx _serial_ interrupts
174
#ifdef CYGINT_IO_SERIAL_SH_SCIF_IRDA
175
    bool              irda_mode;
176
#endif
177
#ifdef CYGINT_IO_SERIAL_SH_SCIF_ASYNC_RXTX
178
    bool              async_rxtx_mode;
179
#endif
180
 
181
#ifdef CYGINT_IO_SERIAL_SH_SCIF_DMA
182
    cyg_bool          dma_enable;       // Set if DMA mode
183
    cyg_uint32        dma_xmt_cr_flags; // CR flags for DMA mode
184
    CYG_WORD          dma_xmt_int_num;  // DMA xmt completion interrupt
185
    CYG_ADDRWORD      dma_xmt_base;     // Base address of DMA channel
186
    int               dma_xmt_len;      // length transferred by DMA
187
    cyg_interrupt     dma_xmt_interrupt;
188
    cyg_handle_t      dma_xmt_interrupt_handle;
189
    volatile cyg_bool dma_xmt_running;  // expect tx _dma_ interrupts
190
#endif
191
} sh_scif_info;
192
 
193
static bool sh_scif_init(struct cyg_devtab_entry *tab);
194
static bool sh_scif_putc(serial_channel *chan, unsigned char c);
195
static Cyg_ErrNo sh_scif_lookup(struct cyg_devtab_entry **tab,
196
                                   struct cyg_devtab_entry *sub_tab,
197
                                   const char *name);
198
static unsigned char sh_scif_getc(serial_channel *chan);
199
static Cyg_ErrNo sh_scif_set_config(serial_channel *chan, cyg_uint32 key,
200
                                     const void *xbuf, cyg_uint32 *len);
201
static void sh_scif_start_xmit(serial_channel *chan);
202
static void sh_scif_stop_xmit(serial_channel *chan);
203
 
204
static cyg_uint32 sh_scif_tx_ISR(cyg_vector_t vector, cyg_addrword_t data);
205
static void       sh_scif_tx_DSR(cyg_vector_t vector, cyg_ucount32 count,
206
                                   cyg_addrword_t data);
207
static cyg_uint32 sh_scif_rx_ISR(cyg_vector_t vector, cyg_addrword_t data);
208
static void       sh_scif_rx_DSR(cyg_vector_t vector, cyg_ucount32 count,
209
                                   cyg_addrword_t data);
210
static cyg_uint32 sh_scif_er_ISR(cyg_vector_t vector, cyg_addrword_t data);
211
static void       sh_scif_er_DSR(cyg_vector_t vector, cyg_ucount32 count,
212
                                   cyg_addrword_t data);
213
 
214
#ifdef CYGINT_IO_SERIAL_SH_SCIF_DMA
215
static cyg_uint32 sh_dma_xmt_ISR(cyg_vector_t vector, cyg_addrword_t data);
216
static void       sh_dma_xmt_DSR(cyg_vector_t vector, cyg_ucount32 count,
217
                                 cyg_addrword_t data);
218
#endif
219
 
220
static SERIAL_FUNS(sh_scif_funs,
221
                   sh_scif_putc,
222
                   sh_scif_getc,
223
                   sh_scif_set_config,
224
                   sh_scif_start_xmit,
225
                   sh_scif_stop_xmit
226
    );
227
 
228
// Get the board specification
229
#include CYGDAT_IO_SERIAL_SH_SCIF_INL
230
 
231
// Allow platform to define handling of additional config keys
232
#ifndef CYGPRI_DEVS_SH_SCIF_SET_CONFIG_PLF
233
# define CYGPRI_DEVS_SH_SCIF_SET_CONFIG_PLF
234
#endif
235
 
236
// Internal function to actually configure the hardware to desired baud rate,
237
// etc.
238
static bool
239
sh_scif_config_port(serial_channel *chan, cyg_serial_info_t *new_config,
240
                     bool init)
241
{
242
    cyg_uint16 baud_divisor = select_baud[new_config->baud];
243
    sh_scif_info *sh_chan = (sh_scif_info *)chan->dev_priv;
244
    cyg_uint8 _scr, _smr;
245
    cyg_uint16 _sr;
246
    CYG_ADDRWORD base = sh_chan->ctrl_base;
247
 
248
    // Check configuration request
249
    if ((-1 == select_word_length[(new_config->word_length -
250
                                  CYGNUM_SERIAL_WORD_LENGTH_5)])
251
        || -1 == select_stop_bits[new_config->stop]
252
        || -1 == select_parity[new_config->parity]
253
        || baud_divisor == 0)
254
        return false;
255
 
256
    // Disable SCI interrupts while changing hardware
257
    HAL_READ_UINT8(base+SCIF_SCSCR, _scr);
258
    HAL_WRITE_UINT8(base+SCIF_SCSCR, 0);
259
 
260
    // Reset FIFO.
261
    HAL_WRITE_UINT8(base+SCIF_SCFCR,
262
                    CYGARC_REG_SCIF_SCFCR_TFRST|CYGARC_REG_SCIF_SCFCR_RFRST);
263
 
264
#ifdef CYGINT_IO_SERIAL_SH_SCIF_ASYNC_RXTX
265
    sh_chan->async_rxtx_mode = false;
266
#endif
267
#ifdef CYGINT_IO_SERIAL_SH_SCIF_IRDA
268
    if (sh_chan->irda_mode) {
269
        // In IrDA mode, the configuration is hardwired and the mode
270
        // bits should not be set
271
#ifdef CYGARC_REG_SCIF_SCSMR_IRMOD
272
        _smr = CYGARC_REG_SCIF_SCSMR_IRMOD;
273
#elif defined(SCIF_SCIMR)
274
        _smr = 0;
275
        HAL_WRITE_UINT8(base+SCIF_SCIMR, CYGARC_REG_SCIF_SCIMR_IRMOD);
276
#endif
277
    } else
278
#endif
279
    {
280
        // Set databits, stopbits and parity.
281
        _smr = select_word_length[(new_config->word_length -
282
                                   CYGNUM_SERIAL_WORD_LENGTH_5)] |
283
            select_stop_bits[new_config->stop] |
284
            select_parity[new_config->parity];
285
#ifdef CYGINT_IO_SERIAL_SH_SCIF_IRDA
286
#ifdef SCIF_SCIMR
287
        // Disable IrDA mode
288
        HAL_WRITE_UINT8(base+SCIF_SCIMR, 0);
289
#endif
290
#endif
291
    }
292
    HAL_WRITE_UINT8(base+SCIF_SCSMR, _smr);
293
 
294
    // Set baud rate.
295
    _smr &= ~CYGARC_REG_SCIF_SCSMR_CKSx_MASK;
296
    _smr |= baud_divisor >> 8;
297
    HAL_WRITE_UINT8(base+SCIF_SCSMR, _smr);
298
    HAL_WRITE_UINT8(base+SCIF_SCBRR, baud_divisor & 0xff);
299
 
300
    // FIXME: Should delay 1/<baud> second here.
301
 
302
    // Clear the status register (read first).
303
    HAL_READ_UINT16(base+SCIF_SCSSR, _sr);
304
    HAL_WRITE_UINT16(base+SCIF_SCSSR, 0);
305
 
306
    // Bring FIFO out of reset and set FIFO trigger marks
307
    //
308
    // Note that the RX FIFO size must be smaller when flow control is
309
    // enabled. This due to observations made by running the flow2
310
    // serial test. The automatic RTS de-assertion happens
311
    // (apparently) when the FIFO fills past the trigger count -
312
    // causing the sender to stop transmission. But there's a lag
313
    // before transmission is stopped, and if the FIFO fills in that
314
    // time, data will be lost. Thus, seeing as HW flow control is
315
    // presumed used for prevention of data loss, set the trigger
316
    // level so the sender has time to stop transmission before the
317
    // FIFO fills up.
318
    //
319
    // The trigger setting of 8 allows test flow2 to complete without
320
    // problems. It tests duplex data transmission at 115200
321
    // baud. Depending on the lag time between the de-assertion of RTS
322
    // and actual transmission stop, it may be necessary to reduce the
323
    // trigger level further.
324
#ifdef CYGOPT_IO_SERIAL_FLOW_CONTROL_HW
325
    HAL_WRITE_UINT8(base+SCIF_SCFCR,
326
                    CYGARC_REG_SCIF_SCFCR_RTRG_8|CYGARC_REG_SCIF_SCFCR_TTRG_8);
327
#else
328
    HAL_WRITE_UINT8(base+SCIF_SCFCR,
329
                    CYGARC_REG_SCIF_SCFCR_RTRG_14|CYGARC_REG_SCIF_SCFCR_TTRG_8);
330
#endif
331
 
332
    if (init) {
333
        // Always enable received and (for normal mode) transmitter
334
        _scr = CYGARC_REG_SCIF_SCSCR_TE | CYGARC_REG_SCIF_SCSCR_RE;
335
#ifdef CYGINT_IO_SERIAL_SH_SCIF_ASYNC_RXTX
336
        if (sh_chan->async_rxtx_mode)
337
            _scr = CYGARC_REG_SCIF_SCSCR_RE;
338
#endif
339
#ifdef CYGINT_IO_SERIAL_SH_SCIF_IRDA
340
        if (sh_chan->irda_mode)
341
            _scr = CYGARC_REG_SCIF_SCSCR_RE;
342
#endif
343
 
344
        if (chan->in_cbuf.len != 0)
345
            _scr |= CYGARC_REG_SCIF_SCSCR_RIE; // enable rx interrupts
346
    }
347
 
348
    HAL_WRITE_UINT8(base+SCIF_SCSCR, _scr);
349
 
350
    if (new_config != &chan->config) {
351
        chan->config = *new_config;
352
    }
353
    return true;
354
}
355
 
356
// Function to initialize the device.  Called at bootstrap time.
357
static bool
358
sh_scif_init(struct cyg_devtab_entry *tab)
359
{
360
    serial_channel *chan = (serial_channel *)tab->priv;
361
    sh_scif_info *sh_chan = (sh_scif_info *)chan->dev_priv;
362
#ifdef CYGDBG_IO_INIT
363
    diag_printf("SH SERIAL init - dev: %x.%d\n",
364
                sh_chan->ctrl_base, sh_chan->rx_int_num);
365
#endif
366
    // Really only required for interrupt driven devices
367
    (chan->callbacks->serial_init)(chan);
368
 
369
    if (chan->out_cbuf.len != 0) {
370
        cyg_drv_interrupt_create(sh_chan->tx_int_num,
371
                                 3,
372
                                 (cyg_addrword_t)chan, // Data item passed to interrupt handler
373
                                 sh_scif_tx_ISR,
374
                                 sh_scif_tx_DSR,
375
                                 &sh_chan->serial_tx_interrupt_handle,
376
                                 &sh_chan->serial_tx_interrupt);
377
        cyg_drv_interrupt_attach(sh_chan->serial_tx_interrupt_handle);
378
        cyg_drv_interrupt_unmask(sh_chan->tx_int_num);
379
        sh_chan->tx_enabled = false;
380
    }
381
    if (chan->in_cbuf.len != 0) {
382
        // Receive interrupt
383
        cyg_drv_interrupt_create(sh_chan->rx_int_num,
384
                                 3,
385
                                 (cyg_addrword_t)chan, // Data item passed to interrupt handler
386
                                 sh_scif_rx_ISR,
387
                                 sh_scif_rx_DSR,
388
                                 &sh_chan->serial_rx_interrupt_handle,
389
                                 &sh_chan->serial_rx_interrupt);
390
        cyg_drv_interrupt_attach(sh_chan->serial_rx_interrupt_handle);
391
        // Receive error interrupt
392
        cyg_drv_interrupt_create(sh_chan->er_int_num,
393
                                 3,
394
                                 (cyg_addrword_t)chan, // Data item passed to interrupt handler
395
                                 sh_scif_er_ISR,
396
                                 sh_scif_er_DSR,
397
                                 &sh_chan->serial_er_interrupt_handle,
398
                                 &sh_chan->serial_er_interrupt);
399
        cyg_drv_interrupt_attach(sh_chan->serial_er_interrupt_handle);
400
#ifdef CYGINT_IO_SERIAL_SH_SCIF_BR_INTERRUPT
401
        // Break error interrupt
402
        cyg_drv_interrupt_create(sh_chan->br_int_num,
403
                                 3,
404
                                 (cyg_addrword_t)chan, // Data item passed to interrupt handler
405
                                 sh_scif_er_ISR,
406
                                 sh_scif_er_DSR,
407
                                 &sh_chan->serial_br_interrupt_handle,
408
                                 &sh_chan->serial_br_interrupt);
409
        cyg_drv_interrupt_attach(sh_chan->serial_br_interrupt_handle);
410
#endif
411
        // This unmasks all interrupt sources.
412
        cyg_drv_interrupt_unmask(sh_chan->rx_int_num);
413
    }
414
 
415
#ifdef CYGINT_IO_SERIAL_SH_SCIF_DMA
416
    // Assign DMA channel and interrupt if requested
417
    if (sh_chan->dma_enable) {
418
        // FIXME: Need a cleaner way to assign DMA channels
419
        static int dma_channel = 0;
420
#if defined(CYGPKG_HAL_SH_SH2)
421
        sh_chan->dma_xmt_int_num = dma_channel+CYGNUM_HAL_INTERRUPT_DMAC0_TE;
422
#elif defined(CYGPKG_HAL_SH_SH3)
423
        sh_chan->dma_xmt_int_num = dma_channel+CYGNUM_HAL_INTERRUPT_DMAC_DEI0;
424
#else
425
# error "No interrupt defined for variant"
426
#endif
427
        sh_chan->dma_xmt_base = (dma_channel*0x10)+CYGARC_REG_SAR0;
428
        dma_channel++;
429
 
430
        // Enable the DMA engines.
431
        HAL_WRITE_UINT16(CYGARC_REG_DMAOR, CYGARC_REG_DMAOR_DME);
432
 
433
        cyg_drv_interrupt_create(sh_chan->dma_xmt_int_num,
434
                                 3,
435
                                 (cyg_addrword_t)chan, // Data item passed to interrupt handler
436
                                 sh_dma_xmt_ISR,
437
                                 sh_dma_xmt_DSR,
438
                                 &sh_chan->dma_xmt_interrupt_handle,
439
                                 &sh_chan->dma_xmt_interrupt);
440
        cyg_drv_interrupt_attach(sh_chan->dma_xmt_interrupt_handle);
441
        cyg_drv_interrupt_unmask(sh_chan->dma_xmt_int_num);
442
    }
443
    sh_chan->dma_xmt_running = false;
444
#endif // CYGINT_IO_SERIAL_SH_SCIF_DMA
445
 
446
    sh_scif_config_port(chan, &chan->config, true);
447
    return true;
448
}
449
 
450
// This routine is called when the device is "looked" up (i.e. attached)
451
static Cyg_ErrNo
452
sh_scif_lookup(struct cyg_devtab_entry **tab,
453
                  struct cyg_devtab_entry *sub_tab,
454
                  const char *name)
455
{
456
    serial_channel *chan = (serial_channel *)(*tab)->priv;
457
 
458
    // Really only required for interrupt driven devices
459
    (chan->callbacks->serial_init)(chan);
460
    return ENOERR;
461
}
462
 
463
// Send a character to the device output buffer.
464
// Return 'true' if character is sent to device
465
static bool
466
sh_scif_putc(serial_channel *chan, unsigned char c)
467
{
468
    cyg_uint16 _fdr, _sr;
469
    sh_scif_info *sh_chan = (sh_scif_info *)chan->dev_priv;
470
 
471
    HAL_READ_UINT16(sh_chan->ctrl_base+SCIF_SCFDR, _fdr);
472
    if (((_fdr & CYGARC_REG_SCIF_SCFDR_TCOUNT_MASK) >> CYGARC_REG_SCIF_SCFDR_TCOUNT_shift) < 15) {
473
// Transmit FIFO has room for another char
474
        HAL_WRITE_UINT8(sh_chan->ctrl_base+SCIF_SCFTDR, c);
475
        // Clear FIFO-empty/transmit end flags (read back sr first)
476
        HAL_READ_UINT16(sh_chan->ctrl_base+SCIF_SCSSR, _sr);
477
        HAL_WRITE_UINT16(sh_chan->ctrl_base+SCIF_SCSSR,
478
                        CYGARC_REG_SCIF_SCSSR_CLEARMASK & ~CYGARC_REG_SCIF_SCSSR_TDFE);
479
        return true;
480
    } else {
481
// No space
482
        return false;
483
    }
484
}
485
 
486
// Fetch a character from the device input buffer, waiting if necessary
487
// Note: Input is running wo FIFO enabled, so the counter is not checked here.
488
static unsigned char
489
sh_scif_getc(serial_channel *chan)
490
{
491
    sh_scif_info *sh_chan = (sh_scif_info *)chan->dev_priv;
492
    unsigned char c;
493
    cyg_uint16 _sr;
494
 
495
    do {
496
        HAL_READ_UINT16(sh_chan->ctrl_base+SCIF_SCSSR, _sr);
497
    } while ((_sr & CYGARC_REG_SCIF_SCSSR_RDF) == 0);
498
 
499
    HAL_READ_UINT8(sh_chan->ctrl_base+SCIF_SCFRDR, c);
500
 
501
    // Clear buffer full flag (read back first)
502
    HAL_READ_UINT16(sh_chan->ctrl_base+SCIF_SCSSR, _sr);
503
    HAL_WRITE_UINT16(sh_chan->ctrl_base+SCIF_SCSSR,
504
                     CYGARC_REG_SCIF_SCSSR_CLEARMASK & ~CYGARC_REG_SCIF_SCSSR_RDF);
505
 
506
    return c;
507
}
508
 
509
// Set up the device characteristics; baud rate, etc.
510
static Cyg_ErrNo
511
sh_scif_set_config(serial_channel *chan, cyg_uint32 key,
512
                    const void *xbuf, cyg_uint32 *len)
513
{
514
    switch (key) {
515
    case CYG_IO_SET_CONFIG_SERIAL_INFO:
516
      {
517
        cyg_serial_info_t *config = (cyg_serial_info_t *)xbuf;
518
        if ( *len < sizeof(cyg_serial_info_t) ) {
519
            return -EINVAL;
520
        }
521
        *len = sizeof(cyg_serial_info_t);
522
        if ( true != sh_scif_config_port(chan, config, false) )
523
            return -EINVAL;
524
      }
525
      break;
526
#ifdef CYGOPT_IO_SERIAL_FLOW_CONTROL_HW
527
    case CYG_IO_SET_CONFIG_SERIAL_HW_RX_FLOW_THROTTLE:
528
      {
529
          sh_scif_info *ser_chan = (sh_scif_info *)chan->dev_priv;
530
          cyg_addrword_t base = ser_chan->ctrl_base;
531
          cyg_uint8 *f = (cyg_uint8 *)xbuf;
532
          if ( *len < *f )
533
              return -EINVAL;
534
 
535
          if ( chan->config.flags & CYGNUM_SERIAL_FLOW_RTSCTS_RX ) {
536
              // Control RX RTC/CTS flow control by disabling/enabling
537
              // RX interrupt.  When disabled, FIFO will fill up and
538
              // clear RTS.
539
              cyg_uint8 _scscr;
540
              HAL_READ_UINT8(base+SCIF_SCSCR, _scscr);
541
              if (*f) // we should throttle
542
                  _scscr &= ~CYGARC_REG_SCIF_SCSCR_RIE;
543
              else // we should no longer throttle
544
                  _scscr |= CYGARC_REG_SCIF_SCSCR_RIE;
545
              HAL_WRITE_UINT8(base+SCIF_SCSCR, _scscr);
546
          }
547
#ifdef CYGHWR_SH_SCIF_FLOW_DSRDTR
548
          if ( chan->config.flags & CYGNUM_SERIAL_FLOW_DSRDTR_RX ) {
549
              // Control RX DSR/DTR flow control via platform specific macro
550
              CYGHWR_SH_SCIF_FLOW_DSRDTR_RX(chan, *f);
551
          }
552
#endif
553
      }
554
      break;
555
    case CYG_IO_SET_CONFIG_SERIAL_HW_FLOW_CONFIG:
556
      {
557
          // Handle CTS/RTS flag
558
          if ( chan->config.flags &
559
               (CYGNUM_SERIAL_FLOW_RTSCTS_RX | CYGNUM_SERIAL_FLOW_RTSCTS_TX )){
560
              cyg_uint8 _scfcr;
561
              sh_scif_info *ser_chan = (sh_scif_info *)chan->dev_priv;
562
              cyg_addrword_t base = ser_chan->ctrl_base;
563
              cyg_uint8 *f = (cyg_uint8 *)xbuf;
564
 
565
              HAL_READ_UINT8(base+SCIF_SCFCR, _scfcr);
566
              if (*f) // enable RTS/CTS flow control
567
                  _scfcr |= CYGARC_REG_SCIF_SCFCR_MCE;
568
              else // disable RTS/CTS flow control
569
                  _scfcr &= ~CYGARC_REG_SCIF_SCFCR_MCE;
570
              HAL_WRITE_UINT8(base+SCIF_SCFCR, _scfcr);
571
          }
572
#ifndef CYGHWR_SH_SCIF_FLOW_DSRDTR
573
          // Clear DSR/DTR flag as it's not supported.
574
          if (chan->config.flags &
575
              (CYGNUM_SERIAL_FLOW_DSRDTR_RX|CYGNUM_SERIAL_FLOW_DSRDTR_TX)) {
576
              chan->config.flags &= ~(CYGNUM_SERIAL_FLOW_DSRDTR_RX|
577
                                      CYGNUM_SERIAL_FLOW_DSRDTR_TX);
578
              return -EINVAL;
579
          }
580
#else
581
          return CYGHWR_SH_SCIF_FLOW_DSRDTR_CONFIG(chan);
582
#endif
583
      }
584
      break;
585
#endif
586
 
587
    CYGPRI_DEVS_SH_SCIF_SET_CONFIG_PLF
588
 
589
    default:
590
        return -EINVAL;
591
    }
592
    return ENOERR;
593
}
594
 
595
 
596
#ifdef CYGINT_IO_SERIAL_SH_SCIF_DMA
597
 
598
// Must be called with serial interrupts disabled
599
static xmt_req_reply_t
600
sh_scif_start_dma_xmt(serial_channel *chan)
601
{
602
    int chars_avail;
603
    unsigned char* chars;
604
    xmt_req_reply_t res;
605
 
606
    // We can transfer the full buffer - ask how much to transfer
607
    res = (chan->callbacks->data_xmt_req)(chan, chan->out_cbuf.len,
608
                                          &chars_avail, &chars);
609
    if (CYG_XMT_OK == res) {
610
        sh_scif_info *sh_chan = (sh_scif_info *)chan->dev_priv;
611
        cyg_uint32 dma_base = sh_chan->dma_xmt_base;
612
        cyg_uint32 scr;
613
 
614
        // Save the length so it can be used in the DMA DSR
615
        sh_chan->dma_xmt_len = chars_avail;
616
 
617
        // Flush cache for the area
618
        HAL_DCACHE_FLUSH((cyg_haladdress)chars, chars_avail);
619
 
620
        // Program DMA
621
        HAL_WRITE_UINT32(dma_base+CYGARC_REG_CHCR, 0); // disable and clear
622
        HAL_WRITE_UINT32(dma_base+CYGARC_REG_SAR, (cyg_uint32)chars);
623
        HAL_WRITE_UINT32(dma_base+CYGARC_REG_DAR,
624
                         (sh_chan->ctrl_base+SCIF_SCFTDR) & 0x0fffffff);
625
        HAL_WRITE_UINT32(dma_base+CYGARC_REG_DMATCR, chars_avail);
626
        // Source increments, dest static, byte transfer, enable
627
        // interrupt on completion.
628
        HAL_WRITE_UINT32(dma_base+CYGARC_REG_CHCR,
629
                         sh_chan->dma_xmt_cr_flags | CYGARC_REG_CHCR_SM0 \
630
                         | CYGARC_REG_CHCR_IE | CYGARC_REG_CHCR_DE);
631
 
632
        // Enable serial interrupts
633
        HAL_READ_UINT8(sh_chan->ctrl_base+SCIF_SCSCR, scr);
634
        scr |= CYGARC_REG_SCIF_SCSCR_TIE;
635
        HAL_WRITE_UINT8(sh_chan->ctrl_base+SCIF_SCSCR, scr);
636
    }
637
 
638
    return res;
639
}
640
 
641
// must be called with serial interrupts masked
642
static void
643
sh_scif_stop_dma_xmt(serial_channel *chan)
644
{
645
    sh_scif_info *sh_chan = (sh_scif_info *)chan->dev_priv;
646
    cyg_uint32 dma_base = sh_chan->dma_xmt_base;
647
    cyg_uint32 cr;
648
 
649
    // Disable DMA engine and interrupt enable flag.  Should be safe
650
    // to do since it's triggered by the serial interrupt which has
651
    // already been disabled.
652
    HAL_READ_UINT32(dma_base+CYGARC_REG_CHCR, cr);
653
    cr &= ~(CYGARC_REG_CHCR_IE | CYGARC_REG_CHCR_DE);
654
    HAL_WRITE_UINT32(dma_base+CYGARC_REG_CHCR, cr);
655
 
656
    // Did transfer complete?
657
    HAL_READ_UINT32(dma_base+CYGARC_REG_CHCR, cr);
658
    if (0 == (cr & CYGARC_REG_CHCR_TE)) {
659
        // Transfer incomplete. Report actually transferred amount of data
660
        // back to the serial driver.
661
        int chars_left;
662
        HAL_READ_UINT32(dma_base+CYGARC_REG_DMATCR, chars_left);
663
        CYG_ASSERT(chars_left > 0, "DMA incomplete, but no data left");
664
        CYG_ASSERT(chars_left <= sh_chan->dma_xmt_len,
665
                   "More data remaining than was attempted transferred");
666
 
667
        (chan->callbacks->data_xmt_done)(chan,
668
                                         sh_chan->dma_xmt_len - chars_left);
669
    }
670
 
671
#ifdef CYGDBG_USE_ASSERTS
672
    {
673
        cyg_uint32 dmaor;
674
        HAL_READ_UINT32(CYGARC_REG_DMAOR, dmaor);
675
        CYG_ASSERT(0== (dmaor & (CYGARC_REG_DMAOR_AE | CYGARC_REG_DMAOR_NMIF)),
676
                   "DMA error");
677
    }
678
#endif
679
 
680
    // The DMA engine is free again.
681
    sh_chan->dma_xmt_running = false;
682
}
683
 
684
// Serial xmt DMA completion interrupt handler (ISR)
685
static cyg_uint32
686
sh_dma_xmt_ISR(cyg_vector_t vector, cyg_addrword_t data)
687
{
688
    serial_channel *chan = (serial_channel *)data;
689
    sh_scif_info *sh_chan = (sh_scif_info *)chan->dev_priv;
690
    cyg_uint32 _cr;
691
 
692
    // mask serial interrupt
693
    HAL_READ_UINT8(sh_chan->ctrl_base+SCIF_SCSCR, _cr);
694
    _cr &= ~CYGARC_REG_SCIF_SCSCR_TIE;      // Disable xmit interrupt
695
    HAL_WRITE_UINT8(sh_chan->ctrl_base+SCIF_SCSCR, _cr);
696
 
697
    // mask DMA interrupt and disable engine
698
    HAL_READ_UINT32(sh_chan->dma_xmt_base+CYGARC_REG_CHCR, _cr);
699
    _cr &= ~(CYGARC_REG_CHCR_IE | CYGARC_REG_CHCR_DE);
700
    HAL_WRITE_UINT32(sh_chan->dma_xmt_base+CYGARC_REG_CHCR, _cr);
701
 
702
    return CYG_ISR_CALL_DSR;  // Cause DSR to be run
703
}
704
 
705
// Serial xmt DMA completion interrupt handler (DSR)
706
static void
707
sh_dma_xmt_DSR(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data)
708
{
709
    serial_channel *chan = (serial_channel *)data;
710
    sh_scif_info *sh_chan = (sh_scif_info *)chan->dev_priv;
711
 
712
    (chan->callbacks->data_xmt_done)(chan, sh_chan->dma_xmt_len);
713
 
714
    // Try to load the engine again.
715
    sh_chan->dma_xmt_running =
716
        (CYG_XMT_OK == sh_scif_start_dma_xmt(chan)) ? true : false;
717
}
718
#endif // CYGINT_IO_SERIAL_SH_SCIF_DMA
719
 
720
 
721
// Enable the transmitter on the device
722
static void
723
sh_scif_start_xmit(serial_channel *chan)
724
{
725
    cyg_uint8 _scr;
726
    sh_scif_info *sh_chan = (sh_scif_info *)chan->dev_priv;
727
    xmt_req_reply_t _block_status = CYG_XMT_DISABLED;
728
 
729
    if (sh_chan->tx_enabled)
730
        return;
731
 
732
#ifdef CYGINT_IO_SERIAL_SH_SCIF_DMA
733
    // Check if the engine is already running. If so, return. Note
734
    // that there will never be a race on this flag - the caller of
735
    // this function is respecting a per-channel lock.
736
    if (sh_chan->dma_xmt_running)
737
        return;
738
    // If the channel uses DMA, try to start a DMA job for this -
739
    // but handle the case where the job doesn't start by falling
740
    // back to the FIFO/interrupt based code.
741
    if (sh_chan->dma_enable) {
742
        _block_status = sh_scif_start_dma_xmt(chan);
743
        CYG_ASSERT(_block_status != CYG_XMT_EMPTY,
744
                   "start_xmit called with empty buffers!");
745
        sh_chan->dma_xmt_running =
746
            (CYG_XMT_OK == _block_status) ? true : false;
747
    }
748
#endif // CYGINT_IO_SERIAL_SH_SCIF_DMA
749
 
750
    if (CYG_XMT_DISABLED == _block_status) {
751
        // Mask interrupts while changing the CR since a rx
752
        // interrupt or another thread doing the same in the
753
        // middle of this would result in a bad CR state.
754
        cyg_drv_isr_lock();
755
        {
756
            HAL_READ_UINT8(sh_chan->ctrl_base+SCIF_SCSCR, _scr);
757
            _scr |= CYGARC_REG_SCIF_SCSCR_TIE;       // Enable xmit interrupt
758
#ifdef CYGINT_IO_SERIAL_SH_SCIF_IRDA
759
            if (sh_chan->irda_mode) {
760
                // Enable transmitter - this automatically disables
761
                // the receiver in the hardware.  Doing it explicitly
762
                // (like for async RX/TX below) causes more spurious
763
                // characters to be read when re-enabling the
764
                // receiver.
765
                _scr |= CYGARC_REG_SCIF_SCSCR_TE;
766
            }
767
#endif
768
#ifdef CYGINT_IO_SERIAL_SH_SCIF_ASYNC_RXTX
769
            if (sh_chan->async_rxtx_mode) {
770
                // Enable transmitter
771
                _scr |= CYGARC_REG_SCIF_SCSCR_TE;
772
                // Disable receiver
773
                _scr &= ~CYGARC_REG_SCIF_SCSCR_RE;
774
            }
775
#endif
776
            HAL_WRITE_UINT8(sh_chan->ctrl_base+SCIF_SCSCR, _scr);
777
            sh_chan->tx_enabled = true;
778
        }
779
        cyg_drv_isr_unlock();
780
    }
781
}
782
 
783
// Disable the transmitter on the device
784
static void
785
sh_scif_stop_xmit(serial_channel *chan)
786
{
787
    cyg_uint8 _scr;
788
    sh_scif_info *sh_chan = (sh_scif_info *)chan->dev_priv;
789
 
790
    // In IrDA and async mode the transmitter needs to be disabled, so
791
    // wait for transmission to complete within reason: disable it
792
    // after 0.1s
793
    if (0
794
#ifdef CYGINT_IO_SERIAL_SH_SCIF_IRDA
795
        || sh_chan->irda_mode
796
#endif
797
#if defined(CYGINT_IO_SERIAL_SH_SCIF_ASYNC_RXTX)
798
        || sh_chan->async_rxtx_mode
799
#endif
800
        ) {
801
        cyg_uint16 sr;
802
        int i = 1000;
803
        do {
804
            HAL_READ_UINT16(sh_chan->ctrl_base+SCIF_SCSSR, sr);
805
            if (sr & CYGARC_REG_SCIF_SCSSR_TEND) break;
806
            HAL_DELAY_US(100);
807
        } while (i-- > 0);
808
    }
809
 
810
    // Mask interrupts while changing the CR since a rx interrupt or
811
    // another thread doing the same in the middle of this would
812
    // result in a bad CR state.
813
    cyg_drv_isr_lock();
814
    {
815
            HAL_READ_UINT8(sh_chan->ctrl_base+SCIF_SCSCR, _scr);
816
            _scr &= ~CYGARC_REG_SCIF_SCSCR_TIE;      // Disable xmit interrupt
817
#ifdef CYGINT_IO_SERIAL_SH_SCIF_IRDA
818
            if (sh_chan->irda_mode) {
819
#ifdef CYGHWR_IO_SERIAL_SH_SCIF_IRDA_TXRX_COMPENSATION
820
                // In IrDA mode there will be generated spurious RX
821
                // events when the TX unit is switched on. Eat that
822
                // character.
823
                cyg_uint8 _junk;
824
                cyg_uint16 _sr;
825
                HAL_READ_UINT8(sh_chan->ctrl_base+SCIF_SCFRDR, _junk);
826
 
827
                // Clear buffer full flag (read back first)
828
                HAL_READ_UINT16(sh_chan->ctrl_base+SCIF_SCSSR, _sr);
829
                HAL_WRITE_UINT16(sh_chan->ctrl_base+SCIF_SCSSR,
830
                                 CYGARC_REG_SCIF_SCSSR_CLEARMASK & ~(CYGARC_REG_SCIF_SCSSR_RDF|CYGARC_REG_SCIF_SCSSR_DR));
831
#endif
832
                // Disable transmitter
833
                _scr &= ~CYGARC_REG_SCIF_SCSCR_TE;
834
            }
835
#endif
836
#ifdef CYGINT_IO_SERIAL_SH_SCIF_ASYNC_RXTX
837
            if (sh_chan->async_rxtx_mode) {
838
                // Enable receiver again
839
                _scr |= CYGARC_REG_SCIF_SCSCR_RE;
840
                // Disable transmitter
841
                _scr &= ~CYGARC_REG_SCIF_SCSCR_TE;
842
            }
843
#endif
844
            HAL_WRITE_UINT8(sh_chan->ctrl_base+SCIF_SCSCR, _scr);
845
    }
846
    cyg_drv_isr_unlock();
847
 
848
#ifdef CYGINT_IO_SERIAL_SH_SCIF_DMA
849
    // If the channel uses DMA, stop the DMA engine.
850
    if (sh_chan->dma_xmt_running)
851
        sh_scif_stop_dma_xmt(chan);
852
    else // dangling else!
853
#endif // CYGINT_IO_SERIAL_SH_SCIF_DMA
854
        sh_chan->tx_enabled = false;
855
}
856
 
857
// Serial I/O - low level tx interrupt handler (ISR)
858
static cyg_uint32
859
sh_scif_tx_ISR(cyg_vector_t vector, cyg_addrword_t data)
860
{
861
    serial_channel *chan = (serial_channel *)data;
862
    sh_scif_info *sh_chan = (sh_scif_info *)chan->dev_priv;
863
    cyg_uint8 _scr;
864
 
865
    HAL_READ_UINT8(sh_chan->ctrl_base+SCIF_SCSCR, _scr);
866
    _scr &= ~CYGARC_REG_SCIF_SCSCR_TIE;      // mask out tx interrupts
867
    HAL_WRITE_UINT8(sh_chan->ctrl_base+SCIF_SCSCR, _scr);
868
 
869
    return CYG_ISR_CALL_DSR;  // Cause DSR to be run
870
}
871
 
872
// Serial I/O - high level tx interrupt handler (DSR)
873
static void
874
sh_scif_tx_DSR(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data)
875
{
876
    serial_channel *chan = (serial_channel *)data;
877
    sh_scif_info *sh_chan = (sh_scif_info *)chan->dev_priv;
878
    xmt_req_reply_t _block_status = CYG_XMT_DISABLED;
879
    cyg_uint16 _fdr, _sr;
880
    int _space, _chars_avail;
881
    unsigned char* _chars;
882
    CYG_ADDRWORD _base = sh_chan->ctrl_base;
883
 
884
    // Always check if we're supposed to be enabled; the driver runs
885
    // with DSRs disabled, and a DSR may have been posted (but not
886
    // executed) before the interrupt was masked.
887
    if (!sh_chan->tx_enabled)
888
        return;
889
 
890
#ifdef CYGHWR_SH_SCIF_FLOW_DSRDTR
891
    CYGHWR_SH_SCIF_FLOW_DSRDTR_TX(chan);
892
#endif
893
 
894
    // How many chars can we stuff into the FIFO?
895
    HAL_READ_UINT16(_base+SCIF_SCFDR, _fdr);
896
    _space = 16 - ((_fdr & CYGARC_REG_SCIF_SCFDR_TCOUNT_MASK) >> CYGARC_REG_SCIF_SCFDR_TCOUNT_shift);
897
 
898
    // Try to do the transfer most efficiently
899
    _block_status = (chan->callbacks->data_xmt_req)(chan, _space,
900
                                                    &_chars_avail, &_chars);
901
    if (CYG_XMT_OK == _block_status) {
902
        // Transfer the data in block(s).
903
        do {
904
            int i = _chars_avail;
905
            while (i--) {
906
                HAL_WRITE_UINT8(sh_chan->ctrl_base+SCIF_SCFTDR, *_chars++);
907
                _space--;
908
            }
909
            (chan->callbacks->data_xmt_done)(chan, _chars_avail);
910
        } while (_space > 0 &&
911
                 (CYG_XMT_OK == (chan->callbacks->data_xmt_req)(chan, _space,
912
                                                                &_chars_avail,
913
                                                                &_chars)));
914
    } else if (CYG_XMT_DISABLED == _block_status) {
915
        // Transfer char-by-char, but stop if the transmitter
916
        // gets disabled.
917
        while (_space-- && sh_chan->tx_enabled)
918
            (chan->callbacks->xmt_char)(chan);
919
    }
920
 
921
    // Clear FIFO-empty/transmit end flags (read back sr first)
922
    HAL_READ_UINT16(sh_chan->ctrl_base+SCIF_SCSSR, _sr);
923
    HAL_WRITE_UINT16(sh_chan->ctrl_base+SCIF_SCSSR,
924
                     CYGARC_REG_SCIF_SCSSR_CLEARMASK & ~CYGARC_REG_SCIF_SCSSR_TDFE);
925
 
926
    if (sh_chan->tx_enabled) {
927
        cyg_uint8 _scr;
928
        HAL_READ_UINT8(sh_chan->ctrl_base+SCIF_SCSCR, _scr);
929
        _scr |= CYGARC_REG_SCIF_SCSCR_TIE;       // unmask tx interrupts
930
        HAL_WRITE_UINT8(sh_chan->ctrl_base+SCIF_SCSCR, _scr);
931
    }
932
}
933
 
934
// Serial I/O - low level RX interrupt handler (ISR)
935
static cyg_uint32
936
sh_scif_rx_ISR(cyg_vector_t vector, cyg_addrword_t data)
937
{
938
    serial_channel *chan = (serial_channel *)data;
939
    sh_scif_info *sh_chan = (sh_scif_info *)chan->dev_priv;
940
    cyg_uint8 _scr;
941
 
942
    HAL_READ_UINT8(sh_chan->ctrl_base+SCIF_SCSCR, _scr);
943
    _scr &= ~CYGARC_REG_SCIF_SCSCR_RIE;      // mask rx interrupts
944
    HAL_WRITE_UINT8(sh_chan->ctrl_base+SCIF_SCSCR, _scr);
945
    return CYG_ISR_CALL_DSR;            // Cause DSR to be run
946
}
947
 
948
// Serial I/O - high level rx interrupt handler (DSR)
949
static void
950
sh_scif_rx_DSR(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data)
951
{
952
    serial_channel *chan = (serial_channel *)data;
953
    sh_scif_info *sh_chan = (sh_scif_info *)chan->dev_priv;
954
    cyg_uint8 _scr;
955
    cyg_uint16 _fdr, _sr;
956
    int _avail, _space_avail;
957
    unsigned char* _space;
958
    rcv_req_reply_t _block_status;
959
 
960
    HAL_READ_UINT16(sh_chan->ctrl_base+SCIF_SCFDR, _fdr);
961
    HAL_READ_UINT16(sh_chan->ctrl_base+SCIF_SCSSR, _sr);
962
 
963
    _avail = _fdr & CYGARC_REG_SCIF_SCFDR_RCOUNT_MASK;
964
    if (_avail > 0) {
965
        _block_status = (chan->callbacks->data_rcv_req)(chan, _avail,
966
                                                        &_space_avail, &_space);
967
        if (CYG_RCV_OK == _block_status) {
968
            // Transfer the data in block(s).
969
            do {
970
                int i = _space_avail;
971
                while(i--) {
972
                    cyg_uint8 _c;
973
                    HAL_READ_UINT8(sh_chan->ctrl_base+SCIF_SCFRDR, _c);
974
                    *_space++ = _c;
975
                    _avail--;
976
                }
977
                (chan->callbacks->data_rcv_done)(chan, _space_avail);
978
            } while (_avail > 0 &&
979
                     (CYG_RCV_OK == (chan->callbacks->data_rcv_req)(chan, _avail,
980
                                                                    &_space_avail,
981
                                                                    &_space)));
982
        } else {
983
            // Transfer the data char-by-char both for CYG_RCV_FULL
984
            // and CYG_RCV_DISABLED, leaving all policy decisions with
985
            // the IO driver.
986
            while(_avail--) {
987
                cyg_uint8 _c;
988
                HAL_READ_UINT8(sh_chan->ctrl_base+SCIF_SCFRDR, _c);
989
                (chan->callbacks->rcv_char)(chan, _c);
990
            }
991
        }
992
    } else {
993
        CYG_ASSERT(_avail > 0, "No data to be read in RX DSR");
994
    }
995
 
996
    // Clear buffer full flag (read back first)
997
    HAL_READ_UINT16(sh_chan->ctrl_base+SCIF_SCSSR, _sr);
998
    HAL_WRITE_UINT16(sh_chan->ctrl_base+SCIF_SCSSR,
999
                     CYGARC_REG_SCIF_SCSSR_CLEARMASK & ~(CYGARC_REG_SCIF_SCSSR_RDF|CYGARC_REG_SCIF_SCSSR_DR));
1000
 
1001
    HAL_READ_UINT8(sh_chan->ctrl_base+SCIF_SCSCR, _scr);
1002
    _scr |= CYGARC_REG_SCIF_SCSCR_RIE;       // unmask rx interrupts
1003
    HAL_WRITE_UINT8(sh_chan->ctrl_base+SCIF_SCSCR, _scr);
1004
}
1005
 
1006
// Serial I/O - low level error interrupt handler (ISR)
1007
static cyg_uint32
1008
sh_scif_er_ISR(cyg_vector_t vector, cyg_addrword_t data)
1009
{
1010
    serial_channel *chan = (serial_channel *)data;
1011
    sh_scif_info *sh_chan = (sh_scif_info *)chan->dev_priv;
1012
    cyg_uint8 _scr;
1013
 
1014
    HAL_READ_UINT8(sh_chan->ctrl_base+SCIF_SCSCR, _scr);
1015
    _scr &= ~CYGARC_REG_SCIF_SCSCR_RIE;      // mask rx interrupts
1016
    HAL_WRITE_UINT8(sh_chan->ctrl_base+SCIF_SCSCR, _scr);
1017
    return CYG_ISR_CALL_DSR;            // Cause DSR to be run
1018
}
1019
 
1020
// Serial I/O - high level error interrupt handler (DSR)
1021
static void
1022
sh_scif_er_DSR(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data)
1023
{
1024
    serial_channel *chan = (serial_channel *)data;
1025
    sh_scif_info *sh_chan = (sh_scif_info *)chan->dev_priv;
1026
    cyg_uint16 _ssr, _ssr_mask;
1027
#ifdef SCIF_SC2SSR
1028
    cyg_uint8 _ssr2;
1029
#endif
1030
    cyg_uint8 _scr;
1031
#ifdef CYGOPT_IO_SERIAL_SUPPORT_LINE_STATUS
1032
    cyg_serial_line_status_t stat;
1033
#endif
1034
 
1035
    HAL_READ_UINT16(sh_chan->ctrl_base+SCIF_SCSSR, _ssr);
1036
    _ssr_mask = CYGARC_REG_SCIF_SCSSR_CLEARMASK;
1037
    // Clear the ER bit
1038
    _ssr_mask &= ~CYGARC_REG_SCIF_SCSSR_ER;
1039
 
1040
 
1041
#ifdef SCIF_SC2SSR
1042
    HAL_READ_UINT8(sh_chan->ctrl_base+SCIF_SC2SSR, _ssr2);
1043
    if (_ssr2 & CYGARC_REG_SCIF_SC2SSR_ORER) {
1044
        _ssr2 &= ~CYGARC_REG_SCIF_SC2SSR_ORER;
1045
        HAL_WRITE_UINT8(sh_chan->ctrl_base+SCIF_SC2SSR, _ssr2);
1046
        stat.which = CYGNUM_SERIAL_STATUS_OVERRUNERR;
1047
        (chan->callbacks->indicate_status)(chan, &stat );
1048
    }
1049
#endif
1050
    if (_ssr & CYGARC_REG_SCIF_SCSSR_FER) {
1051
        // _ssr_mask &= ~CYGARC_REG_SCIF_SCSSR_FER; // FER is read-only
1052
#ifdef CYGOPT_IO_SERIAL_SUPPORT_LINE_STATUS
1053
        stat.which = CYGNUM_SERIAL_STATUS_FRAMEERR;
1054
        (chan->callbacks->indicate_status)(chan, &stat );
1055
#endif
1056
    }
1057
    if (_ssr & CYGARC_REG_SCIF_SCSSR_PER) {
1058
        // _ssr_mask &= ~CYGARC_REG_SCIF_SCSSR_PER; // PER is read-only
1059
#ifdef CYGOPT_IO_SERIAL_SUPPORT_LINE_STATUS
1060
        stat.which = CYGNUM_SERIAL_STATUS_PARITYERR;
1061
        (chan->callbacks->indicate_status)(chan, &stat );
1062
#endif
1063
    }
1064
    if (_ssr & CYGARC_REG_SCIF_SCSSR_BRK) {
1065
        _ssr_mask &= ~CYGARC_REG_SCIF_SCSSR_BRK;
1066
#ifdef CYGOPT_IO_SERIAL_SUPPORT_LINE_STATUS
1067
        stat.which = CYGNUM_SERIAL_STATUS_BREAK;
1068
        (chan->callbacks->indicate_status)(chan, &stat );
1069
#endif
1070
    }
1071
    HAL_WRITE_UINT16(sh_chan->ctrl_base+SCIF_SCSSR, _ssr_mask);
1072
 
1073
    HAL_READ_UINT8(sh_chan->ctrl_base+SCIF_SCSCR, _scr);
1074
    _scr |= CYGARC_REG_SCIF_SCSCR_RIE;       // unmask rx interrupts
1075
    HAL_WRITE_UINT8(sh_chan->ctrl_base+SCIF_SCSCR, _scr);
1076
}
1077
 
1078
#endif // ifdef CYGDAT_IO_SERIAL_SH_SCIF_INL

powered by: WebSVN 2.1.0

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