source: rtems/c/src/lib/libcpu/sh/sh7750/sci/sh4uart.c @ 0fdc099

4.104.114.84.95
Last change on this file since 0fdc099 was 3906b3ea, checked in by Ralf Corsepius <ralf.corsepius@…>, on 04/16/04 at 21:29:43

Remove stray white spaces.

  • Property mode set to 100644
File size: 23.2 KB
Line 
1/*
2 * Generic UART Serial driver for SH-4 processors
3 *
4 * Copyright (C) 2000 OKTET Ltd., St.-Petersburg, Russian Fed.
5 * Author: Alexandra Kossovsky <sasha@oktet.ru>
6 *
7 *  COPYRIGHT (c) 1989-2000.
8 *  On-Line Applications Research Corporation (OAR).
9 *
10 *  The license and distribution terms for this file may be
11 *  found in the file LICENSE in this distribution or at
12 *
13 *  http://www.rtems.com/license/LICENSE.
14 *
15 *  $Id$
16 *
17 */
18
19#include <rtems.h>
20#include <termios.h>
21#include <rtems/libio.h>
22#include <bsp.h>
23#include "sh/sh4uart.h"
24
25#ifndef SH4_UART_INTERRUPT_LEVEL
26#define SH4_UART_INTERRUPT_LEVEL 4
27#endif
28
29/* Forward function declarations */
30static rtems_isr
31sh4uart1_interrupt_transmit(rtems_vector_number vec);
32static rtems_isr
33sh4uart1_interrupt_receive(rtems_vector_number vec);
34static rtems_isr
35sh4uart2_interrupt_transmit(rtems_vector_number vec);
36static rtems_isr
37sh4uart2_interrupt_receive(rtems_vector_number vec);
38
39/*
40 * sh4uart_init --
41 * This function verifies the input parameters and perform initialization
42 *     of the SH-4 on-chip UART descriptor structure.
43 *
44 * PARAMETERS:
45 *     uart - pointer to the UART channel descriptor structure
46 *     tty - pointer to termios structure
47 *     chn - channel number (SH4_SCI/SH4_SCIF -- 1/2)
48 *     int_driven - interrupt-driven (1) or polled (0) I/O mode
49 *
50 * RETURNS:
51 *     RTEMS_SUCCESSFUL if all parameters are valid, or error code
52 */
53rtems_status_code
54sh4uart_init(sh4uart *uart, void *tty, int chn, int int_driven)
55{
56    if (uart == NULL)
57        return RTEMS_INVALID_ADDRESS;
58
59    if ((chn != SH4_SCI) && (chn != SH4_SCIF))
60                return RTEMS_INVALID_NUMBER;
61
62    uart->chn = chn;
63    uart->tty = tty;
64    uart->int_driven = int_driven;
65
66#if 0
67    sh4uart_poll_write(uart, "init", 4);
68#endif
69    return RTEMS_SUCCESSFUL;
70}
71
72/*
73 * sh4uart_get_Pph --
74 *    Get current peripheral module clock.
75 *
76 * PARAMETERS: none;
77 *    Cpu clock is get from CPU_CLOCK_RATE_HZ marco
78 *    (defined in bspopts.h, included from bsp.h)
79 *
80 * RETURNS:
81 *    peripheral module clock in Hz.
82 */
83uint32_t
84sh4uart_get_Pph(void)
85{
86    uint16_t   frqcr = *(volatile uint16_t*)SH7750_FRQCR;
87    uint32_t   Pph = CPU_CLOCK_RATE_HZ;
88
89    switch (frqcr & SH7750_FRQCR_IFC)
90    {
91        case SH7750_FRQCR_IFCDIV1:
92            break;
93
94        case SH7750_FRQCR_IFCDIV2:
95            Pph *= 2;
96            break;
97
98        case SH7750_FRQCR_IFCDIV3:
99            Pph *= 3;
100            break;
101
102        case SH7750_FRQCR_IFCDIV4:
103            Pph *= 4;
104            break;
105
106        case SH7750_FRQCR_IFCDIV6:
107            Pph *= 6;
108            break;
109
110        case SH7750_FRQCR_IFCDIV8:
111            Pph *= 8;
112            break;
113
114        default: /* unreachable */
115            break;
116    }
117
118    switch (frqcr & SH7750_FRQCR_PFC)
119    {
120        case SH7750_FRQCR_PFCDIV2:
121            Pph /= 2;
122            break;
123
124        case SH7750_FRQCR_PFCDIV3:
125            Pph /= 3;
126            break;
127
128        case SH7750_FRQCR_PFCDIV4:
129            Pph /= 4;
130            break;
131
132        case SH7750_FRQCR_PFCDIV6:
133            Pph /= 6;
134            break;
135
136        case SH7750_FRQCR_PFCDIV8:
137            Pph /= 8;
138            break;
139
140        default: /* unreachable */
141            break;
142    }
143
144    return Pph;
145}
146
147/*
148 * sh4uart_set_baudrate --
149 *     Program the UART timer to specified baudrate
150 *
151 * PARAMETERS:
152 *     uart - pointer to UART descriptor structure
153 *     baud - termios baud rate (B50, B9600, etc...)
154 *
155 * ALGORITHM:
156 *     see SH7750 Hardware Manual.
157 *
158 * RETURNS:
159 *     none
160 */
161static void
162sh4uart_set_baudrate(sh4uart *uart, speed_t baud)
163{
164    uint32_t   rate;
165    int16_t   div;
166    int n;
167    uint32_t   Pph = sh4uart_get_Pph();
168
169    switch (baud)
170    {
171        case B50:     rate = 50; break;
172        case B75:     rate = 75; break;
173        case B110:    rate = 110; break;
174        case B134:    rate = 134; break;
175        case B150:    rate = 150; break;
176        case B200:    rate = 200; break;
177        case B300:    rate = 300; break;
178        case B600:    rate = 600; break;
179        case B1200:   rate = 1200; break;
180        case B2400:   rate = 2400; break;
181        case B4800:   rate = 4800; break;
182        case B9600:   rate = 9600; break;
183        case B19200:  rate = 19200; break;
184        case B38400:  rate = 38400; break;
185        case B57600:  rate = 57600; break;
186#ifdef B115200
187        case B115200: rate = 115200; break;
188#endif
189#ifdef B230400
190        case B230400: rate = 230400; break;
191#endif
192        default:      rate = 9600; break;
193    }
194
195    for (n = 0; n < 4; n++)
196    {
197        div = Pph / (32 * (1 << (2 * n)) * rate) - 1;
198        if (div < 0x100)
199            break;
200    }
201
202    /* Set default baudrate if specified baudrate is impossible */
203    if (n >= 4)
204        sh4uart_set_baudrate(uart, B9600);
205
206    SCSMR(uart->chn) &= ~SH7750_SCSMR_CKS;
207    SCSMR(uart->chn) |= n << SH7750_SCSMR_CKS_S;
208    SCBRR(uart->chn) = div;
209    /* Whait at least 1 bit interwal */
210    rtems_task_wake_after(RTEMS_MILLISECONDS_TO_TICKS(1000 / rate));
211}
212
213/*
214 * sh4uart_reset --
215 *     This function perform the hardware initialization of SH-4
216 *     on-chip UART controller using parameters
217 *     filled by the sh4uart_init function.
218 *
219 * PARAMETERS:
220 *     uart - pointer to UART channel descriptor structure
221 *
222 * RETURNS:
223 *     RTEMS_SUCCESSFUL if channel is initialized successfully, error
224 *     code in other case
225 */
226rtems_status_code
227sh4uart_reset(sh4uart *uart)
228{
229    register int chn;
230    register int int_driven;
231    rtems_status_code rc;
232
233    if (uart == NULL)
234        return RTEMS_INVALID_ADDRESS;
235
236    chn = uart->chn;
237    int_driven = uart->int_driven;
238
239    SCSCR(chn) = 0x0;       /* Is set properly at the end of this function */
240    SCSMR(chn) = 0x0;       /* 8-bit, non-parity, 1 stop bit, pf/1 clock */
241
242    if (chn == SH4_SCIF)
243        SCFCR2 = SH7750_SCFCR2_TFRST | SH7750_SCFCR2_RFRST |
244                SH7750_SCFCR2_RTRG_1 | SH7750_SCFCR2_TTRG_4;
245
246    if (chn == SH4_SCI)
247        SCSPTR1 = int_driven ? 0x0 : SH7750_SCSPTR1_EIO;
248    else
249        SCSPTR2 = SH7750_SCSPTR2_RTSDT;
250
251    if (int_driven)
252    {
253        uint16_t   ipr;
254
255        if (chn == SH4_SCI)
256        {
257            ipr = IPRB;
258            ipr &= ~SH7750_IPRB_SCI1;
259            ipr |= SH4_UART_INTERRUPT_LEVEL << SH7750_IPRB_SCI1_S;
260            IPRB = ipr;
261
262            rc = rtems_interrupt_catch(sh4uart1_interrupt_transmit,
263                    SH7750_EVT_TO_NUM(SH7750_EVT_SCI_TXI),
264                    &uart->old_handler_transmit);
265            if (rc != RTEMS_SUCCESSFUL)
266                return rc;
267            rc = rtems_interrupt_catch(sh4uart1_interrupt_receive,
268                    SH7750_EVT_TO_NUM(SH7750_EVT_SCI_RXI),
269                    &uart->old_handler_receive);
270            if (rc != RTEMS_SUCCESSFUL)
271                return rc;
272        }
273        else
274        {
275            ipr = IPRC;
276            ipr &= ~SH7750_IPRC_SCIF;
277            ipr |= SH4_UART_INTERRUPT_LEVEL << SH7750_IPRC_SCIF_S;
278            IPRC = ipr;
279
280            rc = rtems_interrupt_catch(sh4uart2_interrupt_transmit,
281                    SH7750_EVT_TO_NUM(SH7750_EVT_SCIF_TXI),
282                    &uart->old_handler_transmit);
283            if (rc != RTEMS_SUCCESSFUL)
284                return rc;
285            rc = rtems_interrupt_catch(sh4uart2_interrupt_receive,
286                    SH7750_EVT_TO_NUM(SH7750_EVT_SCIF_RXI),
287                    &uart->old_handler_receive);
288            if (rc != RTEMS_SUCCESSFUL)
289                return rc;
290        }
291        uart->tx_buf = NULL;
292        uart->tx_ptr = uart->tx_buf_len = 0;
293    }
294
295    sh4uart_set_baudrate(uart, B38400); /* debug defaults (unfortunately,
296                                           it is differ to termios default */
297
298    SCSCR(chn) = SH7750_SCSCR_TE | SH7750_SCSCR_RE |
299            (chn == SH4_SCI ? 0x0 : SH7750_SCSCR2_REIE) |
300            (int_driven ? (SH7750_SCSCR_RIE | SH7750_SCSCR_TIE) : 0x0);
301
302    return RTEMS_SUCCESSFUL;
303}
304
305/*
306 * sh4uart_disable --
307 *     This function disable the operations on SH-4 UART controller
308 *
309 * PARAMETERS:
310 *     uart - pointer to UART channel descriptor structure
311 *     disable_port - disable receive and transmit on the port
312 *
313 * RETURNS:
314 *     RTEMS_SUCCESSFUL if UART closed successfuly, or error code in
315 *     other case
316 */
317rtems_status_code
318sh4uart_disable(sh4uart *uart, int disable_port)
319{
320    rtems_status_code rc;
321
322    if (disable_port)
323        SCSCR(uart->chn) &= ~(SH7750_SCSCR_TE | SH7750_SCSCR_RE);
324
325    if (uart->int_driven)
326    {
327        rc = rtems_interrupt_catch(uart->old_handler_transmit,
328                uart->chn == SH4_SCI ?
329                        SH7750_EVT_SCI_TXI : SH7750_EVT_SCIF_TXI,
330                NULL);
331        if (rc != RTEMS_SUCCESSFUL)
332            return rc;
333        rc = rtems_interrupt_catch(uart->old_handler_receive,
334                uart->chn == SH4_SCI ?
335                        SH7750_EVT_SCI_RXI : SH7750_EVT_SCIF_RXI,
336                NULL);
337        if (rc != RTEMS_SUCCESSFUL)
338            return rc;
339    }
340
341    return RTEMS_SUCCESSFUL;
342}
343
344/*
345 * sh4uart_set_attributes --
346 *     This function parse the termios attributes structure and perform
347 *     the appropriate settings in hardware.
348 *
349 * PARAMETERS:
350 *     uart - pointer to the UART descriptor structure
351 *     t - pointer to termios parameters
352 *
353 * RETURNS:
354 *     RTEMS_SUCCESSFUL
355 */
356rtems_status_code
357sh4uart_set_attributes(sh4uart *uart, const struct termios *t)
358{
359    int level;
360    speed_t baud;
361    uint16_t   smr;
362
363    smr = (uint16_t)(*(uint8_t*)SH7750_SCSMR(uart->chn));
364
365    baud = cfgetospeed(t);
366
367    /* Set flow control XXX*/
368    if ((t->c_cflag & CRTSCTS) != 0)
369    {
370    }
371
372    /* Set character size -- only 7 or 8 bit */
373    switch (t->c_cflag & CSIZE)
374    {
375        case CS5:
376        case CS6:
377        case CS7: smr |= SH7750_SCSMR_CHR_7; break;
378        case CS8: smr &= ~SH7750_SCSMR_CHR_7; break;
379    }
380
381    /* Set number of stop bits */
382    if ((t->c_cflag & CSTOPB) != 0)
383        smr |= SH7750_SCSMR_STOP_2;
384    else
385        smr &= ~SH7750_SCSMR_STOP_2;
386
387    /* Set parity mode */
388    if ((t->c_cflag & PARENB) != 0)
389    {
390        smr |= SH7750_SCSMR_PE;
391        if ((t->c_cflag & PARODD) != 0)
392           smr |= SH7750_SCSMR_PM_ODD;
393        else
394           smr &= ~SH7750_SCSMR_PM_ODD;
395    }
396    else
397        smr &= ~SH7750_SCSMR_PE;
398
399    rtems_interrupt_disable(level);
400    /* wait untill all data is transmitted */
401    rtems_task_wake_after(RTEMS_MILLISECONDS_TO_TICKS(100));
402    /* disable operations */
403    SCSCR(uart->chn) &= ~(SH7750_SCSCR_TE | SH7750_SCSCR_RE);
404
405    sh4uart_set_baudrate(uart, baud);
406    SCSMR(uart->chn) = (uint8_t)smr;
407
408    /* enable operations */
409    SCSCR(uart->chn) |= SH7750_SCSCR_TE | SH7750_SCSCR_RE;
410    rtems_interrupt_enable(level);
411
412    return RTEMS_SUCCESSFUL;
413}
414
415/*
416 * sh4uart_handle_error --
417 *     Perfoms error (Overrun, Framing & Parity) handling
418 *
419 * PARAMETERS:
420 *     uart - pointer to UART descriptor structure
421 *
422 * RETURNS:
423 *     nothing
424 */
425void
426sh4uart_handle_error(sh4uart *uart)
427{
428#if 0
429    int status_reg = SCSSR(uart->chn);
430#endif
431
432    if(uart->chn == SH4_SCI)
433    {
434        SCSSR1 &= ~(SH7750_SCSSR1_ORER | SH7750_SCSSR1_FER | SH7750_SCSSR1_PER);
435    }
436    else
437    {
438        SCSSR2 &= ~(SH7750_SCSSR2_ER | SH7750_SCSSR2_BRK | SH7750_SCSSR2_FER);
439        SCLSR2 &= ~(SH7750_SCLSR2_ORER);
440    }
441}
442
443/*
444 * sh4uart_poll_read --
445 *     This function tried to read character from SH-4 UART and perform
446 *     error handling. When parity or framing error occured, return
447 *     value dependent on termios input mode flags:
448 *         - received character, if IGNPAR == 1
449 *         - 0, if IGNPAR == 0 and PARMRK == 0
450 *         - 0xff and 0x00 on next poll_read invocation, if IGNPAR == 0 and
451 *           PARMRK == 1
452 *
453 * PARAMETERS:
454 *     uart - pointer to UART descriptor structure
455 *
456 * RETURNS:
457 *     code of received character or -1 if no characters received.
458 */
459int
460sh4uart_poll_read(sh4uart *uart)
461{
462    int chn = uart->chn;
463    int error_occured = 0;
464    int parity_error = 0;
465    int break_occured = 0;
466    int ch;
467
468    if (uart->parerr_mark_flag == 1)
469    {
470        uart->parerr_mark_flag = 0;
471        return 0;
472    }
473
474    if (chn == SH4_SCI)
475    {
476        if ((SCSSR1 & (SH7750_SCSSR1_PER | SH7750_SCSSR1_FER |
477                     SH7750_SCSSR1_ORER)) != 0)
478        {
479            error_occured = 1;
480            if (SCSSR1 & (SH7750_SCSSR1_PER | SH7750_SCSSR1_FER))
481                parity_error = 1;
482            sh4uart_handle_error(uart);
483        }
484        if ((SCSSR1 & SH7750_SCSSR1_RDRF) == 0)
485            return -1;
486    }
487    else
488    {
489        if ((SCSSR2 & (SH7750_SCSSR2_ER | SH7750_SCSSR2_DR |
490                     SH7750_SCSSR2_BRK)) != 0 ||
491                (SCLSR2 & SH7750_SCLSR2_ORER) != 0)
492        {
493            error_occured = 1;
494            if (SCSSR2 & (SH7750_SCSSR1_PER | SH7750_SCSSR1_FER))
495                parity_error = 1;
496            if (SCSSR2 & SH7750_SCSSR2_BRK)
497                break_occured = 1;
498            sh4uart_handle_error(uart);
499        }
500        if ((SCSSR2 & SH7750_SCSSR2_RDF) == 0)
501            return -1;
502    }
503
504    if (parity_error && !(uart->c_iflag & IGNPAR))
505    {
506        if (uart->c_iflag & PARMRK)
507        {
508            uart->parerr_mark_flag = 1;
509            return 0xff;
510        }
511        else
512            return 0;
513    }
514
515    if (break_occured && !(uart->c_iflag & BRKINT))
516    {
517        if (uart->c_iflag & IGNBRK)
518            return 0;
519        else
520            return 0;   /* XXX -- SIGINT */
521    }
522
523    ch = SCRDR(chn);
524    if (uart->chn == SH4_SCI)
525        SCSSR1 &= ~SH7750_SCSSR1_RDRF;
526    else
527        SCSSR2 &= ~SH7750_SCSSR2_RDF;
528
529    return ch;
530}
531
532/*
533 * sh4uart_poll_write --
534 *     This function transmit buffer byte-by-byte in polling mode.
535 *
536 * PARAMETERS:
537 *     uart - pointer to the UART descriptor structure
538 *     buf - pointer to transmit buffer
539 *     len - transmit buffer length
540 *
541 * RETURNS:
542 *     0
543 */
544int
545sh4uart_poll_write(sh4uart *uart, const char *buf, int len)
546{
547    while (len)
548    {
549        if (uart->chn == SH4_SCI)
550        {
551            while ((SCSSR1 & SH7750_SCSSR1_TDRE) != 0)
552            {
553                SCTDR1 = *buf++;
554                len--;
555                SCSSR1 &= ~SH7750_SCSSR1_TDRE;
556            }
557        }
558        else
559        {
560            while ((SCSSR2 & SH7750_SCSSR2_TDFE) != 0)
561            {
562                int i;
563                for (i = 0;
564                        i < 16 - TRANSMIT_TRIGGER_VALUE(SCFCR2 &
565                            SH7750_SCFCR2_TTRG);
566                        i++)
567                {
568                    SCTDR2 = *buf++;
569                    len--;
570                }
571                while ((SCSSR2 & SH7750_SCSSR2_TDFE) == 0 ||
572                        (SCSSR2 & SH7750_SCSSR2_TEND) == 0);
573                    SCSSR2 &= ~(SH7750_SCSSR1_TDRE | SH7750_SCSSR2_TEND);
574            }
575        }
576    }
577    return 0;
578}
579
580/**********************************
581 * Functions to handle interrupts *
582 **********************************/
583/* sh4uart1_interrupt_receive --
584 *     UART interrupt handler routine -- SCI
585 *     Receiving data
586 *
587 * PARAMETERS:
588 *     vec - interrupt vector number
589 *
590 * RETURNS:
591 *     none
592 */
593static rtems_isr
594sh4uart1_interrupt_receive(rtems_vector_number vec)
595{
596    register int bp = 0;
597    char buf[32];
598
599    /* Find UART descriptor from vector number */
600    sh4uart *uart = &sh4_uarts[0];
601
602    while (1)
603    {
604        if ((bp < sizeof(buf) - 1) && ((SCSSR1 & SH7750_SCSSR1_RDRF) != 0))
605        {
606            /* Receive character and handle frame/parity errors */
607            if ((SCSSR1 & (SH7750_SCSSR1_PER | SH7750_SCSSR1_FER |
608                            SH7750_SCSSR1_ORER)) != 0)
609            {
610                if (SCSSR1 & (SH7750_SCSSR1_PER | SH7750_SCSSR1_FER))
611                {
612                    if(!(uart->c_iflag & IGNPAR))
613                    {
614                        if (uart->c_iflag & PARMRK)
615                        {
616                            buf[bp++] = 0xff;
617                            buf[bp++] = 0x00;
618                        }
619                        else
620                            buf[bp++] = 0x00;
621                    }
622                    else
623                        buf[bp++] = SCRDR1;
624                }
625                sh4uart_handle_error(uart);
626            }
627            else
628                buf[bp++] = SCRDR1;
629            SCSSR1 &= ~SH7750_SCSSR1_RDRF;
630        }
631        else
632        {
633            if (bp != 0)
634                rtems_termios_enqueue_raw_characters(uart->tty, buf, bp);
635            break;
636        }
637    }
638}
639
640/* sh4uart2_interrupt_receive --
641 *     UART interrupt handler routine -- SCIF
642 *     Receiving data
643 *
644 * PARAMETERS:
645 *     vec - interrupt vector number
646 *
647 * RETURNS:
648 *     none
649 */
650static rtems_isr
651sh4uart2_interrupt_receive(rtems_vector_number vec)
652{
653    register int bp = 0;
654    char buf[32];
655
656    /* Find UART descriptor from vector number */
657    sh4uart *uart = &sh4_uarts[1];
658
659    while (1)
660    {
661        if ((bp < sizeof(buf) - 1) && ((SCSSR2 & SH7750_SCSSR2_RDF) != 0))
662        {
663            if ((SCSSR2 & (SH7750_SCSSR2_ER | SH7750_SCSSR2_DR |
664                            SH7750_SCSSR2_BRK)) != 0 ||
665                    (SH7750_SCLSR2 & SH7750_SCLSR2_ORER) != 0)
666            {
667                if (SCSSR2 & SH7750_SCSSR2_ER)
668                {
669                    if(!(uart->c_iflag & IGNPAR))
670                    {
671                        if (uart->c_iflag & PARMRK)
672                        {
673                            buf[bp++] = 0xff;
674                            buf[bp++] = 0x00;
675                        }
676                        else
677                            buf[bp++] = 0x00;
678                    }
679                    else
680                        buf[bp++] = SCRDR1;
681                }
682
683                if (SCSSR2 & SH7750_SCSSR2_BRK)
684                {
685                    if (uart->c_iflag & IGNBRK)
686                        buf[bp++] = 0x00;
687                    else
688                        buf[bp++] = 0x00;   /* XXX -- SIGINT */
689                }
690
691                sh4uart_handle_error(uart);
692            }
693            else
694                buf[bp++] = SCRDR1;
695            SCSSR2 &= ~SH7750_SCSSR2_RDF;
696        }
697        else
698        {
699            if (bp != 0)
700                rtems_termios_enqueue_raw_characters(uart->tty, buf, bp);
701            break;
702        }
703    }
704}
705
706
707/* sh4uart1_interrupt_transmit --
708 *     UART interrupt handler routine -- SCI
709 *     It continues transmit data when old part of data is transmitted
710 *
711 * PARAMETERS:
712 *     vec - interrupt vector number
713 *
714 * RETURNS:
715 *     none
716 */
717static rtems_isr
718sh4uart1_interrupt_transmit(rtems_vector_number vec)
719{
720    /* Find UART descriptor from vector number */
721    sh4uart *uart = &sh4_uarts[0];
722
723    if (uart->tx_buf != NULL && uart->tx_ptr < uart->tx_buf_len)
724    {
725        while ((SCSSR1 & SH7750_SCSSR1_TDRE) != 0 &&
726                uart->tx_ptr < uart->tx_buf_len)
727        {
728            SCTDR1 = uart->tx_buf[uart->tx_ptr++];
729            SCSSR1 &= ~SH7750_SCSSR1_TDRE;
730        }
731    }
732    else
733    {
734        register int dequeue = uart->tx_buf_len;
735
736        uart->tx_buf = NULL;
737        uart->tx_ptr = uart->tx_buf_len = 0;
738
739        /* Disable interrupts while we do not have any data to transmit */
740        SCSCR1 &= ~SH7750_SCSCR_TIE;
741
742        rtems_termios_dequeue_characters(uart->tty, dequeue);
743    }
744}
745
746/* sh4uart2_interrupt_transmit --
747 *     UART interrupt handler routine -- SCI
748 *     It continues transmit data when old part of data is transmitted
749 *
750 * PARAMETERS:
751 *     vec - interrupt vector number
752 *
753 * RETURNS:
754 *     none
755 */
756static rtems_isr
757sh4uart2_interrupt_transmit(rtems_vector_number vec)
758{
759    /* Find UART descriptor from vector number */
760    sh4uart *uart = &sh4_uarts[1];
761
762    if (uart->tx_buf != NULL && uart->tx_ptr < uart->tx_buf_len)
763    {
764            while ((SCSSR2 & SH7750_SCSSR2_TDFE) != 0)
765            {
766                int i;
767                for (i = 0;
768                        i < 16 - TRANSMIT_TRIGGER_VALUE(SCFCR2 &
769                            SH7750_SCFCR2_TTRG);
770                        i++)
771                    SCTDR2 = uart->tx_buf[uart->tx_ptr++];
772                while ((SCSSR1 & SH7750_SCSSR1_TDRE) == 0 ||
773                        (SCSSR1 & SH7750_SCSSR1_TEND) == 0);
774                    SCSSR1 &= ~(SH7750_SCSSR1_TDRE | SH7750_SCSSR2_TEND);
775            }
776    }
777    else
778    {
779        register int dequeue = uart->tx_buf_len;
780
781        uart->tx_buf = NULL;
782        uart->tx_ptr = uart->tx_buf_len = 0;
783
784        /* Disable interrupts while we do not have any data to transmit */
785        SCSCR2 &= ~SH7750_SCSCR_TIE;
786
787        rtems_termios_dequeue_characters(uart->tty, dequeue);
788    }
789}
790
791/* sh4uart_interrupt_write --
792 *     This function initiate transmitting of the buffer in interrupt mode.
793 *
794 * PARAMETERS:
795 *     uart - pointer to the UART descriptor structure
796 *     buf - pointer to transmit buffer
797 *     len - transmit buffer length
798 *
799 * RETURNS:
800 *     0
801 */
802rtems_status_code
803sh4uart_interrupt_write(sh4uart *uart, const char *buf, int len)
804{
805    int level;
806
807    while ((SCSSR1 & SH7750_SCSSR1_TEND) == 0);
808
809    rtems_interrupt_disable(level);
810
811    uart->tx_buf = buf;
812    uart->tx_buf_len = len;
813    uart->tx_ptr = 0;
814
815    if (uart->chn == SH4_SCI)
816    {
817        SCSCR1 |= SH7750_SCSCR_TIE;
818    }
819    else
820        SCSCR2 |= SH7750_SCSCR_TIE;
821
822    rtems_interrupt_enable(level);
823
824    return RTEMS_SUCCESSFUL;
825}
826
827/* sh4uart_stop_remote_tx --
828 *     This function stop data flow from remote device.
829 *
830 * PARAMETERS:
831 *     uart - pointer to the UART descriptor structure
832 *
833 * RETURNS:
834 *     RTEMS_SUCCESSFUL
835 */
836rtems_status_code
837sh4uart_stop_remote_tx(sh4uart *uart)
838{
839    SCSCR(uart->chn) &= ~(SH7750_SCSCR_RIE | SH7750_SCSCR_RE);
840    return RTEMS_SUCCESSFUL;
841}
842
843/* sh4uart_start_remote_tx --
844 *     This function resume data flow from remote device.
845 *
846 * PARAMETERS:
847 *     uart - pointer to the UART descriptor structure
848 *
849 * RETURNS:
850 *     RTEMS_SUCCESSFUL
851 */
852rtems_status_code
853sh4uart_start_remote_tx(sh4uart *uart)
854{
855    SCSCR(uart->chn) |= SH7750_SCSCR_RIE | SH7750_SCSCR_RE;
856    return RTEMS_SUCCESSFUL;
857}
858
859#ifdef SH4_WITH_IPL
860/*********************************
861 * Functions for SH-IPL gdb stub *
862 *********************************/
863
864/*
865 * ipl_finish --
866 *     Says gdb that program finished to get out from it.
867 */
868extern void ipl_finish(void);
869asm(
870"   .global _ipl_finish\n"
871"_ipl_finish:\n"
872"   mov.l   __ipl_finish_value, r0\n"
873"   trapa   #0x3f\n"
874"   nop\n"
875"   rts\n"
876"   nop\n"
877"   .align 4\n"
878"__ipl_finish_value:\n"
879"   .long   255"
880);
881
882extern int ipl_serial_input(int poll_count);
883asm(
884"    .global _ipl_serial_input\n"
885"_ipl_serial_input:\n"
886"    mov  #1,r0\n"
887"    trapa #0x3f\n"
888"    nop\n"
889"    rts\n"
890"    nop\n");
891
892extern void ipl_serial_output(const char *buf, int len);
893asm (
894"    .global _ipl_serial_output\n"
895"_ipl_serial_output:\n"
896"    mov  #0,r0\n"
897"    trapa #0x3f\n"
898"    nop\n"
899"    rts\n"
900"    nop\n");
901
902/* ipl_console_poll_read --
903 *     poll read operation for simulator console through ipl mechanism.
904 *
905 * PARAMETERS:
906 *     minor - minor device number
907 *
908 * RETURNS:
909 *     character code red from UART, or -1 if there is no characters
910 *     available
911 */
912int
913ipl_console_poll_read(int minor)
914{
915    unsigned char buf;
916    buf = ipl_serial_input(0x100000);
917    return buf;
918}
919
920/* ipl_console_poll_write --
921 *     wrapper for polling mode write function
922 *
923 * PARAMETERS:
924 *     minor - minor device number
925 *     buf - output buffer
926 *     len - output buffer length
927 *
928 * RETURNS:
929 *     result code (0)
930 */
931int
932ipl_console_poll_write(int minor, const char *buf, int len)
933{
934    int c;
935    while (len > 0)
936    {
937        c = (len < 64 ? len : 64);
938        ipl_serial_output(buf, c);
939        len -= c;
940        buf += c;
941    }
942    return 0;
943}
944#endif
Note: See TracBrowser for help on using the repository browser.