Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:23:58

0001 /*
0002  * This software is Copyright (C) 1998 by T.sqware - all rights limited
0003  * It is provided in to the public domain "as is", can be freely modified
0004  * as far as this copyight notice is kept unchanged, but does not imply
0005  * an endorsement by T.sqware of the product in which it is included.
0006  */
0007 
0008 #include <stdint.h>
0009 #include <stdio.h>
0010 #include <bsp.h>
0011 #include <bsp/irq.h>
0012 #include <bsp/uart.h>
0013 #include <rtems/libio.h>
0014 #include <rtems/bspIo.h>
0015 #include <rtems/termiostypes.h>
0016 #include <termios.h>
0017 #include <assert.h>
0018 
0019 /*
0020  * Basic 16552 driver
0021  */
0022 
0023 struct uart_data
0024 {
0025   unsigned long       ioBase;
0026   int                 irq;
0027   int                 hwFlow;
0028   int                 baud;
0029   BSP_UartBreakCbRec  breakCallback;
0030   int                 ioMode;
0031 };
0032 
0033 /*
0034  * Initialization of BSP specific data.
0035  * The constants are pulled in from a BSP
0036  * specific file, whereas all of the code
0037  * in this file is generic and makes no
0038  * assumptions about addresses, irq vectors
0039  * etc...
0040  */
0041 
0042 #define UART_UNSUPP ((unsigned long)(-1))
0043 
0044 static struct uart_data uart_data[2] = {
0045     {
0046 #ifdef  BSP_UART_IOBASE_COM1
0047         BSP_UART_IOBASE_COM1,
0048         BSP_UART_COM1_IRQ,
0049 #else
0050         UART_UNSUPP,
0051         -1,
0052 #endif
0053     },
0054     {
0055 #ifdef  BSP_UART_IOBASE_COM2
0056         BSP_UART_IOBASE_COM2,
0057         BSP_UART_COM2_IRQ,
0058 #else
0059         UART_UNSUPP,
0060         -1,
0061 #endif
0062     },
0063 };
0064 
0065 #define MAX_UARTS (sizeof(uart_data)/sizeof(uart_data[0]))
0066 #define SANITY_CHECK(uart) \
0067   assert( MAX_UARTS > (unsigned)(uart) && uart_data[(uart)].ioBase != UART_UNSUPP )
0068 /*
0069  * Macros to read/write register of uart, if configuration is
0070  * different just rewrite these macros
0071  */
0072 
0073 static inline unsigned char
0074 uread(int uart, unsigned int reg)
0075 {
0076     return in_8((uint8_t*)(uart_data[uart].ioBase + reg));
0077 }
0078 
0079 static inline void
0080 uwrite(int uart, int reg, unsigned int val)
0081 {
0082     out_8((uint8_t*)(uart_data[uart].ioBase + reg), val);
0083 }
0084 
0085 
0086 static void
0087 uartError(int uart, void *termiosPrivate)
0088 {
0089   unsigned char uartStatus, dummy;
0090   BSP_UartBreakCbProc       h;
0091 
0092   uartStatus = uread(uart, LSR);
0093   dummy = uread(uart, RBR);
0094 
0095 #ifdef UARTDEBUG
0096   if (uartStatus & OE)
0097     printk("********* Over run Error **********\n");
0098   if (uartStatus & PE)
0099     printk("********* Parity Error   **********\n");
0100   if (uartStatus & FE)
0101     printk("********* Framing Error  **********\n");
0102   if (uartStatus & BI) {
0103     printk("********* BREAK INTERRUPT *********\n");
0104 #endif
0105    if ((h=uart_data[uart].breakCallback.handler)) {
0106      h(uart,
0107        (dummy<<8)|uartStatus,
0108        termiosPrivate,
0109        uart_data[uart].breakCallback.private);
0110   }
0111 #ifdef UARTDEBUG
0112   if (uartStatus & ERFIFO)
0113     printk("********* Error receive Fifo **********\n");
0114 #endif
0115 }
0116 
0117 /*
0118  * Uart initialization, it is hardcoded to 8 bit, no parity,
0119  * one stop bit, FIFO, things to be changed
0120  * are baud rate and nad hw flow control,
0121  * and longest rx fifo setting
0122  */
0123 void
0124 BSP_uart_init(int uart, int baud, int hwFlow)
0125 {
0126   unsigned char tmp;
0127 
0128   /* Sanity check */
0129   SANITY_CHECK(uart);
0130 
0131   /* Make sure any printk activity drains before
0132    * re-initializing.
0133    */
0134   while ( ! (uread(uart, LSR) & TEMT) )
0135     ;
0136 
0137   switch(baud)
0138     {
0139     case 50:
0140     case 75:
0141     case 110:
0142     case 134:
0143     case 300:
0144     case 600:
0145     case 1200:
0146     case 2400:
0147     case 9600:
0148     case 19200:
0149     case 38400:
0150     case 57600:
0151     case 115200:
0152       break;
0153     default:
0154       assert(0);
0155       return;
0156     }
0157 
0158   /* Set DLAB bit to 1 */
0159   uwrite(uart, LCR, DLAB);
0160 
0161   if ( (int)BSPBaseBaud <= 0 ) {
0162     /* Use current divisor assuming BSPBaseBaud gives us the current speed */
0163     BSPBaseBaud  = BSPBaseBaud ? -BSPBaseBaud : BSP_CONSOLE_BAUD;
0164     BSPBaseBaud *= ((uread(uart, DLM) << 8) | uread(uart, DLL));
0165   }
0166 
0167   /* Set baud rate */
0168   uwrite(uart, DLL,  (BSPBaseBaud/baud) & 0xff);
0169   uwrite(uart, DLM,  ((BSPBaseBaud/baud) >> 8) & 0xff);
0170 
0171   /* 8-bit, no parity , 1 stop */
0172   uwrite(uart, LCR, CHR_8_BITS);
0173 
0174   /* Set DTR, RTS and OUT2 high */
0175   uwrite(uart, MCR, DTR | RTS | OUT_2);
0176 
0177   /* Enable FIFO */
0178   uwrite(uart, FCR, FIFO_EN | XMIT_RESET | RCV_RESET | RECEIVE_FIFO_TRIGGER12);
0179 
0180   /* Disable Interrupts */
0181   uwrite(uart, IER, 0);
0182 
0183   /* Read status to clear them */
0184   tmp = uread(uart, LSR);
0185   tmp = uread(uart, RBR);
0186   tmp = uread(uart, MSR);
0187   (void) tmp; /* avoid set but not used warning */
0188 
0189   /* Remember state */
0190   uart_data[uart].hwFlow     = hwFlow;
0191   uart_data[uart].baud       = baud;
0192   return;
0193 }
0194 
0195 /*
0196  * Set baud
0197  */
0198 void
0199 BSP_uart_set_baud(int uart, int baud)
0200 {
0201   unsigned char mcr, ier;
0202 
0203   /* Sanity check */
0204   SANITY_CHECK(uart);
0205 
0206   /*
0207    * This function may be called whenever TERMIOS parameters
0208    * are changed, so we have to make sure that baud change is
0209    * indeed required.
0210    */
0211 
0212   if(baud == uart_data[uart].baud)
0213     {
0214       return;
0215     }
0216 
0217   mcr = uread(uart, MCR);
0218   ier = uread(uart, IER);
0219 
0220   BSP_uart_init(uart, baud, uart_data[uart].hwFlow);
0221 
0222   uwrite(uart, MCR, mcr);
0223   uwrite(uart, IER, ier);
0224 
0225   return;
0226 }
0227 
0228 /*
0229  * Enable/disable interrupts
0230  */
0231 void
0232 BSP_uart_intr_ctrl(int uart, int cmd)
0233 {
0234 
0235   SANITY_CHECK(uart);
0236 
0237   switch(cmd)
0238     {
0239     case BSP_UART_INTR_CTRL_DISABLE:
0240       uwrite(uart, IER, INTERRUPT_DISABLE);
0241       break;
0242     case BSP_UART_INTR_CTRL_ENABLE:
0243       if(uart_data[uart].hwFlow)
0244     {
0245       uwrite(uart, IER,
0246          (RECEIVE_ENABLE  |
0247           TRANSMIT_ENABLE |
0248           RECEIVER_LINE_ST_ENABLE |
0249           MODEM_ENABLE
0250          )
0251         );
0252     }
0253       else
0254     {
0255       uwrite(uart, IER,
0256          (RECEIVE_ENABLE  |
0257           TRANSMIT_ENABLE |
0258           RECEIVER_LINE_ST_ENABLE
0259          )
0260         );
0261     }
0262       break;
0263     case BSP_UART_INTR_CTRL_TERMIOS:
0264       if(uart_data[uart].hwFlow)
0265     {
0266       uwrite(uart, IER,
0267          (RECEIVE_ENABLE  |
0268           RECEIVER_LINE_ST_ENABLE |
0269           MODEM_ENABLE
0270          )
0271         );
0272     }
0273       else
0274     {
0275       uwrite(uart, IER,
0276          (RECEIVE_ENABLE  |
0277           RECEIVER_LINE_ST_ENABLE
0278          )
0279         );
0280     }
0281       break;
0282     case BSP_UART_INTR_CTRL_GDB:
0283       uwrite(uart, IER, RECEIVE_ENABLE);
0284       break;
0285     default:
0286       assert(0);
0287       break;
0288     }
0289 
0290   return;
0291 }
0292 
0293 void
0294 BSP_uart_throttle(int uart)
0295 {
0296   unsigned int mcr;
0297 
0298   SANITY_CHECK(uart);
0299 
0300   if(!uart_data[uart].hwFlow)
0301     {
0302       /* Should not happen */
0303       assert(0);
0304       return;
0305     }
0306   mcr = uread (uart, MCR);
0307   /* RTS down */
0308   mcr &= ~RTS;
0309   uwrite(uart, MCR, mcr);
0310 
0311   return;
0312 }
0313 
0314 void
0315 BSP_uart_unthrottle(int uart)
0316 {
0317   unsigned int mcr;
0318 
0319   SANITY_CHECK(uart);
0320 
0321   if(!uart_data[uart].hwFlow)
0322     {
0323       /* Should not happen */
0324       assert(0);
0325       return;
0326     }
0327   mcr = uread (uart, MCR);
0328   /* RTS up */
0329   mcr |= RTS;
0330   uwrite(uart, MCR, mcr);
0331 
0332   return;
0333 }
0334 
0335 /*
0336  * Status function, -1 if error
0337  * detected, 0 if no received chars available,
0338  * 1 if received char available, 2 if break
0339  * is detected, it will eat break and error
0340  * chars. It ignores overruns - we cannot do
0341  * anything about - it execpt count statistics
0342  * and we are not counting it.
0343  */
0344 int
0345 BSP_uart_polled_status(int uart)
0346 {
0347   unsigned char val;
0348 
0349   SANITY_CHECK(uart);
0350 
0351   val = uread(uart, LSR);
0352 
0353   if(val & BI)
0354     {
0355       /* BREAK found, eat character */
0356       uread(uart, RBR);
0357       return BSP_UART_STATUS_BREAK;
0358     }
0359 
0360   if((val & (DR | OE | FE)) ==  1)
0361     {
0362       /* No error, character present */
0363       return BSP_UART_STATUS_CHAR;
0364     }
0365 
0366   if((val & (DR | OE | FE)) == 0)
0367     {
0368       /* Nothing */
0369       return BSP_UART_STATUS_NOCHAR;
0370     }
0371 
0372   /*
0373    * Framing or parity error
0374    * eat character
0375    */
0376   uread(uart, RBR);
0377 
0378   return BSP_UART_STATUS_ERROR;
0379 }
0380 
0381 /*
0382  * Polled mode write function
0383  */
0384 void
0385 BSP_uart_polled_write(int uart, int val)
0386 {
0387   unsigned char val1;
0388 
0389   /* Sanity check */
0390   SANITY_CHECK(uart);
0391 
0392   for(;;)
0393     {
0394       if((val1=uread(uart, LSR)) & THRE)
0395     {
0396       break;
0397     }
0398     }
0399 
0400   if(uart_data[uart].hwFlow)
0401     {
0402       for(;;)
0403     {
0404       if(uread(uart, MSR) & CTS)
0405         {
0406           break;
0407         }
0408     }
0409     }
0410 
0411   uwrite(uart, THR, val & 0xff);
0412 
0413   return;
0414 }
0415 
0416 void
0417 BSP_output_char_via_serial(const char val)
0418 {
0419   BSP_uart_polled_write(BSPConsolePort, val);
0420 }
0421 
0422 /*
0423  * Polled mode read function
0424  */
0425 int
0426 BSP_uart_polled_read(int uart)
0427 {
0428   unsigned char val;
0429 
0430   SANITY_CHECK(uart);
0431 
0432   for(;;)
0433     {
0434       if(uread(uart, LSR) & DR)
0435     {
0436       break;
0437     }
0438     }
0439 
0440   val = uread(uart, RBR);
0441 
0442   return (int)(val & 0xff);
0443 }
0444 
0445 unsigned
0446 BSP_poll_char_via_serial()
0447 {
0448     return BSP_uart_polled_read(BSPConsolePort);
0449 }
0450 
0451 static void
0452 uart_noop(const rtems_irq_connect_data *unused)
0453 {
0454   return;
0455 }
0456 
0457 /* note that the IRQ names contain _ISA_ for legacy
0458  * reasons. They can be any interrupt, depending
0459  * on the particular BSP...
0460  */
0461 
0462 static int
0463 uart_isr_is_on(const rtems_irq_connect_data *irq)
0464 {
0465   int uart;
0466 
0467   uart = (irq->name == BSP_UART_COM1_IRQ) ?
0468             BSP_UART_COM1 : BSP_UART_COM2;
0469 
0470   return uread(uart,IER);
0471 }
0472 
0473 static int
0474 doit(int uart, rtems_irq_hdl handler, int (*p)(const rtems_irq_connect_data*))
0475 {
0476     rtems_irq_connect_data d={0};
0477     d.name = uart_data[uart].irq;
0478     d.off  = d.on = uart_noop;
0479     d.isOn = uart_isr_is_on;
0480     d.hdl  = handler;
0481     return p(&d);
0482 }
0483 
0484 int
0485 BSP_uart_install_isr(int uart, rtems_irq_hdl handler)
0486 {
0487 /* Using shared interrupts by default might break things.. the
0488  * shared IRQ installer uses malloc() and if a BSP had called this
0489  * during early init it might not work...
0490  */
0491 #ifdef BSP_UART_USE_SHARED_IRQS
0492     return doit(uart, handler, BSP_install_rtems_shared_irq_handler);
0493 #else
0494     return doit(uart, handler, BSP_install_rtems_irq_handler);
0495 #endif
0496 }
0497 
0498 int
0499 BSP_uart_remove_isr(int uart, rtems_irq_hdl handler)
0500 {
0501     return doit(uart, handler, BSP_remove_rtems_irq_handler);
0502 }
0503 
0504 /* ================ Termios support  =================*/
0505 
0506 static volatile int  termios_stopped_com[2]        = {0,0};
0507 static volatile int  termios_tx_active_com[2]      = {0,0};
0508 static void*         termios_ttyp_com[2]           = {NULL,NULL};
0509 static char          termios_tx_hold_com[2]        = {0,0};
0510 static volatile char termios_tx_hold_valid_com[2]  = {0,0};
0511 
0512 /*
0513  * Set channel parameters
0514  */
0515 void
0516 BSP_uart_termios_set(int uart, void *p)
0517 {
0518   struct rtems_termios_tty *ttyp = p;
0519   unsigned char val;
0520   SANITY_CHECK(uart);
0521 
0522   if(uart_data[uart].hwFlow)
0523     {
0524       val = uread(uart, MSR);
0525 
0526       termios_stopped_com[uart]    = (val & CTS) ? 0 : 1;
0527     }
0528   else
0529   {
0530       termios_stopped_com[uart] = 0;
0531   }
0532   termios_tx_active_com[uart]      = 0;
0533   termios_ttyp_com[uart]           = ttyp;
0534   termios_tx_hold_com[uart]        = 0;
0535   termios_tx_hold_valid_com[uart]  = 0;
0536 
0537   uart_data[uart].ioMode           = ttyp->device.outputUsesInterrupts;
0538 
0539   /* Convert from the baud number to the "speed_t" termios setting. */
0540   ttyp->termios.c_ispeed = ttyp->termios.c_ospeed =
0541     rtems_termios_number_to_baud(uart_data[uart].baud);
0542 
0543   return;
0544 }
0545 
0546 ssize_t
0547 BSP_uart_termios_write_polled(int minor, const char *buf, size_t len)
0548 {
0549   int uart=minor;   /* could differ, theoretically */
0550   int nwrite;
0551   const char *b = buf;
0552 
0553   for (nwrite=0 ; nwrite < len ; nwrite++) {
0554     BSP_uart_polled_write(uart, *b++);
0555   }
0556   return nwrite;
0557 }
0558 
0559 ssize_t
0560 BSP_uart_termios_write_com(int minor, const char *buf, size_t len)
0561 {
0562   int uart=minor;   /* could differ, theoretically */
0563 
0564   if(len <= 0)
0565     {
0566       return 0;
0567     }
0568 
0569   /* If the TX buffer is busy - something is royally screwed up */
0570   /*   assert((uread(BSP_UART_COM1, LSR) & THRE) != 0); */
0571 
0572   if(termios_stopped_com[uart])
0573     {
0574       /* CTS low */
0575       termios_tx_hold_com[uart]       = *buf;
0576       termios_tx_hold_valid_com[uart] = 1;
0577       return 0;
0578     }
0579 
0580   /* Write character */
0581   uwrite(uart, THR, *buf & 0xff);
0582 
0583   /* Enable interrupts if necessary */
0584   if(!termios_tx_active_com[uart] && uart_data[uart].hwFlow)
0585     {
0586       termios_tx_active_com[uart] = 1;
0587       uwrite(uart, IER,
0588          (RECEIVE_ENABLE  |
0589           TRANSMIT_ENABLE |
0590           RECEIVER_LINE_ST_ENABLE |
0591           MODEM_ENABLE
0592          )
0593         );
0594     }
0595   else if(!termios_tx_active_com[uart])
0596     {
0597       termios_tx_active_com[uart] = 1;
0598       uwrite(uart, IER,
0599          (RECEIVE_ENABLE  |
0600           TRANSMIT_ENABLE |
0601           RECEIVER_LINE_ST_ENABLE
0602          )
0603         );
0604     }
0605 
0606   return 0;
0607 }
0608 
0609 int
0610 BSP_uart_termios_read_com(int uart)
0611 {
0612   int     off = (int)0;
0613   char    buf[40];
0614   rtems_interrupt_level l;
0615 
0616   /* read bytes */
0617   while (( off < sizeof(buf) ) && ( uread(uart, LSR) & DR )) {
0618     buf[off++] = uread(uart, RBR);
0619   }
0620 
0621   /* write out data */
0622   if ( off > 0 ) {
0623     rtems_termios_enqueue_raw_characters(termios_ttyp_com[uart], buf, off);
0624   }
0625 
0626   /* enable receive interrupts */
0627   rtems_interrupt_disable(l);
0628   uwrite(uart, IER, uread(uart, IER) | (RECEIVE_ENABLE | RECEIVER_LINE_ST_ENABLE));
0629   rtems_interrupt_enable(l);
0630 
0631   return ( EOF );
0632 }
0633 
0634 static void
0635 BSP_uart_termios_isr_com(int uart)
0636 {
0637   unsigned char buf[40];
0638   unsigned char val, ier;
0639   int      off, ret, vect;
0640 
0641   off = 0;
0642 
0643   for(;;)
0644     {
0645       vect = uread(uart, IIR) & 0xf;
0646 
0647       switch(vect)
0648     {
0649     case MODEM_STATUS :
0650       val = uread(uart, MSR);
0651       if(uart_data[uart].hwFlow)
0652         {
0653           if(val & CTS)
0654         {
0655           /* CTS high */
0656           termios_stopped_com[uart] = 0;
0657           if(termios_tx_hold_valid_com[uart])
0658             {
0659               termios_tx_hold_valid_com[uart] = 0;
0660               BSP_uart_termios_write_com(uart, &termios_tx_hold_com[uart],
0661                             1);
0662             }
0663         }
0664           else
0665         {
0666           /* CTS low */
0667           termios_stopped_com[uart] = 1;
0668         }
0669         }
0670       break;
0671     case NO_MORE_INTR :
0672       /* No more interrupts */
0673       if(off != 0)
0674         {
0675           /* Update rx buffer */
0676           rtems_termios_enqueue_raw_characters(termios_ttyp_com[uart],
0677                            (char *)buf,
0678                            off);
0679         }
0680       return;
0681     case TRANSMITTER_HODING_REGISTER_EMPTY :
0682       /*
0683        * TX holding empty: we have to disable these interrupts
0684        * if there is nothing more to send.
0685        */
0686 
0687       ret = rtems_termios_dequeue_characters(termios_ttyp_com[uart], 1);
0688 
0689       /* If nothing else to send disable interrupts */
0690       if(ret == 0 && uart_data[uart].hwFlow)
0691         {
0692           uwrite(uart, IER,
0693              (RECEIVE_ENABLE  |
0694               RECEIVER_LINE_ST_ENABLE |
0695               MODEM_ENABLE
0696              )
0697             );
0698               termios_tx_active_com[uart] = 0;
0699         }
0700       else if(ret == 0)
0701         {
0702           uwrite(uart, IER,
0703              (RECEIVE_ENABLE  |
0704               RECEIVER_LINE_ST_ENABLE
0705              )
0706             );
0707               termios_tx_active_com[uart] = 0;
0708         }
0709       break;
0710     case RECEIVER_DATA_AVAIL :
0711     case CHARACTER_TIMEOUT_INDICATION:
0712       if ( uart_data[uart].ioMode == TERMIOS_TASK_DRIVEN )
0713         {
0714           /* ensure interrupts are enabled */
0715           if ( (ier = uread(uart,IER)) & RECEIVE_ENABLE )
0716             {
0717                /* disable interrupts and notify termios */
0718                ier &= ~(RECEIVE_ENABLE | RECEIVER_LINE_ST_ENABLE);
0719                uwrite(uart, IER, ier);
0720                rtems_termios_rxirq_occured(termios_ttyp_com[uart]);
0721             }
0722         }
0723       else
0724         {
0725           /* RX data ready */
0726           assert(off < sizeof(buf));
0727           while ( off < sizeof(buf) && ( DR & uread(uart, LSR) ) )
0728             buf[off++] = uread(uart, RBR);
0729         }
0730       break;
0731     case RECEIVER_ERROR:
0732       /* RX error: eat character */
0733        uartError(uart, termios_ttyp_com[uart]);
0734       break;
0735     default:
0736       /* Should not happen */
0737       assert(0);
0738       return;
0739     }
0740     }
0741 }
0742 
0743 /*
0744  * XXX - Note that this can now be one isr with the uart
0745  *       passed as the parameter.
0746  */
0747 void
0748 BSP_uart_termios_isr_com1(void *unused)
0749 {
0750     BSP_uart_termios_isr_com(BSP_UART_COM1);
0751 }
0752 
0753 void
0754 BSP_uart_termios_isr_com2(void *unused)
0755 {
0756     BSP_uart_termios_isr_com(BSP_UART_COM2);
0757 }
0758 
0759 /* retrieve 'break' handler info */
0760 int
0761 BSP_uart_get_break_cb(int uart, rtems_libio_ioctl_args_t *arg)
0762 {
0763 BSP_UartBreakCb cb=arg->buffer;
0764 unsigned long flags;
0765     SANITY_CHECK(uart);
0766     rtems_interrupt_disable(flags);
0767         *cb = uart_data[uart].breakCallback;
0768     rtems_interrupt_enable(flags);
0769     arg->ioctl_return=0;
0770     return RTEMS_SUCCESSFUL;
0771 }
0772 
0773 /* install 'break' handler */
0774 int
0775 BSP_uart_set_break_cb(int uart, rtems_libio_ioctl_args_t *arg)
0776 {
0777 BSP_UartBreakCb cb=arg->buffer;
0778 unsigned long flags;
0779     SANITY_CHECK(uart);
0780     rtems_interrupt_disable(flags);
0781         uart_data[uart].breakCallback = *cb;
0782     rtems_interrupt_enable(flags);
0783     arg->ioctl_return=0;
0784     return RTEMS_SUCCESSFUL;
0785 }