Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:24:01

0001 /*
0002  * Generic UART Serial driver for SH-4 processors
0003  *
0004  * Copyright (C) 2000 OKTET Ltd., St.-Petersburg, Russian Fed.
0005  * Author: Alexandra Kossovsky <sasha@oktet.ru>
0006  *
0007  *  COPYRIGHT (c) 1989-2000.
0008  *  On-Line Applications Research Corporation (OAR).
0009  *
0010  *  The license and distribution terms for this file may be
0011  *  found in the file LICENSE in this distribution or at
0012  *  http://www.rtems.org/license/LICENSE.
0013  *
0014  */
0015 
0016 #include <rtems.h>
0017 #include <termios.h>
0018 #include <rtems/libio.h>
0019 #include <bsp.h>
0020 #include "sh/sh4uart.h"
0021 
0022 #ifndef SH4_UART_INTERRUPT_LEVEL
0023 #define SH4_UART_INTERRUPT_LEVEL 4
0024 #endif
0025 
0026 /* Forward function declarations */
0027 static rtems_isr
0028 sh4uart1_interrupt_transmit(rtems_vector_number vec);
0029 static rtems_isr
0030 sh4uart1_interrupt_receive(rtems_vector_number vec);
0031 static rtems_isr
0032 sh4uart2_interrupt_transmit(rtems_vector_number vec);
0033 static rtems_isr
0034 sh4uart2_interrupt_receive(rtems_vector_number vec);
0035 
0036 /*
0037  * sh4uart_init --
0038  * This function verifies the input parameters and perform initialization
0039  *     of the SH-4 on-chip UART descriptor structure.
0040  *
0041  * PARAMETERS:
0042  *     uart - pointer to the UART channel descriptor structure
0043  *     tty - pointer to termios structure
0044  *     chn - channel number (SH4_SCI/SH4_SCIF -- 1/2)
0045  *     int_driven - interrupt-driven (1) or polled (0) I/O mode
0046  *
0047  * RETURNS:
0048  *     RTEMS_SUCCESSFUL if all parameters are valid, or error code
0049  */
0050 rtems_status_code
0051 sh4uart_init(sh4uart *uart, void *tty, int chn, int int_driven)
0052 {
0053   if (uart == NULL)
0054     return RTEMS_INVALID_ADDRESS;
0055 
0056   if ((chn != SH4_SCI) && (chn != SH4_SCIF))
0057     return RTEMS_INVALID_NUMBER;
0058 
0059   uart->chn = chn;
0060   uart->tty = tty;
0061   uart->int_driven = int_driven;
0062 
0063 #if 0
0064   sh4uart_poll_write(uart, "init", 4);
0065 #endif
0066   return RTEMS_SUCCESSFUL;
0067 }
0068 
0069 /*
0070  * sh4uart_get_Pph --
0071  *    Get current peripheral module clock.
0072  *
0073  * PARAMETERS: none;
0074  *    Cpu clock is get from CPU_CLOCK_RATE_HZ marco
0075  *    (defined in bspopts.h, included from bsp.h)
0076  *
0077  * RETURNS:
0078  *    peripheral module clock in Hz.
0079  */
0080 static uint32_t
0081 sh4uart_get_Pph(void)
0082 {
0083   uint16_t   frqcr = *(volatile uint16_t*)SH7750_FRQCR;
0084   uint32_t   Pph = CPU_CLOCK_RATE_HZ;
0085 
0086   switch (frqcr & SH7750_FRQCR_IFC) {
0087     case SH7750_FRQCR_IFCDIV1: break;
0088     case SH7750_FRQCR_IFCDIV2: Pph *= 2; break;
0089     case SH7750_FRQCR_IFCDIV3: Pph *= 3; break;
0090     case SH7750_FRQCR_IFCDIV4: Pph *= 4; break;
0091     case SH7750_FRQCR_IFCDIV6: Pph *= 6; break;
0092     case SH7750_FRQCR_IFCDIV8: Pph *= 8; break;
0093     default: /* unreachable */
0094       break;
0095   }
0096 
0097   switch (frqcr & SH7750_FRQCR_PFC) {
0098     case SH7750_FRQCR_PFCDIV2: Pph /= 2; break;
0099     case SH7750_FRQCR_PFCDIV3: Pph /= 3; break;
0100     case SH7750_FRQCR_PFCDIV4: Pph /= 4; break;
0101     case SH7750_FRQCR_PFCDIV6: Pph /= 6; break;
0102     case SH7750_FRQCR_PFCDIV8: Pph /= 8; break;
0103     default: /* unreachable */
0104       break;
0105   }
0106 
0107   return Pph;
0108 }
0109 
0110 /*
0111  * sh4uart_set_baudrate --
0112  *     Program the UART timer to specified baudrate
0113  *
0114  * PARAMETERS:
0115  *     uart - pointer to UART descriptor structure
0116  *     baud - termios baud rate (B50, B9600, etc...)
0117  *
0118  * ALGORITHM:
0119  *     see SH7750 Hardware Manual.
0120  *
0121  * RETURNS:
0122  *     none
0123  */
0124 static void
0125 sh4uart_set_baudrate(sh4uart *uart, speed_t baud)
0126 {
0127   uint32_t   rate;
0128   int16_t   div;
0129   int n;
0130   uint32_t   Pph = sh4uart_get_Pph();
0131 
0132   switch (baud) {
0133     case B50:     rate = 50; break;
0134     case B75:     rate = 75; break;
0135     case B110:    rate = 110; break;
0136     case B134:    rate = 134; break;
0137     case B150:    rate = 150; break;
0138     case B200:    rate = 200; break;
0139     case B300:    rate = 300; break;
0140     case B600:    rate = 600; break;
0141     case B1200:   rate = 1200; break;
0142     case B2400:   rate = 2400; break;
0143     case B4800:   rate = 4800; break;
0144     case B9600:   rate = 9600; break;
0145     case B19200:  rate = 19200; break;
0146     case B38400:  rate = 38400; break;
0147     case B57600:  rate = 57600; break;
0148 #ifdef B115200
0149     case B115200: rate = 115200; break;
0150 #endif
0151 #ifdef B230400
0152     case B230400: rate = 230400; break;
0153 #endif
0154     default:      rate = 9600; break;
0155   }
0156 
0157   for (n = 0; n < 4; n++) {
0158     div = Pph / (32 * (1 << (2 * n)) * rate) - 1;
0159     if (div < 0x100)
0160       break;
0161   }
0162 
0163   /* Set default baudrate if specified baudrate is impossible */
0164   if (n >= 4)
0165     sh4uart_set_baudrate(uart, B9600);
0166 
0167   if ( uart->chn == 1 ) {
0168     volatile uint8_t *smr1 = (volatile uint8_t *)SH7750_SCSMR1;
0169     *smr1 &= ~SH7750_SCSMR_CKS;
0170     *smr1 |= n << SH7750_SCSMR_CKS_S;
0171   } else {
0172     volatile uint16_t *smr2 = (volatile uint16_t *)SH7750_SCSMR2;
0173     *smr2 &= ~SH7750_SCSMR_CKS;
0174     *smr2 |= n << SH7750_SCSMR_CKS_S;
0175   }
0176 
0177   SCBRR(uart->chn) = div;
0178   /* Wait at least 1 bit interwal */
0179   rtems_task_wake_after(RTEMS_MILLISECONDS_TO_TICKS(1000 / rate));
0180 }
0181 
0182 /*
0183  * sh4uart_reset --
0184  *     This function perform the hardware initialization of SH-4
0185  *     on-chip UART controller using parameters
0186  *     filled by the sh4uart_init function.
0187  *
0188  * PARAMETERS:
0189  *     uart - pointer to UART channel descriptor structure
0190  *
0191  * RETURNS:
0192  *     RTEMS_SUCCESSFUL if channel is initialized successfully, error
0193  *     code in other case
0194  */
0195 rtems_status_code
0196 sh4uart_reset(sh4uart *uart)
0197 {
0198   register int chn;
0199   register int int_driven;
0200   rtems_status_code rc;
0201   uint16_t tmp;
0202 
0203   if (uart == NULL)
0204     return RTEMS_INVALID_ADDRESS;
0205 
0206   chn = uart->chn;
0207   int_driven = uart->int_driven;
0208 
0209   if ( chn == 1 ) {
0210     volatile uint8_t *scr1 = (volatile uint8_t *)SH7750_SCSCR1;
0211     volatile uint8_t *smr1 = (volatile uint8_t *)SH7750_SCSMR1;
0212     *scr1 = 0x0;       /* Is set properly at the end of this function */
0213     *smr1 = 0x0;       /* 8-bit, non-parity, 1 stop bit, pf/1 clock */
0214   } else {
0215     volatile uint16_t *scr2 = (volatile uint16_t *)SH7750_SCSCR2;
0216     volatile uint16_t *smr2 = (volatile uint16_t *)SH7750_SCSMR2;
0217     *scr2 = 0x0;       /* Is set properly at the end of this function */
0218     *smr2 = 0x0;       /* 8-bit, non-parity, 1 stop bit, pf/1 clock */
0219   }
0220 
0221   if (chn == SH4_SCIF)
0222     SCFCR2 = SH7750_SCFCR2_TFRST | SH7750_SCFCR2_RFRST |
0223              SH7750_SCFCR2_RTRG_1 | SH7750_SCFCR2_TTRG_4;
0224 
0225   if (chn == SH4_SCI)
0226     SCSPTR1 = int_driven ? 0x0 : SH7750_SCSPTR1_EIO;
0227   else
0228     SCSPTR2 = SH7750_SCSPTR2_RTSDT;
0229 
0230   if (int_driven) {
0231     uint16_t   ipr;
0232 
0233     if (chn == SH4_SCI) {
0234       ipr = IPRB;
0235       ipr &= ~SH7750_IPRB_SCI1;
0236       ipr |= SH4_UART_INTERRUPT_LEVEL << SH7750_IPRB_SCI1_S;
0237       IPRB = ipr;
0238 
0239       rc = rtems_interrupt_catch(sh4uart1_interrupt_transmit,
0240                                  SH7750_EVT_TO_NUM(SH7750_EVT_SCI_TXI),
0241                                  &uart->old_handler_transmit);
0242       if (rc != RTEMS_SUCCESSFUL)
0243         return rc;
0244 
0245       rc = rtems_interrupt_catch(sh4uart1_interrupt_receive,
0246                                  SH7750_EVT_TO_NUM(SH7750_EVT_SCI_RXI),
0247                                  &uart->old_handler_receive);
0248       if (rc != RTEMS_SUCCESSFUL)
0249         return rc;
0250     } else {
0251       ipr = IPRC;
0252       ipr &= ~SH7750_IPRC_SCIF;
0253       ipr |= SH4_UART_INTERRUPT_LEVEL << SH7750_IPRC_SCIF_S;
0254       IPRC = ipr;
0255 
0256       rc = rtems_interrupt_catch(sh4uart2_interrupt_transmit,
0257                                  SH7750_EVT_TO_NUM(SH7750_EVT_SCIF_TXI),
0258                                  &uart->old_handler_transmit);
0259       if (rc != RTEMS_SUCCESSFUL)
0260         return rc;
0261       rc = rtems_interrupt_catch(sh4uart2_interrupt_receive,
0262                                  SH7750_EVT_TO_NUM(SH7750_EVT_SCIF_RXI),
0263                                  &uart->old_handler_receive);
0264       if (rc != RTEMS_SUCCESSFUL)
0265         return rc;
0266     }
0267     uart->tx_buf = NULL;
0268     uart->tx_ptr = uart->tx_buf_len = 0;
0269   }
0270 
0271   sh4uart_set_baudrate(uart, B38400); /* debug defaults (unfortunately,
0272                                          it is differ to termios default */
0273 
0274   tmp = SH7750_SCSCR_TE | SH7750_SCSCR_RE |
0275           (chn == SH4_SCI ? 0x0 : SH7750_SCSCR2_REIE) |
0276           (int_driven ? (SH7750_SCSCR_RIE | SH7750_SCSCR_TIE) : 0x0);
0277 
0278   if ( chn == 1 ) {
0279     volatile uint8_t *scr = (volatile uint8_t *)SH7750_SCSCR1;
0280     *scr = tmp;
0281   } else {
0282     volatile uint16_t *scr = (volatile uint16_t *)SH7750_SCSCR2;
0283     *scr = tmp;
0284   }
0285 
0286   return RTEMS_SUCCESSFUL;
0287 }
0288 
0289 /*
0290  * sh4uart_disable --
0291  *     This function disable the operations on SH-4 UART controller
0292  *
0293  * PARAMETERS:
0294  *     uart - pointer to UART channel descriptor structure
0295  *     disable_port - disable receive and transmit on the port
0296  *
0297  * RETURNS:
0298  *     RTEMS_SUCCESSFUL if UART closed successfuly, or error code in
0299  *     other case
0300  */
0301 rtems_status_code
0302 sh4uart_disable(sh4uart *uart, int disable_port)
0303 {
0304   rtems_status_code rc;
0305 
0306   if (disable_port) {
0307     if ( uart->chn == 1 ) {
0308       volatile uint8_t *scr = (volatile uint8_t *)SH7750_SCSCR1;
0309       *scr &= ~(SH7750_SCSCR_TE | SH7750_SCSCR_RE);
0310     } else {
0311       volatile uint16_t *scr = (volatile uint16_t *)SH7750_SCSCR2;
0312       *scr &= ~(SH7750_SCSCR_TE | SH7750_SCSCR_RE);
0313     }
0314   }
0315 
0316   if (uart->int_driven) {
0317     rc = rtems_interrupt_catch(uart->old_handler_transmit,
0318            uart->chn == SH4_SCI ?  SH7750_EVT_SCI_TXI : SH7750_EVT_SCIF_TXI,
0319            NULL);
0320     if (rc != RTEMS_SUCCESSFUL)
0321       return rc;
0322     rc = rtems_interrupt_catch(uart->old_handler_receive,
0323            uart->chn == SH4_SCI ?  SH7750_EVT_SCI_RXI : SH7750_EVT_SCIF_RXI,
0324            NULL);
0325     if (rc != RTEMS_SUCCESSFUL)
0326       return rc;
0327   }
0328 
0329   return RTEMS_SUCCESSFUL;
0330 }
0331 
0332 /*
0333  * sh4uart_set_attributes --
0334  *     This function parse the termios attributes structure and perform
0335  *     the appropriate settings in hardware.
0336  *
0337  * PARAMETERS:
0338  *     uart - pointer to the UART descriptor structure
0339  *     t - pointer to termios parameters
0340  *
0341  * RETURNS:
0342  *     RTEMS_SUCCESSFUL
0343  */
0344 rtems_status_code
0345 sh4uart_set_attributes(sh4uart *uart, const struct termios *t)
0346 {
0347   int level;
0348   speed_t baud;
0349   uint16_t   smr;
0350 
0351   smr = (uint16_t)(*(uint8_t*)SH7750_SCSMR(uart->chn));
0352 
0353   baud = cfgetospeed(t);
0354 
0355   /* Set flow control XXX*/
0356   if ((t->c_cflag & CRTSCTS) != 0) {
0357   }
0358 
0359   /* Set character size -- only 7 or 8 bit */
0360   switch (t->c_cflag & CSIZE) {
0361     case CS5:
0362     case CS6:
0363     case CS7: smr |= SH7750_SCSMR_CHR_7; break;
0364     case CS8: smr &= ~SH7750_SCSMR_CHR_7; break;
0365   }
0366 
0367     /* Set number of stop bits */
0368   if ((t->c_cflag & CSTOPB) != 0)
0369     smr |= SH7750_SCSMR_STOP_2;
0370   else
0371     smr &= ~SH7750_SCSMR_STOP_2;
0372 
0373   /* Set parity mode */
0374   if ((t->c_cflag & PARENB) != 0) {
0375     smr |= SH7750_SCSMR_PE;
0376     if ((t->c_cflag & PARODD) != 0)
0377        smr |= SH7750_SCSMR_PM_ODD;
0378     else
0379        smr &= ~SH7750_SCSMR_PM_ODD;
0380   } else
0381     smr &= ~SH7750_SCSMR_PE;
0382 
0383   rtems_interrupt_disable(level);
0384   /* wait untill all data is transmitted */
0385   /* XXX JOEL says this is broken -- interrupts are OFF so NO ticks  */
0386   rtems_task_wake_after(RTEMS_MILLISECONDS_TO_TICKS(100));
0387 
0388   if ( uart->chn == 1 ) {
0389     volatile uint8_t *scrP = (volatile uint8_t *)SH7750_SCSCR1;
0390     volatile uint8_t *smrP = (volatile uint8_t *)SH7750_SCSMR1;
0391 
0392     *scrP &= ~(SH7750_SCSCR_TE | SH7750_SCSCR_RE); /* disable operations */
0393     sh4uart_set_baudrate(uart, baud);
0394     *smrP = (uint8_t)smr;
0395     *scrP |= SH7750_SCSCR_TE | SH7750_SCSCR_RE;    /* enable operations */
0396   } else {
0397     volatile uint16_t *scrP = (volatile uint16_t *)SH7750_SCSCR2;
0398     volatile uint16_t *smrP = (volatile uint16_t *)SH7750_SCSMR2;
0399 
0400     *scrP &= ~(SH7750_SCSCR_TE | SH7750_SCSCR_RE); /* disable operations */
0401     sh4uart_set_baudrate(uart, baud);
0402     *smrP = (uint8_t)smr;
0403     *scrP |= SH7750_SCSCR_TE | SH7750_SCSCR_RE;    /* enable operations */
0404   }
0405 
0406   rtems_interrupt_enable(level);
0407 
0408   return RTEMS_SUCCESSFUL;
0409 }
0410 
0411 /*
0412  * sh4uart_handle_error --
0413  *     Perfoms error (Overrun, Framing & Parity) handling
0414  *
0415  * PARAMETERS:
0416  *     uart - pointer to UART descriptor structure
0417  *
0418  * RETURNS:
0419  *     nothing
0420  */
0421 static void
0422 sh4uart_handle_error(sh4uart *uart)
0423 {
0424   if (uart->chn == SH4_SCI) {
0425     volatile uint8_t *scr = (volatile uint8_t *)SH7750_SCSCR1;
0426     *scr &= ~(SH7750_SCSSR1_ORER | SH7750_SCSSR1_FER | SH7750_SCSSR1_PER);
0427   } else {
0428     volatile uint16_t *scr = (volatile uint16_t *)SH7750_SCSCR2;
0429     *scr &= ~(SH7750_SCSSR2_ER | SH7750_SCSSR2_BRK | SH7750_SCSSR2_FER);
0430     *scr &= ~(SH7750_SCLSR2_ORER);
0431   }
0432 }
0433 
0434 /*
0435  * sh4uart_poll_read --
0436  *     This function tried to read character from SH-4 UART and perform
0437  *     error handling. When parity or framing error occured, return
0438  *     value dependent on termios input mode flags:
0439  *         - received character, if IGNPAR == 1
0440  *         - 0, if IGNPAR == 0 and PARMRK == 0
0441  *         - 0xff and 0x00 on next poll_read invocation, if IGNPAR == 0 and
0442  *           PARMRK == 1
0443  *
0444  * PARAMETERS:
0445  *     uart - pointer to UART descriptor structure
0446  *
0447  * RETURNS:
0448  *     code of received character or -1 if no characters received.
0449  */
0450 int
0451 sh4uart_poll_read(sh4uart *uart)
0452 {
0453   int chn = uart->chn;
0454   int parity_error = 0;
0455   int break_occured = 0;
0456   int ch;
0457 
0458   if (uart->parerr_mark_flag == true) {
0459     uart->parerr_mark_flag = false;
0460     return 0;
0461   }
0462 
0463   if (chn == SH4_SCI) {
0464     if ((SCSSR1 & (SH7750_SCSSR1_PER | SH7750_SCSSR1_FER |
0465                  SH7750_SCSSR1_ORER)) != 0) {
0466       if (SCSSR1 & (SH7750_SCSSR1_PER | SH7750_SCSSR1_FER))
0467         parity_error = 1;
0468       sh4uart_handle_error(uart);
0469     }
0470     if ((SCSSR1 & SH7750_SCSSR1_RDRF) == 0)
0471       return -1;
0472   } else {
0473     if ((SCSSR2 & (SH7750_SCSSR2_ER | SH7750_SCSSR2_DR |
0474                  SH7750_SCSSR2_BRK)) != 0 ||
0475             (SCLSR2 & SH7750_SCLSR2_ORER) != 0) {
0476       if (SCSSR2 & (SH7750_SCSSR1_PER | SH7750_SCSSR1_FER))
0477         parity_error = 1;
0478       if (SCSSR2 & SH7750_SCSSR2_BRK)
0479         break_occured = 1;
0480       sh4uart_handle_error(uart);
0481     }
0482     if ((SCSSR2 & SH7750_SCSSR2_RDF) == 0)
0483       return -1;
0484   }
0485 
0486   if (parity_error && !(uart->c_iflag & IGNPAR)) {
0487     if (uart->c_iflag & PARMRK) {
0488       uart->parerr_mark_flag = true;
0489       return 0xff;
0490     } else
0491       return 0;
0492   }
0493 
0494   if (break_occured && !(uart->c_iflag & BRKINT)) {
0495     if (uart->c_iflag & IGNBRK)
0496       return 0;
0497     else
0498       return 0;   /* XXX -- SIGINT */
0499   }
0500 
0501   ch = SCRDR(chn);
0502 
0503   if (uart->chn == SH4_SCI) {
0504     volatile uint8_t *scr = (volatile uint8_t *)SH7750_SCSCR1;
0505     *scr &= ~SH7750_SCSSR1_RDRF;
0506   } else {
0507     volatile uint16_t *scr = (volatile uint16_t *)SH7750_SCSCR2;
0508     *scr &= ~SH7750_SCSSR2_RDF;
0509   }
0510 
0511   return ch;
0512 }
0513 
0514 /*
0515  * sh4uart_poll_write --
0516  *     This function transmit buffer byte-by-byte in polling mode.
0517  *
0518  * PARAMETERS:
0519  *     uart - pointer to the UART descriptor structure
0520  *     buf - pointer to transmit buffer
0521  *     len - transmit buffer length
0522  *
0523  * RETURNS:
0524  *     0
0525  */
0526 int
0527 sh4uart_poll_write(sh4uart *uart, const char *buf, int len)
0528 {
0529   volatile uint8_t *ssr1 = (volatile uint8_t *)SH7750_SCSSR1;
0530   volatile uint16_t *ssr2 = (volatile uint16_t *)SH7750_SCSSR2;
0531 
0532   while (len) {
0533     if (uart->chn == SH4_SCI) {
0534       while ((SCSSR1 & SH7750_SCSSR1_TDRE) != 0) {
0535           SCTDR1 = *buf++;
0536           len--;
0537           *ssr1 &= ~SH7750_SCSSR1_TDRE;
0538       }
0539     } else {
0540       while ((SCSSR2 & SH7750_SCSSR2_TDFE) != 0) {
0541         int i;
0542         for (i = 0;
0543                 i < 16 - TRANSMIT_TRIGGER_VALUE(SCFCR2 &
0544                     SH7750_SCFCR2_TTRG);
0545                 i++) {
0546             SCTDR2 = *buf++;
0547             len--;
0548         }
0549         while ((SCSSR2 & SH7750_SCSSR2_TDFE) == 0 ||
0550                 (SCSSR2 & SH7750_SCSSR2_TEND) == 0);
0551         *ssr2 &= ~(SH7750_SCSSR1_TDRE | SH7750_SCSSR2_TEND);
0552       }
0553     }
0554   }
0555   return 0;
0556 }
0557 
0558 /**********************************
0559  * Functions to handle interrupts *
0560  **********************************/
0561 /* sh4uart1_interrupt_receive --
0562  *     UART interrupt handler routine -- SCI
0563  *     Receiving data
0564  *
0565  * PARAMETERS:
0566  *     vec - interrupt vector number
0567  *
0568  * RETURNS:
0569  *     none
0570  */
0571 static rtems_isr
0572 sh4uart1_interrupt_receive(rtems_vector_number vec)
0573 {
0574   register int bp = 0;
0575   char buf[32];
0576   volatile uint8_t *ssr1 = (volatile uint8_t *)SH7750_SCSSR1;
0577 
0578 
0579   /* Find UART descriptor from vector number */
0580   sh4uart *uart = &sh4_uarts[0];
0581 
0582   while (1) {
0583     if ((bp < sizeof(buf) - 1) && ((SCSSR1 & SH7750_SCSSR1_RDRF) != 0)) {
0584       /* Receive character and handle frame/parity errors */
0585       if ((SCSSR1 & (SH7750_SCSSR1_PER | SH7750_SCSSR1_FER |
0586                       SH7750_SCSSR1_ORER)) != 0) {
0587         if (SCSSR1 & (SH7750_SCSSR1_PER | SH7750_SCSSR1_FER)) {
0588             if (!(uart->c_iflag & IGNPAR)) {
0589               if (uart->c_iflag & PARMRK) {
0590                 buf[bp++] = 0xff;
0591                 buf[bp++] = 0x00;
0592               } else
0593                 buf[bp++] = 0x00;
0594             } else
0595               buf[bp++] = SCRDR1;
0596           }
0597           sh4uart_handle_error(uart);
0598       } else
0599           buf[bp++] = SCRDR1;
0600       *ssr1 &= ~SH7750_SCSSR1_RDRF;
0601     } else {
0602       if (bp != 0)
0603         rtems_termios_enqueue_raw_characters(uart->tty, buf, bp);
0604       break;
0605     }
0606   }
0607 }
0608 
0609 /* sh4uart2_interrupt_receive --
0610  *     UART interrupt handler routine -- SCIF
0611  *     Receiving data
0612  *
0613  * PARAMETERS:
0614  *     vec - interrupt vector number
0615  *
0616  * RETURNS:
0617  *     none
0618  */
0619 static rtems_isr
0620 sh4uart2_interrupt_receive(rtems_vector_number vec)
0621 {
0622   register int bp = 0;
0623   char buf[32];
0624   volatile uint16_t *ssr2 = (volatile uint16_t *)SH7750_SCSSR2;
0625 
0626 
0627   /* Find UART descriptor from vector number */
0628   sh4uart *uart = &sh4_uarts[1];
0629 
0630   while (1) {
0631     if ((bp < sizeof(buf) - 1) && ((SCSSR2 & SH7750_SCSSR2_RDF) != 0)) {
0632       if ((SCSSR2 & (SH7750_SCSSR2_ER | SH7750_SCSSR2_DR |
0633                       SH7750_SCSSR2_BRK)) != 0 ||
0634               (SH7750_SCLSR2 & SH7750_SCLSR2_ORER) != 0) {
0635         if (SCSSR2 & SH7750_SCSSR2_ER) {
0636           if (!(uart->c_iflag & IGNPAR)) {
0637             if (uart->c_iflag & PARMRK) {
0638               buf[bp++] = 0xff;
0639               buf[bp++] = 0x00;
0640             } else
0641               buf[bp++] = 0x00;
0642           } else
0643               buf[bp++] = SCRDR1;
0644         }
0645 
0646         if (SCSSR2 & SH7750_SCSSR2_BRK) {
0647           if (uart->c_iflag & IGNBRK)
0648             buf[bp++] = 0x00;
0649           else
0650             buf[bp++] = 0x00;   /* XXX -- SIGINT */
0651         }
0652 
0653         sh4uart_handle_error(uart);
0654       } else
0655         buf[bp++] = SCRDR1;
0656       *ssr2 &= ~SH7750_SCSSR2_RDF;
0657     } else {
0658       if (bp != 0)
0659         rtems_termios_enqueue_raw_characters(uart->tty, buf, bp);
0660       break;
0661     }
0662   }
0663 }
0664 
0665 
0666 /* sh4uart1_interrupt_transmit --
0667  *     UART interrupt handler routine -- SCI
0668  *     It continues transmit data when old part of data is transmitted
0669  *
0670  * PARAMETERS:
0671  *     vec - interrupt vector number
0672  *
0673  * RETURNS:
0674  *     none
0675  */
0676 static rtems_isr
0677 sh4uart1_interrupt_transmit(rtems_vector_number vec)
0678 {
0679   volatile uint8_t *scr1 = (volatile uint8_t *)SH7750_SCSCR1;
0680   volatile uint8_t *ssr1 = (volatile uint8_t *)SH7750_SCSSR1;
0681 
0682   /* Find UART descriptor from vector number */
0683   sh4uart *uart = &sh4_uarts[0];
0684 
0685   if (uart->tx_buf != NULL && uart->tx_ptr < uart->tx_buf_len) {
0686     while ((SCSSR1 & SH7750_SCSSR1_TDRE) != 0 &&
0687             uart->tx_ptr < uart->tx_buf_len) {
0688         SCTDR1 = uart->tx_buf[uart->tx_ptr++];
0689         *ssr1 &= ~SH7750_SCSSR1_TDRE;
0690     }
0691   } else {
0692     register int dequeue = uart->tx_buf_len;
0693 
0694     uart->tx_buf = NULL;
0695     uart->tx_ptr = uart->tx_buf_len = 0;
0696 
0697     /* Disable interrupts while we do not have any data to transmit */
0698     *scr1 &= ~SH7750_SCSCR_TIE;
0699 
0700     rtems_termios_dequeue_characters(uart->tty, dequeue);
0701   }
0702 }
0703 
0704 /* sh4uart2_interrupt_transmit --
0705  *     UART interrupt handler routine -- SCI
0706  *     It continues transmit data when old part of data is transmitted
0707  *
0708  * PARAMETERS:
0709  *     vec - interrupt vector number
0710  *
0711  * RETURNS:
0712  *     none
0713  */
0714 static rtems_isr
0715 sh4uart2_interrupt_transmit(rtems_vector_number vec)
0716 {
0717   volatile uint8_t *ssr1 = (volatile uint8_t *)SH7750_SCSSR1;
0718   volatile uint16_t *scr2 = (volatile uint16_t *)SH7750_SCSCR2;
0719 
0720   /* Find UART descriptor from vector number */
0721   sh4uart *uart = &sh4_uarts[1];
0722 
0723   if (uart->tx_buf != NULL && uart->tx_ptr < uart->tx_buf_len) {
0724     while ((SCSSR2 & SH7750_SCSSR2_TDFE) != 0) {
0725         int i;
0726         for (i = 0;
0727              i < 16 - TRANSMIT_TRIGGER_VALUE(SCFCR2 & SH7750_SCFCR2_TTRG);
0728              i++)
0729           SCTDR2 = uart->tx_buf[uart->tx_ptr++];
0730         while ((SCSSR1 & SH7750_SCSSR1_TDRE) == 0 ||
0731                 (SCSSR1 & SH7750_SCSSR1_TEND) == 0);
0732         *ssr1 &= ~(SH7750_SCSSR1_TDRE | SH7750_SCSSR2_TEND);
0733     }
0734   } else {
0735     register int dequeue = uart->tx_buf_len;
0736 
0737     uart->tx_buf = NULL;
0738     uart->tx_ptr = uart->tx_buf_len = 0;
0739 
0740     /* Disable interrupts while we do not have any data to transmit */
0741     *scr2 &= ~SH7750_SCSCR_TIE;
0742 
0743     rtems_termios_dequeue_characters(uart->tty, dequeue);
0744   }
0745 }
0746 
0747 /* sh4uart_interrupt_write --
0748  *     This function initiate transmitting of the buffer in interrupt mode.
0749  *
0750  * PARAMETERS:
0751  *     uart - pointer to the UART descriptor structure
0752  *     buf - pointer to transmit buffer
0753  *     len - transmit buffer length
0754  *
0755  * RETURNS:
0756  *     0
0757  */
0758 rtems_status_code
0759 sh4uart_interrupt_write(sh4uart *uart, const char *buf, int len)
0760 {
0761   if (len > 0) {
0762     volatile uint8_t  *scr1 = (volatile uint8_t *)SH7750_SCSCR1;
0763     volatile uint16_t *scr2 = (volatile uint16_t *)SH7750_SCSCR2;
0764 
0765     while ((SCSSR1 & SH7750_SCSSR1_TEND) == 0);
0766 
0767     uart->tx_buf = buf;
0768     uart->tx_buf_len = len;
0769     uart->tx_ptr = 0;
0770 
0771     if (uart->chn == SH4_SCI)
0772       *scr1 |= SH7750_SCSCR_TIE;
0773     else
0774       *scr2 |= SH7750_SCSCR_TIE;
0775   }
0776 
0777   return RTEMS_SUCCESSFUL;
0778 }
0779 
0780 /* sh4uart_stop_remote_tx --
0781  *     This function stop data flow from remote device.
0782  *
0783  * PARAMETERS:
0784  *     uart - pointer to the UART descriptor structure
0785  *
0786  * RETURNS:
0787  *     RTEMS_SUCCESSFUL
0788  */
0789 rtems_status_code
0790 sh4uart_stop_remote_tx(sh4uart *uart)
0791 {
0792   if ( uart->chn == 1 ) {
0793     volatile uint8_t *scr = (volatile uint8_t *)SH7750_SCSCR1;
0794     *scr &= ~(SH7750_SCSCR_RIE | SH7750_SCSCR_RE);
0795   } else {
0796     volatile uint16_t *scr = (volatile uint16_t *)SH7750_SCSCR2;
0797     *scr &= ~(SH7750_SCSCR_RIE | SH7750_SCSCR_RE);
0798   }
0799 
0800   return RTEMS_SUCCESSFUL;
0801 }
0802 
0803 /* sh4uart_start_remote_tx --
0804  *     This function resume data flow from remote device.
0805  *
0806  * PARAMETERS:
0807  *     uart - pointer to the UART descriptor structure
0808  *
0809  * RETURNS:
0810  *     RTEMS_SUCCESSFUL
0811  */
0812 rtems_status_code
0813 sh4uart_start_remote_tx(sh4uart *uart)
0814 {
0815   if ( uart->chn == 1 ) {
0816     volatile uint8_t *scr = (volatile uint8_t *)SH7750_SCSCR1;
0817     *scr |= SH7750_SCSCR_RIE | SH7750_SCSCR_RE;
0818   } else {
0819     volatile uint16_t *scr = (volatile uint16_t *)SH7750_SCSCR2;
0820     *scr |= SH7750_SCSCR_RIE | SH7750_SCSCR_RE;
0821   }
0822 
0823   return RTEMS_SUCCESSFUL;
0824 }
0825 
0826 #ifdef SH4_WITH_IPL
0827 /*********************************
0828  * Functions for SH-IPL gdb stub *
0829  *********************************/
0830 
0831 /*
0832  * ipl_finish --
0833  *     Says gdb that program finished to get out from it.
0834  */
0835 extern void ipl_finish(void);
0836 __asm__ (
0837 "   .global _ipl_finish\n"
0838 "_ipl_finish:\n"
0839 "   mov.l   __ipl_finish_value, r0\n"
0840 "   trapa   #0x3f\n"
0841 "   nop\n"
0842 "   rts\n"
0843 "   nop\n"
0844 "   .align 4\n"
0845 "__ipl_finish_value:\n"
0846 "   .long   255"
0847 );
0848 
0849 extern int ipl_serial_input(int poll_count);
0850 __asm__ (
0851 "    .global _ipl_serial_input\n"
0852 "_ipl_serial_input:\n"
0853 "    mov  #1,r0\n"
0854 "    trapa #0x3f\n"
0855 "    nop\n"
0856 "    rts\n"
0857 "    nop\n");
0858 
0859 extern void ipl_serial_output(const char *buf, int len);
0860 __asm__ (
0861 "    .global _ipl_serial_output\n"
0862 "_ipl_serial_output:\n"
0863 "    mov  #0,r0\n"
0864 "    trapa #0x3f\n"
0865 "    nop\n"
0866 "    rts\n"
0867 "    nop\n");
0868 
0869 /* ipl_console_poll_read --
0870  *     poll read operation for simulator console through ipl mechanism.
0871  *
0872  * PARAMETERS:
0873  *     minor - minor device number
0874  *
0875  * RETURNS:
0876  *     character code red from UART, or -1 if there is no characters
0877  *     available
0878  */
0879 int
0880 ipl_console_poll_read(int minor)
0881 {
0882     unsigned char buf;
0883     buf = ipl_serial_input(0x100000);
0884     return buf;
0885 }
0886 
0887 /* ipl_console_poll_write --
0888  *     wrapper for polling mode write function
0889  *
0890  * PARAMETERS:
0891  *     minor - minor device number
0892  *     buf - output buffer
0893  *     len - output buffer length
0894  *
0895  * RETURNS:
0896  *     result code (0)
0897  */
0898 int
0899 ipl_console_poll_write(int minor, const char *buf, int len)
0900 {
0901   int c;
0902   while (len > 0) {
0903     c = (len < 64 ? len : 64);
0904     ipl_serial_output(buf, c);
0905     len -= c;
0906     buf += c;
0907   }
0908   return 0;
0909 }
0910 #endif