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

4.104.114.84.95
Last change on this file since 3bcc0d8 was f08c3a86, checked in by Joel Sherrill <joel.sherrill@…>, on 10/12/01 at 21:00:22

2001-10-12 Joel Sherrill <joel@…>

  • clock/ckinit.c, include/iosh7750.h, include/ipl.h, include/ispsh7750.h, sci/console.c, sci/sh4uart.c, score/cpu_asm.c, score/ispsh7750.c, timer/timer.c: Fixed typo.
  • 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 *
13 *  The license and distribution terms for this file may be
14 *  found in the file LICENSE in this distribution or at
15 *
16 *  http://www.OARcorp.com/rtems/license.html.
17 *
18 *  $Id$
19 *
20 */
21
22#include <rtems.h>
23#include <termios.h>
24#include <rtems/libio.h>
25#include "sh/sh4uart.h"
26
27#ifndef SH4_UART_INTERRUPT_LEVEL
28#define SH4_UART_INTERRUPT_LEVEL 4
29#endif
30
31/* Forward function declarations */
32static rtems_isr
33sh4uart1_interrupt_transmit(rtems_vector_number vec);
34static rtems_isr
35sh4uart1_interrupt_receive(rtems_vector_number vec);
36static rtems_isr
37sh4uart2_interrupt_transmit(rtems_vector_number vec);
38static rtems_isr
39sh4uart2_interrupt_receive(rtems_vector_number vec);
40
41/*
42 * sh4uart_init --
43 * This function verifies the input parameters and perform initialization
44 *     of the SH-4 on-chip UART descriptor structure.
45 *
46 * PARAMETERS:
47 *     uart - pointer to the UART channel descriptor structure
48 *     tty - pointer to termios structure
49 *     chn - channel number (SH4_SCI/SH4_SCIF -- 1/2)
50 *     int_driven - interrupt-driven (1) or polled (0) I/O mode
51 *
52 * RETURNS:
53 *     RTEMS_SUCCESSFUL if all parameters are valid, or error code
54 */
55rtems_status_code
56sh4uart_init(sh4uart *uart, void *tty, int chn, int int_driven)
57{
58    if (uart == NULL)
59        return RTEMS_INVALID_ADDRESS;
60
61    if ((chn != SH4_SCI) && (chn != SH4_SCIF))
62                return RTEMS_INVALID_NUMBER;
63
64    uart->chn = chn;
65    uart->tty = tty;
66    uart->int_driven = int_driven;
67
68#if 0
69    sh4uart_poll_write(uart, "init", 4);
70#endif
71    return RTEMS_SUCCESSFUL;
72}
73
74/*
75 * sh4uart_get_Pph --
76 *    Get current peripheral module clock.
77 *   
78 * PARAMETERS: none;
79 *    Cpu clock is get from SH4_CPU_HZ_Frequency.
80 *    This variable should be defined in bsp.
81 *
82 * RETURNS:
83 *    peripheral module clock in Hz.
84 */
85rtems_unsigned32
86sh4uart_get_Pph(void)
87{
88    rtems_unsigned16 frqcr = *(volatile rtems_unsigned16 *)SH7750_FRQCR;
89    rtems_unsigned32 Pph = SH4_CPU_HZ_Frequency;
90
91    switch (frqcr & SH7750_FRQCR_IFC)
92    {
93        case SH7750_FRQCR_IFCDIV1:
94            break;
95
96        case SH7750_FRQCR_IFCDIV2:
97            Pph *= 2;
98            break;
99
100        case SH7750_FRQCR_IFCDIV3:
101            Pph *= 3;
102            break;
103
104        case SH7750_FRQCR_IFCDIV4:
105            Pph *= 4;
106            break;
107
108        case SH7750_FRQCR_IFCDIV6:
109            Pph *= 6;
110            break;
111
112        case SH7750_FRQCR_IFCDIV8:
113            Pph *= 8;
114            break;
115
116        default: /* unreachable */
117            break;
118    }
119   
120    switch (frqcr & SH7750_FRQCR_PFC)
121    {
122        case SH7750_FRQCR_PFCDIV2:
123            Pph /= 2;
124            break;
125
126        case SH7750_FRQCR_PFCDIV3:
127            Pph /= 3;
128            break;
129
130        case SH7750_FRQCR_PFCDIV4:
131            Pph /= 4;
132            break;
133
134        case SH7750_FRQCR_PFCDIV6:
135            Pph /= 6;
136            break;
137
138        case SH7750_FRQCR_PFCDIV8:
139            Pph /= 8;
140            break;
141
142        default: /* unreachable */
143            break;
144    }
145
146    return Pph;
147}
148
149/*
150 * sh4uart_set_baudrate --
151 *     Program the UART timer to specified baudrate
152 *
153 * PARAMETERS:
154 *     uart - pointer to UART descriptor structure
155 *     baud - termios baud rate (B50, B9600, etc...)
156 *
157 * ALGORITHM:
158 *     see SH7750 Hardware Manual.
159 *
160 * RETURNS:
161 *     none
162 */
163static void
164sh4uart_set_baudrate(sh4uart *uart, speed_t baud)
165{
166    rtems_unsigned32 rate;
167    rtems_signed16 div;
168    int n;
169    rtems_unsigned32 Pph = sh4uart_get_Pph();
170
171    switch (baud)
172    {
173        case B50:     rate = 50; break;
174        case B75:     rate = 75; break;
175        case B110:    rate = 110; break;
176        case B134:    rate = 134; break;
177        case B150:    rate = 150; break;
178        case B200:    rate = 200; break;
179        case B300:    rate = 300; break;
180        case B600:    rate = 600; break;
181        case B1200:   rate = 1200; break;
182        case B2400:   rate = 2400; break;
183        case B4800:   rate = 4800; break;
184        case B9600:   rate = 9600; break;
185        case B19200:  rate = 19200; break;
186        case B38400:  rate = 38400; break;
187        case B57600:  rate = 57600; break;
188#ifdef B115200
189        case B115200: rate = 115200; break;
190#endif
191#ifdef B230400
192        case B230400: rate = 230400; break;
193#endif
194        default:      rate = 9600; break;
195    }
196
197    for (n = 0; n < 4; n++)
198    {
199        div = Pph / (32 * (1 << (2 * n)) * rate) - 1;
200        if (div < 0x100)
201            break;
202    }
203
204    /* Set default baudrate if specified baudrate is impossible */
205    if (n >= 4)
206        sh4uart_set_baudrate(uart, B9600);
207   
208    SCSMR(uart->chn) &= ~SH7750_SCSMR_CKS;
209    SCSMR(uart->chn) |= n << SH7750_SCSMR_CKS_S;
210    SCBRR(uart->chn) = div;
211    /* Whait at least 1 bit interwal */
212    rtems_task_wake_after(RTEMS_MILLISECONDS_TO_TICKS(1000 / rate));
213}
214
215/*
216 * sh4uart_reset --
217 *     This function perform the hardware initialization of SH-4
218 *     on-chip UART controller using parameters
219 *     filled by the sh4uart_init function.
220 *
221 * PARAMETERS:
222 *     uart - pointer to UART channel descriptor structure
223 *
224 * RETURNS:
225 *     RTEMS_SUCCESSFUL if channel is initialized successfully, error
226 *     code in other case
227 */
228rtems_status_code
229sh4uart_reset(sh4uart *uart)
230{
231    register int chn;
232    register int int_driven;
233    rtems_status_code rc;
234
235    if (uart == NULL)
236        return RTEMS_INVALID_ADDRESS;
237
238    chn = uart->chn;
239    int_driven = uart->int_driven;
240
241    SCSCR(chn) = 0x0;       /* Is set properly at the end of this function */
242    SCSMR(chn) = 0x0;       /* 8-bit, non-parity, 1 stop bit, pf/1 clock */
243
244    if (chn == SH4_SCIF)
245        SCFCR2 = SH7750_SCFCR2_TFRST | SH7750_SCFCR2_RFRST |
246                SH7750_SCFCR2_RTRG_1 | SH7750_SCFCR2_TTRG_4;
247
248    if (chn == SH4_SCI)
249        SCSPTR1 = int_driven ? 0x0 : SH7750_SCSPTR1_EIO;
250    else
251        SCSPTR2 = SH7750_SCSPTR2_RTSDT;
252
253    if (int_driven)
254    {
255        rtems_unsigned16 ipr;
256
257        if (chn == SH4_SCI)
258        {
259            ipr = IPRB;
260            ipr &= ~SH7750_IPRB_SCI1;
261            ipr |= SH4_UART_INTERRUPT_LEVEL << SH7750_IPRB_SCI1_S;
262            IPRB = ipr;
263
264            rc = rtems_interrupt_catch(sh4uart1_interrupt_transmit,
265                    SH7750_EVT_TO_NUM(SH7750_EVT_SCI_TXI),
266                    &uart->old_handler_transmit);
267            if (rc != RTEMS_SUCCESSFUL)
268                return rc;
269            rc = rtems_interrupt_catch(sh4uart1_interrupt_receive,
270                    SH7750_EVT_TO_NUM(SH7750_EVT_SCI_RXI),
271                    &uart->old_handler_receive);
272            if (rc != RTEMS_SUCCESSFUL)
273                return rc;
274        }
275        else
276        {
277            ipr = IPRC;
278            ipr &= ~SH7750_IPRC_SCIF;
279            ipr |= SH4_UART_INTERRUPT_LEVEL << SH7750_IPRC_SCIF_S;
280            IPRC = ipr;
281
282            rc = rtems_interrupt_catch(sh4uart2_interrupt_transmit,
283                    SH7750_EVT_TO_NUM(SH7750_EVT_SCIF_TXI),
284                    &uart->old_handler_transmit);
285            if (rc != RTEMS_SUCCESSFUL)
286                return rc;
287            rc = rtems_interrupt_catch(sh4uart2_interrupt_receive,
288                    SH7750_EVT_TO_NUM(SH7750_EVT_SCIF_RXI),
289                    &uart->old_handler_receive);
290            if (rc != RTEMS_SUCCESSFUL)
291                return rc;
292        }
293        uart->tx_buf = NULL;
294        uart->tx_ptr = uart->tx_buf_len = 0;
295    }
296
297    sh4uart_set_baudrate(uart, B38400); /* debug defaults (unfortunately,
298                                           it is differ to termios default */
299
300    SCSCR(chn) = SH7750_SCSCR_TE | SH7750_SCSCR_RE |
301            (chn == SH4_SCI ? 0x0 : SH7750_SCSCR2_REIE) |
302            (int_driven ? (SH7750_SCSCR_RIE | SH7750_SCSCR_TIE) : 0x0);
303                   
304    return RTEMS_SUCCESSFUL;
305}
306
307/*
308 * sh4uart_disable --
309 *     This function disable the operations on SH-4 UART controller
310 *
311 * PARAMETERS:
312 *     uart - pointer to UART channel descriptor structure
313 *
314 * RETURNS:
315 *     RTEMS_SUCCESSFUL if UART closed successfuly, or error code in
316 *     other case
317 */
318rtems_status_code
319sh4uart_disable(sh4uart *uart)
320{
321    rtems_status_code rc;
322
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    rtems_unsigned16 smr;
362   
363    smr = (rtems_unsigned16)(*(rtems_unsigned8 *)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) = (rtems_unsigned8)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.