File indexing completed on 2025-05-11 08:24:01
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
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
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
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
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
0071
0072
0073
0074
0075
0076
0077
0078
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:
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:
0104 break;
0105 }
0106
0107 return Pph;
0108 }
0109
0110
0111
0112
0113
0114
0115
0116
0117
0118
0119
0120
0121
0122
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
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
0179 rtems_task_wake_after(RTEMS_MILLISECONDS_TO_TICKS(1000 / rate));
0180 }
0181
0182
0183
0184
0185
0186
0187
0188
0189
0190
0191
0192
0193
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;
0213 *smr1 = 0x0;
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;
0218 *smr2 = 0x0;
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);
0272
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
0291
0292
0293
0294
0295
0296
0297
0298
0299
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
0334
0335
0336
0337
0338
0339
0340
0341
0342
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
0356 if ((t->c_cflag & CRTSCTS) != 0) {
0357 }
0358
0359
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
0368 if ((t->c_cflag & CSTOPB) != 0)
0369 smr |= SH7750_SCSMR_STOP_2;
0370 else
0371 smr &= ~SH7750_SCSMR_STOP_2;
0372
0373
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
0385
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);
0393 sh4uart_set_baudrate(uart, baud);
0394 *smrP = (uint8_t)smr;
0395 *scrP |= SH7750_SCSCR_TE | SH7750_SCSCR_RE;
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);
0401 sh4uart_set_baudrate(uart, baud);
0402 *smrP = (uint8_t)smr;
0403 *scrP |= SH7750_SCSCR_TE | SH7750_SCSCR_RE;
0404 }
0405
0406 rtems_interrupt_enable(level);
0407
0408 return RTEMS_SUCCESSFUL;
0409 }
0410
0411
0412
0413
0414
0415
0416
0417
0418
0419
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
0436
0437
0438
0439
0440
0441
0442
0443
0444
0445
0446
0447
0448
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;
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
0516
0517
0518
0519
0520
0521
0522
0523
0524
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
0560
0561
0562
0563
0564
0565
0566
0567
0568
0569
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
0580 sh4uart *uart = &sh4_uarts[0];
0581
0582 while (1) {
0583 if ((bp < sizeof(buf) - 1) && ((SCSSR1 & SH7750_SCSSR1_RDRF) != 0)) {
0584
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
0610
0611
0612
0613
0614
0615
0616
0617
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
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;
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
0667
0668
0669
0670
0671
0672
0673
0674
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
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
0698 *scr1 &= ~SH7750_SCSCR_TIE;
0699
0700 rtems_termios_dequeue_characters(uart->tty, dequeue);
0701 }
0702 }
0703
0704
0705
0706
0707
0708
0709
0710
0711
0712
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
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
0741 *scr2 &= ~SH7750_SCSCR_TIE;
0742
0743 rtems_termios_dequeue_characters(uart->tty, dequeue);
0744 }
0745 }
0746
0747
0748
0749
0750
0751
0752
0753
0754
0755
0756
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
0781
0782
0783
0784
0785
0786
0787
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
0804
0805
0806
0807
0808
0809
0810
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
0829
0830
0831
0832
0833
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
0870
0871
0872
0873
0874
0875
0876
0877
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
0888
0889
0890
0891
0892
0893
0894
0895
0896
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