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

4.104.114.84.95
Last change on this file since 5850c533 was 12ae6d9e, checked in by Joel Sherrill <joel.sherrill@…>, on 10/15/01 at 18:01:12

2001-10-15 Ralf Corsepius <corsepiu@…>

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