File indexing completed on 2025-05-11 08:24:05
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033 #include <stdlib.h>
0034
0035 #include <rtems.h>
0036 #include <rtems/libio.h>
0037 #include <rtems/ringbuf.h>
0038 #include <rtems/bspIo.h>
0039 #include <rtems/termiostypes.h>
0040
0041 #include <libchip/serial.h>
0042 #include <libchip/sersupp.h>
0043
0044 #include <bsp.h>
0045
0046 #include <libchip/ns16550_p.h>
0047 #include <libchip/ns16550.h>
0048
0049 #if defined(BSP_FEATURE_IRQ_EXTENSION)
0050 #include <bsp/irq.h>
0051 #elif defined(BSP_FEATURE_IRQ_LEGACY)
0052 #include <bsp/irq.h>
0053 #elif defined(__PPC__) || defined(__i386__)
0054 #include <bsp/irq.h>
0055 #define BSP_FEATURE_IRQ_LEGACY
0056 #ifdef BSP_SHARED_HANDLER_SUPPORT
0057 #define BSP_FEATURE_IRQ_LEGACY_SHARED_HANDLER_SUPPORT
0058 #endif
0059 #endif
0060
0061 typedef struct {
0062 uint8_t ucModemCtrl;
0063 int transmitFifoChars;
0064 } NS16550Context;
0065
0066
0067
0068
0069
0070 NS16550_STATIC void ns16550_init(int minor);
0071
0072 NS16550_STATIC int ns16550_open(
0073 int major,
0074 int minor,
0075 void * arg
0076 );
0077
0078 NS16550_STATIC int ns16550_close(
0079 int major,
0080 int minor,
0081 void * arg
0082 );
0083
0084 NS16550_STATIC void ns16550_write_polled(
0085 int minor,
0086 char cChar
0087 );
0088
0089 NS16550_STATIC int ns16550_assert_RTS(
0090 int minor
0091 );
0092
0093 NS16550_STATIC int ns16550_negate_RTS(
0094 int minor
0095 );
0096
0097 NS16550_STATIC int ns16550_assert_DTR(
0098 int minor
0099 );
0100
0101 NS16550_STATIC int ns16550_negate_DTR(
0102 int minor
0103 );
0104
0105 NS16550_STATIC void ns16550_initialize_interrupts(int minor);
0106
0107 NS16550_STATIC void ns16550_cleanup_interrupts(int minor);
0108
0109 NS16550_STATIC ssize_t ns16550_write_support_int(
0110 int minor,
0111 const char *buf,
0112 size_t len
0113 );
0114
0115 NS16550_STATIC ssize_t ns16550_write_support_polled(
0116 int minor,
0117 const char *buf,
0118 size_t len
0119 );
0120
0121 int ns16550_inbyte_nonblocking_polled(
0122 int minor
0123 );
0124
0125 NS16550_STATIC void ns16550_enable_interrupts(
0126 console_tbl *c,
0127 int mask
0128 );
0129
0130 NS16550_STATIC int ns16550_set_attributes(
0131 int minor,
0132 const struct termios *t
0133 );
0134
0135 #if defined(BSP_FEATURE_IRQ_EXTENSION) || defined(BSP_FEATURE_IRQ_LEGACY)
0136 NS16550_STATIC void ns16550_isr(void *arg);
0137 #endif
0138
0139 RTEMS_INTERRUPT_LOCK_DEFINE(static, ns16550_lock, "NS16550")
0140
0141
0142
0143
0144
0145 const console_flow ns16550_flow_RTSCTS = {
0146 ns16550_negate_RTS,
0147 ns16550_assert_RTS
0148 };
0149
0150 const console_flow ns16550_flow_DTRCTS = {
0151 ns16550_negate_DTR,
0152 ns16550_assert_DTR
0153 };
0154
0155 const console_fns ns16550_fns = {
0156 libchip_serial_default_probe,
0157 ns16550_open,
0158 ns16550_close,
0159 NULL,
0160 ns16550_write_support_int,
0161 ns16550_init,
0162 ns16550_write_polled,
0163 ns16550_set_attributes,
0164 true
0165 };
0166
0167 const console_fns ns16550_fns_polled = {
0168 libchip_serial_default_probe,
0169 ns16550_open,
0170 ns16550_close,
0171 ns16550_inbyte_nonblocking_polled,
0172 ns16550_write_support_polled,
0173 ns16550_init,
0174 ns16550_write_polled,
0175 ns16550_set_attributes,
0176 false
0177 };
0178
0179 static uint32_t NS16550_GetBaudDivisor(const console_tbl *c, uint32_t baud)
0180 {
0181 uint32_t clock = c->ulClock;
0182 uint32_t baudDivisor = (clock != 0 ? clock : 115200) / (baud * 16);
0183
0184 if (c->deviceType == SERIAL_NS16550_WITH_FDR) {
0185 uint32_t fractionalDivider = 0x10;
0186 uint32_t err = baud;
0187 uint32_t mulVal;
0188 uint32_t divAddVal;
0189
0190 clock /= 16 * baudDivisor;
0191 for (mulVal = 1; mulVal < 16; ++mulVal) {
0192 for (divAddVal = 0; divAddVal < mulVal; ++divAddVal) {
0193 uint32_t actual = (mulVal * clock) / (mulVal + divAddVal);
0194 uint32_t newErr = actual > baud ? actual - baud : baud - actual;
0195
0196 if (newErr < err) {
0197 err = newErr;
0198 fractionalDivider = (mulVal << 4) | divAddVal;
0199 }
0200 }
0201 }
0202
0203 (*c->setRegister)(
0204 c->ulCtrlPort1,
0205 NS16550_FRACTIONAL_DIVIDER,
0206 fractionalDivider
0207 );
0208 }
0209
0210 return baudDivisor;
0211 }
0212
0213
0214
0215
0216
0217 void ns16550_init(int minor)
0218 {
0219 uintptr_t pNS16550;
0220 uint8_t ucDataByte;
0221 uint32_t ulBaudDivisor;
0222 NS16550Context *pns16550Context;
0223 setRegister_f setReg;
0224 getRegister_f getReg;
0225 console_tbl *c = Console_Port_Tbl [minor];
0226
0227 pns16550Context=(NS16550Context *)malloc(sizeof(NS16550Context));
0228
0229 if (pns16550Context == NULL) {
0230 printk( "%s: Error: Not enough memory\n", __func__);
0231 rtems_fatal_error_occurred( 0xdeadbeef);
0232 }
0233
0234 Console_Port_Data[minor].pDeviceContext=(void *)pns16550Context;
0235 pns16550Context->ucModemCtrl=SP_MODEM_IRQ;
0236
0237 pNS16550 = c->ulCtrlPort1;
0238 setReg = c->setRegister;
0239 getReg = c->getRegister;
0240
0241
0242
0243
0244
0245
0246 (*setReg)(pNS16550, NS16550_LINE_CONTROL, 0x0);
0247 ns16550_enable_interrupts( c, NS16550_DISABLE_ALL_INTR );
0248
0249
0250
0251 ulBaudDivisor = NS16550_GetBaudDivisor(c, (uintptr_t) c->pDeviceParams);
0252 ucDataByte = SP_LINE_DLAB;
0253 (*setReg)(pNS16550, NS16550_LINE_CONTROL, ucDataByte);
0254
0255
0256 (*setReg)(pNS16550,NS16550_TRANSMIT_BUFFER,(uint8_t)(ulBaudDivisor & 0xffU));
0257 (*setReg)(
0258 pNS16550,NS16550_INTERRUPT_ENABLE,
0259 (uint8_t)(( ulBaudDivisor >> 8 ) & 0xffU )
0260 );
0261
0262
0263
0264 ucDataByte = EIGHT_BITS;
0265 (*setReg)(pNS16550, NS16550_LINE_CONTROL, ucDataByte);
0266
0267
0268 ucDataByte = SP_FIFO_ENABLE;
0269 (*setReg)(pNS16550, NS16550_FIFO_CONTROL, ucDataByte);
0270
0271 ucDataByte = SP_FIFO_ENABLE | SP_FIFO_RXRST | SP_FIFO_TXRST;
0272 (*setReg)(pNS16550, NS16550_FIFO_CONTROL, ucDataByte);
0273
0274 ns16550_enable_interrupts(c, NS16550_DISABLE_ALL_INTR);
0275
0276
0277
0278 (*setReg)(pNS16550, NS16550_MODEM_CONTROL,pns16550Context->ucModemCtrl);
0279
0280 (*getReg)(pNS16550, NS16550_LINE_STATUS );
0281 (*getReg)(pNS16550, NS16550_RECEIVE_BUFFER );
0282 }
0283
0284
0285
0286
0287
0288 int ns16550_open(
0289 int major,
0290 int minor,
0291 void *arg
0292 )
0293 {
0294 rtems_libio_open_close_args_t *oc = (rtems_libio_open_close_args_t *) arg;
0295 struct rtems_termios_tty *tty = (struct rtems_termios_tty *) oc->iop->data1;
0296 console_tbl *c = Console_Port_Tbl [minor];
0297 console_data *d = &Console_Port_Data [minor];
0298
0299 d->termios_data = tty;
0300
0301
0302 if (c->pDeviceFlow != &ns16550_flow_DTRCTS) {
0303 ns16550_assert_DTR( minor);
0304 }
0305
0306
0307 rtems_termios_set_initial_baud( tty, (intptr_t) c->pDeviceParams);
0308
0309 if (c->pDeviceFns->deviceOutputUsesInterrupts) {
0310 ns16550_initialize_interrupts( minor);
0311 ns16550_enable_interrupts( c, NS16550_ENABLE_ALL_INTR_EXCEPT_TX);
0312 }
0313
0314 return RTEMS_SUCCESSFUL;
0315 }
0316
0317
0318
0319
0320
0321 int ns16550_close(
0322 int major,
0323 int minor,
0324 void * arg
0325 )
0326 {
0327 console_tbl *c = Console_Port_Tbl [minor];
0328
0329
0330
0331
0332 if (c->pDeviceFlow != &ns16550_flow_DTRCTS) {
0333 ns16550_negate_DTR(minor);
0334 }
0335
0336 ns16550_enable_interrupts(c, NS16550_DISABLE_ALL_INTR);
0337
0338 if (c->pDeviceFns->deviceOutputUsesInterrupts) {
0339 ns16550_cleanup_interrupts(minor);
0340 }
0341
0342 return(RTEMS_SUCCESSFUL);
0343 }
0344
0345
0346
0347
0348 void ns16550_outch_polled(console_tbl *c, char out)
0349 {
0350 uintptr_t port = c->ulCtrlPort1;
0351 getRegister_f get = c->getRegister;
0352 setRegister_f set = c->setRegister;
0353 uint32_t status = 0;
0354 rtems_interrupt_lock_context lock_context;
0355
0356
0357 uint32_t interrupt_mask = get( port, NS16550_INTERRUPT_ENABLE);
0358
0359
0360 ns16550_enable_interrupts( c, NS16550_DISABLE_ALL_INTR);
0361
0362 while (true) {
0363
0364 rtems_interrupt_lock_acquire(&ns16550_lock, &lock_context);
0365
0366
0367 status = get( port, NS16550_LINE_STATUS);
0368 if ((status & SP_LSR_THOLD) != 0) {
0369
0370 set( port, NS16550_TRANSMIT_BUFFER, out);
0371
0372
0373 rtems_interrupt_lock_release(&ns16550_lock, &lock_context);
0374 break;
0375 } else {
0376 rtems_interrupt_lock_release(&ns16550_lock, &lock_context);
0377 }
0378
0379
0380 do {
0381 status = get( port, NS16550_LINE_STATUS);
0382 } while ((status & SP_LSR_THOLD) == 0);
0383 }
0384
0385
0386 set( port, NS16550_INTERRUPT_ENABLE, interrupt_mask);
0387 }
0388
0389 void ns16550_write_polled(int minor, char out)
0390 {
0391 console_tbl *c = Console_Port_Tbl [minor];
0392
0393 ns16550_outch_polled( c, out );
0394 }
0395
0396
0397
0398
0399
0400
0401
0402
0403
0404 NS16550_STATIC int ns16550_assert_RTS(int minor)
0405 {
0406 uint32_t pNS16550;
0407 rtems_interrupt_lock_context lock_context;
0408 NS16550Context *pns16550Context;
0409 setRegister_f setReg;
0410
0411 pns16550Context=(NS16550Context *) Console_Port_Data[minor].pDeviceContext;
0412
0413 pNS16550 = Console_Port_Tbl[minor]->ulCtrlPort1;
0414 setReg = Console_Port_Tbl[minor]->setRegister;
0415
0416
0417
0418
0419 rtems_interrupt_lock_acquire(&ns16550_lock, &lock_context);
0420 pns16550Context->ucModemCtrl|=SP_MODEM_RTS;
0421 (*setReg)(pNS16550, NS16550_MODEM_CONTROL, pns16550Context->ucModemCtrl);
0422 rtems_interrupt_lock_release(&ns16550_lock, &lock_context);
0423 return 0;
0424 }
0425
0426
0427
0428
0429
0430 NS16550_STATIC int ns16550_negate_RTS(int minor)
0431 {
0432 uint32_t pNS16550;
0433 rtems_interrupt_lock_context lock_context;
0434 NS16550Context *pns16550Context;
0435 setRegister_f setReg;
0436
0437 pns16550Context=(NS16550Context *) Console_Port_Data[minor].pDeviceContext;
0438
0439 pNS16550 = Console_Port_Tbl[minor]->ulCtrlPort1;
0440 setReg = Console_Port_Tbl[minor]->setRegister;
0441
0442
0443
0444
0445 rtems_interrupt_lock_acquire(&ns16550_lock, &lock_context);
0446 pns16550Context->ucModemCtrl&=~SP_MODEM_RTS;
0447 (*setReg)(pNS16550, NS16550_MODEM_CONTROL, pns16550Context->ucModemCtrl);
0448 rtems_interrupt_lock_release(&ns16550_lock, &lock_context);
0449 return 0;
0450 }
0451
0452
0453
0454
0455
0456
0457
0458
0459
0460
0461 NS16550_STATIC int ns16550_assert_DTR(int minor)
0462 {
0463 uint32_t pNS16550;
0464 rtems_interrupt_lock_context lock_context;
0465 NS16550Context *pns16550Context;
0466 setRegister_f setReg;
0467
0468 pns16550Context=(NS16550Context *) Console_Port_Data[minor].pDeviceContext;
0469
0470 pNS16550 = Console_Port_Tbl[minor]->ulCtrlPort1;
0471 setReg = Console_Port_Tbl[minor]->setRegister;
0472
0473
0474
0475
0476 rtems_interrupt_lock_acquire(&ns16550_lock, &lock_context);
0477 pns16550Context->ucModemCtrl|=SP_MODEM_DTR;
0478 (*setReg)(pNS16550, NS16550_MODEM_CONTROL, pns16550Context->ucModemCtrl);
0479 rtems_interrupt_lock_release(&ns16550_lock, &lock_context);
0480 return 0;
0481 }
0482
0483
0484
0485
0486
0487 NS16550_STATIC int ns16550_negate_DTR(int minor)
0488 {
0489 uint32_t pNS16550;
0490 rtems_interrupt_lock_context lock_context;
0491 NS16550Context *pns16550Context;
0492 setRegister_f setReg;
0493
0494 pns16550Context=(NS16550Context *) Console_Port_Data[minor].pDeviceContext;
0495
0496 pNS16550 = Console_Port_Tbl[minor]->ulCtrlPort1;
0497 setReg = Console_Port_Tbl[minor]->setRegister;
0498
0499
0500
0501
0502 rtems_interrupt_lock_acquire(&ns16550_lock, &lock_context);
0503 pns16550Context->ucModemCtrl&=~SP_MODEM_DTR;
0504 (*setReg)(pNS16550, NS16550_MODEM_CONTROL,pns16550Context->ucModemCtrl);
0505 rtems_interrupt_lock_release(&ns16550_lock, &lock_context);
0506 return 0;
0507 }
0508
0509
0510
0511
0512
0513
0514
0515
0516 int ns16550_set_attributes(
0517 int minor,
0518 const struct termios *t
0519 )
0520 {
0521 uint32_t pNS16550;
0522 uint32_t ulBaudDivisor;
0523 uint8_t ucLineControl;
0524 uint32_t baud_requested;
0525 setRegister_f setReg;
0526 rtems_interrupt_lock_context lock_context;
0527 const console_tbl *c = Console_Port_Tbl [minor];
0528
0529 pNS16550 = c->ulCtrlPort1;
0530 setReg = c->setRegister;
0531
0532
0533
0534
0535
0536
0537
0538 baud_requested = rtems_termios_baud_to_number(t->c_ospeed);
0539 _Assert( baud_requested != 0 );
0540 ulBaudDivisor = NS16550_GetBaudDivisor(c, baud_requested);
0541
0542 ucLineControl = 0;
0543
0544
0545
0546
0547
0548 if (t->c_cflag & PARENB) {
0549 ucLineControl |= SP_LINE_PAR;
0550 if (!(t->c_cflag & PARODD))
0551 ucLineControl |= SP_LINE_ODD;
0552 }
0553
0554
0555
0556
0557
0558 if (t->c_cflag & CSIZE) {
0559 switch (t->c_cflag & CSIZE) {
0560 case CS5: ucLineControl |= FIVE_BITS; break;
0561 case CS6: ucLineControl |= SIX_BITS; break;
0562 case CS7: ucLineControl |= SEVEN_BITS; break;
0563 case CS8: ucLineControl |= EIGHT_BITS; break;
0564 }
0565 } else {
0566 ucLineControl |= EIGHT_BITS;
0567 }
0568
0569
0570
0571
0572
0573 if (t->c_cflag & CSTOPB) {
0574 ucLineControl |= SP_LINE_STOP;
0575 } else {
0576 ;
0577 }
0578
0579
0580
0581
0582
0583 rtems_interrupt_lock_acquire(&ns16550_lock, &lock_context);
0584
0585
0586
0587
0588
0589
0590
0591
0592
0593 (*setReg)(pNS16550, NS16550_LINE_CONTROL, SP_LINE_DLAB);
0594 (*setReg)(pNS16550, NS16550_TRANSMIT_BUFFER, ulBaudDivisor&0xff);
0595 (*setReg)(pNS16550, NS16550_INTERRUPT_ENABLE, (ulBaudDivisor>>8)&0xff);
0596
0597
0598
0599
0600 (*setReg)(pNS16550, NS16550_LINE_CONTROL, ucLineControl );
0601
0602 rtems_interrupt_lock_release(&ns16550_lock, &lock_context);
0603
0604 return 0;
0605 }
0606
0607 #if defined(BSP_FEATURE_IRQ_EXTENSION) || defined(BSP_FEATURE_IRQ_LEGACY)
0608
0609
0610
0611
0612 NS16550_STATIC void ns16550_process( int minor)
0613 {
0614 console_tbl *c = Console_Port_Tbl [minor];
0615 console_data *d = &Console_Port_Data [minor];
0616 NS16550Context *ctx = d->pDeviceContext;
0617 uint32_t port = c->ulCtrlPort1;
0618 getRegister_f get = c->getRegister;
0619 int i;
0620 char buf [SP_FIFO_SIZE];
0621
0622
0623 do {
0624
0625 i = 0;
0626 while ((get(port, NS16550_LINE_STATUS) & SP_LSR_RDY) != 0) {
0627 buf[i++] = (char) get(port, NS16550_RECEIVE_BUFFER);
0628 if (i == SP_FIFO_SIZE) {
0629
0630 rtems_termios_enqueue_raw_characters( d->termios_data, buf, i);
0631 i = 0;
0632 }
0633 }
0634
0635 if (i > 0)
0636 rtems_termios_enqueue_raw_characters( d->termios_data, buf, i);
0637
0638
0639 if (ctx->transmitFifoChars > 0
0640 && (get( port, NS16550_LINE_STATUS) & SP_LSR_THOLD) != 0) {
0641
0642 rtems_termios_dequeue_characters(
0643 d->termios_data,
0644 ctx->transmitFifoChars
0645 );
0646 }
0647 } while ((get( port, NS16550_INTERRUPT_ID) & SP_IID_0) == 0);
0648 }
0649 #endif
0650
0651
0652
0653
0654
0655
0656
0657
0658
0659
0660 ssize_t ns16550_write_support_int(
0661 int minor,
0662 const char *buf,
0663 size_t len
0664 )
0665 {
0666 console_tbl *c = Console_Port_Tbl [minor];
0667 console_data *d = &Console_Port_Data [minor];
0668 NS16550Context *ctx = d->pDeviceContext;
0669 uint32_t port = c->ulCtrlPort1;
0670 setRegister_f set = c->setRegister;
0671 int i = 0;
0672 int out = len > SP_FIFO_SIZE ? SP_FIFO_SIZE : len;
0673
0674 for (i = 0; i < out; ++i) {
0675 set( port, NS16550_TRANSMIT_BUFFER, buf [i]);
0676 }
0677
0678 ctx->transmitFifoChars = out;
0679
0680 if (out > 0) {
0681 ns16550_enable_interrupts( c, NS16550_ENABLE_ALL_INTR);
0682 } else {
0683 ns16550_enable_interrupts( c, NS16550_ENABLE_ALL_INTR_EXCEPT_TX);
0684 }
0685
0686 return 0;
0687 }
0688
0689
0690
0691
0692
0693
0694 NS16550_STATIC void ns16550_enable_interrupts(
0695 console_tbl *c,
0696 int mask
0697 )
0698 {
0699 uint32_t pNS16550;
0700 setRegister_f setReg;
0701
0702 pNS16550 = c->ulCtrlPort1;
0703 setReg = c->setRegister;
0704
0705 (*setReg)(pNS16550, NS16550_INTERRUPT_ENABLE, mask);
0706 }
0707
0708 #if defined(BSP_FEATURE_IRQ_EXTENSION) || defined(BSP_FEATURE_IRQ_LEGACY)
0709 void ns16550_isr(void *arg)
0710 {
0711 int minor = (intptr_t) arg;
0712
0713 ns16550_process( minor);
0714 }
0715 #endif
0716
0717
0718
0719
0720
0721
0722 NS16550_STATIC void ns16550_initialize_interrupts( int minor)
0723 {
0724 #if defined(BSP_FEATURE_IRQ_EXTENSION) || defined(BSP_FEATURE_IRQ_LEGACY)
0725 console_tbl *c = Console_Port_Tbl [minor];
0726 #endif
0727
0728 #ifdef BSP_FEATURE_IRQ_EXTENSION
0729 {
0730 rtems_status_code sc = RTEMS_SUCCESSFUL;
0731 sc = rtems_interrupt_handler_install(
0732 c->ulIntVector,
0733 "NS16550",
0734 RTEMS_INTERRUPT_SHARED,
0735 ns16550_isr,
0736 (void *) (intptr_t) minor
0737 );
0738 if (sc != RTEMS_SUCCESSFUL) {
0739
0740 printk( "%s: Error: Install interrupt handler\n", __func__);
0741 rtems_fatal_error_occurred( 0xdeadbeef);
0742 }
0743 }
0744 #elif defined(BSP_FEATURE_IRQ_LEGACY)
0745 {
0746 int rv = 0;
0747 #ifdef BSP_FEATURE_IRQ_LEGACY_SHARED_HANDLER_SUPPORT
0748 rtems_irq_connect_data cd = {
0749 c->ulIntVector,
0750 ns16550_isr,
0751 (void *) minor,
0752 NULL,
0753 NULL,
0754 NULL,
0755 NULL
0756 };
0757 rv = BSP_install_rtems_shared_irq_handler( &cd);
0758 #else
0759 rtems_irq_connect_data cd = {
0760 c->ulIntVector,
0761 ns16550_isr,
0762 (void *) minor,
0763 NULL,
0764 NULL,
0765 NULL
0766 };
0767 rv = BSP_install_rtems_irq_handler( &cd);
0768 #endif
0769 if (rv == 0) {
0770
0771 printk( "%s: Error: Install interrupt handler\n", __func__);
0772 rtems_fatal_error_occurred( 0xdeadbeef);
0773 }
0774 }
0775 #endif
0776 }
0777
0778 NS16550_STATIC void ns16550_cleanup_interrupts(int minor)
0779 {
0780 #if defined(BSP_FEATURE_IRQ_EXTENSION)
0781 rtems_status_code sc = RTEMS_SUCCESSFUL;
0782 console_tbl *c = Console_Port_Tbl [minor];
0783 sc = rtems_interrupt_handler_remove(
0784 c->ulIntVector,
0785 ns16550_isr,
0786 (void *) (intptr_t) minor
0787 );
0788 if (sc != RTEMS_SUCCESSFUL) {
0789
0790 printk("%s: Error: Remove interrupt handler\n", __func__);
0791 rtems_fatal_error_occurred(0xdeadbeef);
0792 }
0793 #elif defined(BSP_FEATURE_IRQ_LEGACY)
0794 int rv = 0;
0795 console_tbl *c = Console_Port_Tbl [minor];
0796 rtems_irq_connect_data cd = {
0797 .name = c->ulIntVector,
0798 .hdl = ns16550_isr,
0799 .handle = (void *) minor
0800 };
0801 rv = BSP_remove_rtems_irq_handler(&cd);
0802 if (rv == 0) {
0803
0804 printk("%s: Error: Remove interrupt handler\n", __func__);
0805 rtems_fatal_error_occurred(0xdeadbeef);
0806 }
0807 #endif
0808 }
0809
0810
0811
0812
0813
0814
0815
0816
0817 ssize_t ns16550_write_support_polled(
0818 int minor,
0819 const char *buf,
0820 size_t len
0821 )
0822 {
0823 int nwrite = 0;
0824
0825
0826
0827
0828 while (nwrite < len) {
0829
0830
0831
0832 ns16550_write_polled(minor, *buf++);
0833 nwrite++;
0834 }
0835
0836
0837
0838
0839 return nwrite;
0840 }
0841
0842
0843
0844
0845 int ns16550_inch_polled(
0846 console_tbl *c
0847 )
0848 {
0849 uint32_t pNS16550;
0850 unsigned char ucLineStatus;
0851 uint8_t cChar;
0852 getRegister_f getReg;
0853
0854 pNS16550 = c->ulCtrlPort1;
0855 getReg = c->getRegister;
0856
0857 ucLineStatus = (*getReg)(pNS16550, NS16550_LINE_STATUS);
0858 if (ucLineStatus & SP_LSR_RDY) {
0859 cChar = (*getReg)(pNS16550, NS16550_RECEIVE_BUFFER);
0860 return (int)cChar;
0861 }
0862 return -1;
0863 }
0864
0865
0866
0867
0868
0869
0870 int ns16550_inbyte_nonblocking_polled(int minor)
0871 {
0872 console_tbl *c = Console_Port_Tbl [minor];
0873
0874 return ns16550_inch_polled( c );
0875 }