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