File indexing completed on 2025-05-11 08:23:47
0001
0002
0003
0004
0005
0006
0007 #include <stdio.h>
0008 #include <fcntl.h>
0009 #include <termios.h>
0010 #include <malloc.h>
0011
0012 #include <rtems/libio.h>
0013 #include <rtems/termiostypes.h>
0014 #include <rtems/console.h>
0015 #include <rtems/bspIo.h>
0016
0017 #include <bsp.h>
0018
0019 #define UART_INTC0_IRQ_VECTOR(x) (64+26+(x))
0020
0021 #define MCF_UART_USR_ERROR ( MCF_UART_USR_RB | \
0022 MCF_UART_USR_FE | \
0023 MCF_UART_USR_PE | \
0024 MCF_UART_USR_OE )
0025
0026 static ssize_t IntUartPollWrite(int minor, const char *buf, size_t len);
0027 static ssize_t IntUartInterruptWrite(int minor, const char *buf, size_t len);
0028
0029 static void _BSP_null_char(char c)
0030 {
0031 int level;
0032
0033 rtems_interrupt_disable(level);
0034 while ((MCF_UART_USR(CONSOLE_PORT) & MCF_UART_USR_TXRDY) == 0)
0035 continue;
0036 MCF_UART_UTB(CONSOLE_PORT) = c;
0037 while ((MCF_UART_USR(CONSOLE_PORT) & MCF_UART_USR_TXRDY) == 0)
0038 continue;
0039 rtems_interrupt_enable(level);
0040 }
0041
0042 BSP_output_char_function_type BSP_output_char = _BSP_null_char;
0043 BSP_polling_getchar_function_type BSP_poll_char = NULL;
0044
0045 #define MAX_UART_INFO 3
0046 #define RX_BUFFER_SIZE 512
0047
0048 struct IntUartInfoStruct
0049 {
0050 int iomode;
0051 volatile int uimr;
0052 int baud;
0053 int databits;
0054 int parity;
0055 int stopbits;
0056 int hwflow;
0057 int rx_in;
0058 int rx_out;
0059 char rx_buffer[RX_BUFFER_SIZE];
0060 void *ttyp;
0061 };
0062
0063 struct IntUartInfoStruct IntUartInfo[MAX_UART_INFO];
0064
0065
0066
0067
0068
0069
0070 static void
0071 IntUartSet(int minor, int baud, int databits, int parity, int stopbits,
0072 int hwflow)
0073 {
0074 int divisor;
0075 uint32_t clock_speed;
0076 uint8_t umr1 = 0;
0077 uint8_t umr2 = 0;
0078 struct IntUartInfoStruct *info = &IntUartInfo[minor];
0079 int level;
0080
0081 rtems_interrupt_disable(level);
0082
0083
0084 MCF_UART_UIMR(minor) = 0;
0085 MCF_UART_UOP0(minor) = 1;
0086 MCF_UART_UCR(minor) = (MCF_UART_UCR_TX_DISABLED | MCF_UART_UCR_RX_DISABLED);
0087
0088
0089 info->uimr = 0;
0090 info->baud = baud;
0091 info->databits = databits;
0092 info->parity = parity;
0093 info->stopbits = stopbits;
0094 info->hwflow = hwflow;
0095
0096 clock_speed = bsp_get_BUS_clock_speed();
0097
0098 divisor = ((clock_speed) / (32 * baud));
0099 if (divisor < 2)
0100 divisor = 2;
0101
0102
0103 if (hwflow) {
0104
0105 umr1 |= MCF_UART_UMR_RXRTS;
0106 umr2 |= MCF_UART_UMR_TXCTS;
0107 }
0108
0109
0110 umr1 |= (parity | databits);
0111 umr2 |= (stopbits);
0112
0113
0114 MCF_UART_UCR(minor) = MCF_UART_UCR_RESET_ERROR;
0115 MCF_UART_UCR(minor) = MCF_UART_UCR_RESET_RX;
0116 MCF_UART_UCR(minor) = MCF_UART_UCR_RESET_TX;
0117
0118
0119 MCF_UART_UCR(minor) = MCF_UART_UCR_RESET_MR;
0120 MCF_UART_UMR(minor) = umr1;
0121 MCF_UART_UMR(minor) = umr2;
0122
0123
0124 MCF_UART_UCSR(minor) =
0125 (MCF_UART_UCSR_RCS_SYS_CLK | MCF_UART_UCSR_TCS_SYS_CLK);
0126 MCF_UART_UBG1(minor) = (divisor & 0xff00) >> 8;
0127 MCF_UART_UBG2(minor) = (divisor & 0x00ff);
0128
0129
0130 MCF_UART_UCR(minor) = (MCF_UART_UCR_TX_ENABLED | MCF_UART_UCR_RX_ENABLED);
0131
0132
0133 if (info->iomode != TERMIOS_POLLED) {
0134
0135 info->uimr |= MCF_UART_UIMR_RXRDY_FU;
0136 MCF_UART_UIMR(minor) = info->uimr;
0137 }
0138
0139
0140 if (hwflow) {
0141
0142 MCF_UART_UOP1(minor) = 1;
0143 }
0144
0145 rtems_interrupt_enable(level);
0146
0147 }
0148
0149
0150
0151
0152
0153
0154
0155
0156
0157
0158 static int IntUartSetAttributes(int minor, const struct termios *t)
0159 {
0160
0161 int baud = (int) 19200;
0162 int databits = (int) MCF_UART_UMR_BC_8;
0163 int parity = (int) MCF_UART_UMR_PM_NONE;
0164 int stopbits = (int) MCF_UART_UMR_SB_STOP_BITS_1;
0165 int hwflow = (int) 0;
0166 struct IntUartInfoStruct *info = &IntUartInfo[minor];
0167
0168
0169 if (t != (const struct termios *) 0) {
0170
0171 baud = rtems_termios_baud_to_number(t->c_ospeed);
0172
0173
0174 switch (t->c_cflag & CSIZE) {
0175 case CS5:
0176 databits = (int) MCF_UART_UMR_BC_5;
0177 break;
0178 case CS6:
0179 databits = (int) MCF_UART_UMR_BC_6;
0180 break;
0181 case CS7:
0182 databits = (int) MCF_UART_UMR_BC_7;
0183 break;
0184 case CS8:
0185 databits = (int) MCF_UART_UMR_BC_8;
0186 break;
0187 }
0188
0189
0190 if (t->c_cflag & PARENB) {
0191 if (t->c_cflag & PARODD) {
0192
0193 parity = (int) MCF_UART_UMR_PM_ODD;
0194 } else {
0195
0196 parity = (int) MCF_UART_UMR_PM_EVEN;
0197 }
0198 }
0199
0200
0201 if (t->c_cflag & CSTOPB) {
0202
0203 stopbits = (int) MCF_UART_UMR_SB_STOP_BITS_2;
0204 }
0205
0206
0207 if (t->c_cflag & CRTSCTS) {
0208 hwflow = 1;
0209 }
0210 }
0211
0212
0213 if ((baud != info->baud) ||
0214 (databits != info->databits) ||
0215 (parity != info->parity) ||
0216 (stopbits != info->stopbits) || (hwflow != info->hwflow)) {
0217
0218
0219 IntUartSet(minor, baud, databits, parity, stopbits, hwflow);
0220 }
0221
0222 return (RTEMS_SUCCESSFUL);
0223
0224 }
0225
0226
0227
0228
0229
0230
0231
0232
0233 static rtems_isr IntUartInterruptHandler(rtems_vector_number v)
0234 {
0235 unsigned int chan = v - UART_INTC0_IRQ_VECTOR(0);
0236 struct IntUartInfoStruct *info = &IntUartInfo[chan];
0237
0238
0239 if (MCF_UART_UISR(chan) & MCF_UART_UISR_RXRDY_FU) {
0240
0241 while (MCF_UART_USR(chan) & MCF_UART_USR_RXRDY) {
0242
0243 if (MCF_UART_USR(chan) & MCF_UART_USR_ERROR) {
0244
0245 MCF_UART_UCR(chan) = MCF_UART_UCR_RESET_ERROR;
0246 }
0247
0248 info->rx_buffer[info->rx_in] = MCF_UART_URB(chan);
0249
0250
0251 info->rx_in++;
0252
0253 if (info->rx_in >= RX_BUFFER_SIZE) {
0254 info->rx_in = 0;
0255 }
0256 }
0257
0258 if (info->ttyp) {
0259
0260
0261 if (info->iomode == TERMIOS_TASK_DRIVEN) {
0262
0263 rtems_termios_rxirq_occured(info->ttyp);
0264 } else {
0265
0266 rtems_termios_enqueue_raw_characters(info->ttyp, info->rx_buffer,
0267 info->rx_in);
0268 info->rx_in = 0;
0269 }
0270 }
0271 }
0272
0273
0274 if ((info->uimr & MCF_UART_UIMR_TXRDY) &&
0275 (MCF_UART_UISR(chan) & MCF_UART_UISR_TXRDY)) {
0276
0277
0278 info->uimr &= ~MCF_UART_UIMR_TXRDY;
0279 MCF_UART_UIMR(chan) = info->uimr;
0280
0281
0282 if (info->ttyp)
0283 rtems_termios_dequeue_characters(info->ttyp, 1);
0284 }
0285 }
0286
0287
0288
0289
0290
0291
0292
0293
0294 static void IntUartInitialize(void)
0295 {
0296 unsigned int chan;
0297 struct IntUartInfoStruct *info;
0298 rtems_isr_entry old_handler;
0299 int level;
0300
0301 for (chan = 0; chan < MAX_UART_INFO; chan++) {
0302 info = &IntUartInfo[chan];
0303
0304 info->ttyp = NULL;
0305 info->rx_in = 0;
0306 info->rx_out = 0;
0307 info->baud = -1;
0308 info->databits = -1;
0309 info->parity = -1;
0310 info->stopbits = -1;
0311 info->hwflow = -1;
0312 info->iomode = TERMIOS_POLLED;
0313
0314 MCF_UART_UACR(chan) = 0;
0315 MCF_UART_UIMR(chan) = 0;
0316 if (info->iomode != TERMIOS_POLLED) {
0317 rtems_interrupt_catch(IntUartInterruptHandler,
0318 UART_INTC0_IRQ_VECTOR(chan), &old_handler);
0319 }
0320
0321
0322 IntUartSetAttributes(chan, NULL);
0323
0324
0325 rtems_interrupt_disable(level);
0326 switch (chan) {
0327 case 0:
0328 MCF_INTC0_ICR26 = MCF_INTC_ICR_IL(UART0_IRQ_LEVEL);
0329 MCF_INTC0_IMRL &= ~(MCF_INTC_IMRL_INT_MASK26);
0330 break;
0331
0332 case 1:
0333 MCF_INTC0_ICR27 = MCF_INTC_ICR_IL(UART1_IRQ_LEVEL);
0334 MCF_INTC0_IMRL &= ~(MCF_INTC_IMRL_INT_MASK27);
0335 break;
0336
0337 case 2:
0338 MCF_INTC0_ICR28 = MCF_INTC_ICR_IL(UART2_IRQ_LEVEL);
0339 MCF_INTC0_IMRL &= ~(MCF_INTC_IMRL_INT_MASK28);
0340 break;
0341 }
0342 rtems_interrupt_enable(level);
0343
0344 }
0345
0346 }
0347
0348
0349
0350
0351
0352
0353
0354
0355
0356 static ssize_t IntUartInterruptWrite(int minor, const char *buf, size_t len)
0357 {
0358 if (len > 0) {
0359
0360 MCF_UART_UTB(minor) = *buf;
0361
0362
0363 IntUartInfo[minor].uimr |= MCF_UART_UIMR_TXRDY;
0364 MCF_UART_UIMR(minor) = IntUartInfo[minor].uimr;
0365 }
0366
0367 return (0);
0368 }
0369
0370
0371
0372
0373
0374
0375 static int IntUartInterruptOpen(int major, int minor, void *arg)
0376 {
0377 struct IntUartInfoStruct *info = &IntUartInfo[minor];
0378
0379
0380 MCF_UART_UCR(minor) = (MCF_UART_UCR_TX_ENABLED | MCF_UART_UCR_RX_ENABLED);
0381
0382
0383 if (info->iomode != TERMIOS_POLLED) {
0384
0385 info->uimr |= MCF_UART_UIMR_RXRDY_FU;
0386 MCF_UART_UIMR(minor) = info->uimr;
0387 }
0388
0389
0390 if (info->hwflow) {
0391
0392 MCF_UART_UOP1(minor) = 1;
0393 }
0394
0395 return (0);
0396 }
0397
0398
0399
0400
0401
0402
0403 static int IntUartInterruptClose(int major, int minor, void *arg)
0404 {
0405 struct IntUartInfoStruct *info = &IntUartInfo[minor];
0406
0407
0408 MCF_UART_UIMR(minor) = 0;
0409 MCF_UART_UCR(minor) = (MCF_UART_UCR_TX_DISABLED | MCF_UART_UCR_RX_DISABLED);
0410
0411
0412 info->ttyp = NULL;
0413 info->uimr = 0;
0414 info->rx_in = 0;
0415 info->rx_out = 0;
0416
0417 return (0);
0418 }
0419
0420
0421
0422
0423
0424
0425
0426
0427 static int IntUartTaskRead(int minor)
0428 {
0429 char buffer[RX_BUFFER_SIZE];
0430 int count;
0431 int rx_in;
0432 int index = 0;
0433 struct IntUartInfoStruct *info = &IntUartInfo[minor];
0434
0435
0436 rx_in = info->rx_in;
0437 if (info->rx_out <= rx_in) {
0438 count = rx_in - info->rx_out;
0439 } else {
0440 count = (RX_BUFFER_SIZE - info->rx_out) + rx_in;
0441 }
0442
0443
0444 while ((index < count) && (index < RX_BUFFER_SIZE)) {
0445
0446 buffer[index] = info->rx_buffer[info->rx_out];
0447 index++;
0448
0449
0450 info->rx_out++;
0451 if (info->rx_out >= RX_BUFFER_SIZE) {
0452 info->rx_out = 0;
0453 }
0454 }
0455
0456
0457 if (count > 0) {
0458
0459 rtems_termios_enqueue_raw_characters(info->ttyp, buffer, count);
0460 }
0461
0462 return (EOF);
0463 }
0464
0465
0466
0467
0468
0469
0470
0471 static int IntUartPollRead(int minor)
0472 {
0473 if ((MCF_UART_USR(minor) & MCF_UART_USR_RXRDY) == 0)
0474 return (-1);
0475
0476 return (MCF_UART_URB(minor));
0477 }
0478
0479
0480
0481
0482
0483
0484
0485
0486 static ssize_t IntUartPollWrite(int minor, const char *buf, size_t len)
0487 {
0488 size_t retval = len;
0489
0490 while (len--) {
0491
0492 while ((MCF_UART_USR(minor) & MCF_UART_USR_TXRDY) == 0)
0493 continue;
0494
0495 MCF_UART_UTB(minor) = *buf++;
0496 }
0497 return retval;
0498 }
0499
0500
0501
0502
0503
0504
0505
0506 rtems_device_driver console_initialize(rtems_device_major_number major,
0507 rtems_device_minor_number minor,
0508 void *arg)
0509 {
0510 rtems_status_code status;
0511
0512
0513 rtems_termios_initialize();
0514
0515
0516 IntUartInfo[minor].iomode = TERMIOS_IRQ_DRIVEN;
0517 IntUartInitialize();
0518
0519
0520 status = rtems_io_register_name("/dev/console", major, CONSOLE_PORT);
0521 if (status != RTEMS_SUCCESSFUL) {
0522 rtems_fatal_error_occurred(status);
0523 }
0524
0525
0526 if (CONSOLE_PORT != 0) {
0527 status = rtems_io_register_name("/dev/tty00", major, 0);
0528 if (status != RTEMS_SUCCESSFUL) {
0529 rtems_fatal_error_occurred(status);
0530 }
0531 }
0532 if (CONSOLE_PORT != 1) {
0533 status = rtems_io_register_name("/dev/tty01", major, 1);
0534 if (status != RTEMS_SUCCESSFUL) {
0535 rtems_fatal_error_occurred(status);
0536 }
0537 }
0538
0539 return (RTEMS_SUCCESSFUL);
0540 }
0541
0542
0543
0544
0545
0546
0547
0548
0549
0550 rtems_device_driver console_open(rtems_device_major_number major,
0551 rtems_device_minor_number minor, void *arg)
0552 {
0553 rtems_status_code status = RTEMS_INVALID_NUMBER;
0554 rtems_libio_open_close_args_t *args = (rtems_libio_open_close_args_t *) arg;
0555 struct IntUartInfoStruct *info;
0556
0557 static const rtems_termios_callbacks IntUartPollCallbacks = {
0558 NULL,
0559 NULL,
0560 IntUartPollRead,
0561 IntUartPollWrite,
0562 IntUartSetAttributes,
0563 NULL,
0564 NULL,
0565 TERMIOS_POLLED
0566 };
0567 static const rtems_termios_callbacks IntUartIntrCallbacks = {
0568 IntUartInterruptOpen,
0569 IntUartInterruptClose,
0570 NULL,
0571 IntUartInterruptWrite,
0572 IntUartSetAttributes,
0573 NULL,
0574 NULL,
0575 TERMIOS_IRQ_DRIVEN
0576 };
0577
0578 static const rtems_termios_callbacks IntUartTaskCallbacks = {
0579 IntUartInterruptOpen,
0580 IntUartInterruptClose,
0581 IntUartTaskRead,
0582 IntUartInterruptWrite,
0583 IntUartSetAttributes,
0584 NULL,
0585 NULL,
0586 TERMIOS_TASK_DRIVEN
0587 };
0588
0589
0590 if ((minor >= 0) && (minor < MAX_UART_INFO)) {
0591 info = &IntUartInfo[minor];
0592 switch (info->iomode) {
0593 case TERMIOS_POLLED:
0594 status = rtems_termios_open(major, minor, arg, &IntUartPollCallbacks);
0595 break;
0596 case TERMIOS_IRQ_DRIVEN:
0597 status = rtems_termios_open(major, minor, arg, &IntUartIntrCallbacks);
0598 info->ttyp = args->iop->data1;
0599 break;
0600 case TERMIOS_TASK_DRIVEN:
0601 status = rtems_termios_open(major, minor, arg, &IntUartTaskCallbacks);
0602 info->ttyp = args->iop->data1;
0603 break;
0604 }
0605 }
0606
0607 if (status == RTEMS_SUCCESSFUL) {
0608
0609
0610
0611 struct termios term;
0612
0613 if (tcgetattr(STDIN_FILENO, &term) >= 0) {
0614 term.c_cflag &= ~(CSIZE);
0615 term.c_cflag |= CS8;
0616 term.c_ispeed = B19200;
0617 term.c_ospeed = B19200;
0618 tcsetattr(STDIN_FILENO, TCSANOW, &term);
0619 }
0620 }
0621
0622 return (status);
0623 }
0624
0625
0626
0627
0628
0629
0630 rtems_device_driver console_close(rtems_device_major_number major,
0631 rtems_device_minor_number minor, void *arg)
0632 {
0633 return (rtems_termios_close(arg));
0634 }
0635
0636
0637
0638
0639
0640
0641 rtems_device_driver console_read(rtems_device_major_number major,
0642 rtems_device_minor_number minor, void *arg)
0643 {
0644 return (rtems_termios_read(arg));
0645 }
0646
0647
0648
0649
0650
0651
0652 rtems_device_driver console_write(rtems_device_major_number major,
0653 rtems_device_minor_number minor, void *arg)
0654 {
0655 return (rtems_termios_write(arg));
0656 }
0657
0658
0659
0660
0661
0662
0663 rtems_device_driver console_control(rtems_device_major_number major,
0664 rtems_device_minor_number minor,
0665 void *arg)
0666 {
0667 return (rtems_termios_ioctl(arg));
0668 }