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

4.104.114.84.95
Last change on this file since ba71076 was ba71076, checked in by Joel Sherrill <joel.sherrill@…>, on 10/12/01 at 13:19:08

2001-10-11 Alexandra Kossovsky <sasha@…>

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