Back to home page

LXR

 
 

    


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

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 <stdio.h>
0009 #include <bsp.h>
0010 #include <bsp/irq.h>
0011 #include <uart.h>
0012 #include <rtems/libio.h>
0013 #include <rtems/termiostypes.h>
0014 #include <termios.h>
0015 #include <assert.h>
0016 
0017 /*
0018  * Basic 16552 driver
0019  */
0020 
0021 struct uart_data
0022 {
0023   int ioMode;
0024   int hwFlow;
0025   unsigned int  ier;
0026   unsigned long baud;
0027   unsigned long databits;
0028   unsigned long parity;
0029   unsigned long stopbits;
0030 };
0031 
0032 static struct uart_data uart_data[2];
0033 
0034 /*
0035  * Macros to read/write register of uart, if configuration is
0036  * different just rewrite these macros
0037  */
0038 
0039 static inline unsigned char
0040 uread(int uart, unsigned int reg)
0041 {
0042   register unsigned char val;
0043 
0044   if (uart == 0) {
0045     inport_byte(COM1_BASE_IO+reg, val);
0046   } else {
0047     inport_byte(COM2_BASE_IO+reg, val);
0048   }
0049 
0050   return val;
0051 }
0052 
0053 static inline void
0054 uwrite(int uart, int reg, unsigned int val)
0055 {
0056   if (uart == 0) {
0057     outport_byte(COM1_BASE_IO+reg, val);
0058   } else {
0059     outport_byte(COM2_BASE_IO+reg, val);
0060   }
0061 }
0062 
0063 static void
0064 uartError(int uart)
0065 {
0066   unsigned char uartStatus, dummy;
0067 
0068   uartStatus = uread(uart, LSR);
0069   (void) uartStatus; /* avoid set but not used warning */
0070   dummy = uread(uart, RBR);
0071   (void) dummy;      /* avoid set but not used warning */
0072 
0073 #ifdef UARTDEBUG
0074   if (uartStatus & OE)
0075     printk("********* Over run Error **********\n");
0076   if (uartStatus & PE)
0077     printk("********* Parity Error   **********\n");
0078   if (uartStatus & FE)
0079     printk("********* Framing Error  **********\n");
0080   if (uartStatus & BI)
0081     printk("********* Parity Error   **********\n");
0082   if (uartStatus & ERFIFO)
0083     printk("********* Error receive Fifo **********\n");
0084 #endif
0085 }
0086 
0087 /*
0088  * Uart initialization, it is hardcoded to 8 bit, no parity,
0089  * one stop bit, FIFO, things to be changed
0090  * are baud rate and nad hw flow control,
0091  * and longest rx fifo setting
0092  */
0093 void
0094 BSP_uart_init
0095 (
0096   int uart,
0097   unsigned long baud,
0098   unsigned long databits,
0099   unsigned long parity,
0100   unsigned long stopbits,
0101   int hwFlow
0102 )
0103 {
0104   /* Sanity check */
0105   assert(uart == BSP_UART_COM1 || uart == BSP_UART_COM2);
0106 
0107   switch(baud)
0108     {
0109     case 50:
0110     case 75:
0111     case 110:
0112     case 134:
0113     case 300:
0114     case 600:
0115     case 1200:
0116     case 2400:
0117     case 9600:
0118     case 19200:
0119     case 38400:
0120     case 57600:
0121     case 115200:
0122       break;
0123     default:
0124       assert(0);
0125       return;
0126     }
0127 
0128   /* Set DLAB bit to 1 */
0129   uwrite(uart, LCR, DLAB);
0130 
0131   /* Set baud rate */
0132   uwrite(uart, DLL,  (BSPBaseBaud/baud) & 0xff);
0133   uwrite(uart, DLM,  ((BSPBaseBaud/baud) >> 8) & 0xff);
0134 
0135   /* 8-bit, no parity , 1 stop */
0136   uwrite(uart, LCR, databits | parity | stopbits);
0137 
0138   /* Set DTR, RTS and OUT2 high */
0139   uwrite(uart, MCR, DTR | RTS | OUT_2);
0140 
0141   /* Enable FIFO */
0142   uwrite(uart, FCR, FIFO_EN | XMIT_RESET | RCV_RESET | RECEIVE_FIFO_TRIGGER12);
0143 
0144   /* Disable Interrupts */
0145   uwrite(uart, IER, 0);
0146 
0147   /* Read status to clear them */
0148   uread(uart, LSR);
0149   uread(uart, RBR);
0150   uread(uart, MSR);
0151 
0152   /* Remember state */
0153   uart_data[uart].baud       = baud;
0154   uart_data[uart].databits   = databits;
0155   uart_data[uart].parity     = parity;
0156   uart_data[uart].stopbits   = stopbits;
0157   uart_data[uart].hwFlow     = hwFlow;
0158   return;
0159 }
0160 
0161 /*
0162  * Set baud
0163  */
0164 
0165 void
0166 BSP_uart_set_baud(
0167   int uart,
0168   unsigned long baud
0169 )
0170 {
0171   /* Sanity check */
0172   assert(uart == BSP_UART_COM1 || uart == BSP_UART_COM2);
0173 
0174   BSP_uart_set_attributes( uart, baud, uart_data[uart].databits,
0175     uart_data[uart].parity, uart_data[uart].stopbits );
0176 }
0177 
0178 /*
0179  *  Set all attributes
0180  */
0181 
0182 void
0183 BSP_uart_set_attributes
0184 (
0185   int uart,
0186   unsigned long baud,
0187   unsigned long databits,
0188   unsigned long parity,
0189   unsigned long stopbits
0190 )
0191 {
0192   unsigned char mcr, ier;
0193 
0194   /* Sanity check */
0195   assert(uart == BSP_UART_COM1 || uart == BSP_UART_COM2);
0196 
0197   /*
0198    * This function may be called whenever TERMIOS parameters
0199    * are changed, so we have to make sure that baud change is
0200    * indeed required
0201    */
0202 
0203   if( (baud     == uart_data[uart].baud)     &&
0204       (databits == uart_data[uart].databits) &&
0205       (parity   == uart_data[uart].parity)   &&
0206       (stopbits == uart_data[uart].stopbits) )
0207     {
0208       return;
0209     }
0210 
0211   mcr = uread(uart, MCR);
0212   ier = uread(uart, IER);
0213 
0214   BSP_uart_init(uart, baud, databits, parity, stopbits, uart_data[uart].hwFlow);
0215 
0216   uwrite(uart, MCR, mcr);
0217   uwrite(uart, IER, ier);
0218 
0219   return;
0220 }
0221 
0222 /*
0223  * Enable/disable interrupts
0224  */
0225 void
0226 BSP_uart_intr_ctrl(int uart, int cmd)
0227 {
0228   int iStatus = (int)INTERRUPT_DISABLE;
0229 
0230   assert(uart == BSP_UART_COM1 || uart == BSP_UART_COM2);
0231 
0232   switch(cmd)
0233     {
0234     case BSP_UART_INTR_CTRL_ENABLE:
0235       iStatus |= (RECEIVE_ENABLE | RECEIVER_LINE_ST_ENABLE | TRANSMIT_ENABLE);
0236       if ( uart_data[uart].hwFlow ) {
0237         iStatus |= MODEM_ENABLE;
0238       }
0239       break;
0240     case BSP_UART_INTR_CTRL_TERMIOS:
0241       iStatus |= (RECEIVE_ENABLE | RECEIVER_LINE_ST_ENABLE);
0242       if ( uart_data[uart].hwFlow ) {
0243         iStatus |= MODEM_ENABLE;
0244       }
0245       break;
0246     case BSP_UART_INTR_CTRL_GDB:
0247       iStatus |= RECEIVE_ENABLE;
0248       break;
0249     }
0250 
0251   uart_data[uart].ier = iStatus;
0252   uwrite(uart, IER, iStatus);
0253 
0254   return;
0255 }
0256 
0257 void
0258 BSP_uart_throttle(int uart)
0259 {
0260   unsigned int mcr;
0261 
0262   assert(uart == BSP_UART_COM1 || uart == BSP_UART_COM2);
0263 
0264   if(!uart_data[uart].hwFlow)
0265     {
0266       /* Should not happen */
0267       assert(0);
0268       return;
0269     }
0270   mcr = uread (uart, MCR);
0271   /* RTS down */
0272   mcr &= ~RTS;
0273   uwrite(uart, MCR, mcr);
0274 
0275   return;
0276 }
0277 
0278 void
0279 BSP_uart_unthrottle(int uart)
0280 {
0281   unsigned int mcr;
0282 
0283   assert(uart == BSP_UART_COM1 || uart == BSP_UART_COM2);
0284 
0285   if(!uart_data[uart].hwFlow)
0286     {
0287       /* Should not happen */
0288       assert(0);
0289       return;
0290     }
0291   mcr = uread (uart, MCR);
0292   /* RTS up */
0293   mcr |= RTS;
0294   uwrite(uart, MCR, mcr);
0295 
0296   return;
0297 }
0298 
0299 /*
0300  * Status function, -1 if error
0301  * detected, 0 if no received chars available,
0302  * 1 if received char available, 2 if break
0303  * is detected, it will eat break and error
0304  * chars. It ignores overruns - we cannot do
0305  * anything about - it execpt count statistics
0306  * and we are not counting it.
0307  */
0308 int
0309 BSP_uart_polled_status(int uart)
0310 {
0311   unsigned char val;
0312 
0313   assert(uart == BSP_UART_COM1 || uart == BSP_UART_COM2);
0314 
0315   val = uread(uart, LSR);
0316 
0317   if(val & BI)
0318     {
0319       /* BREAK found, eat character */
0320       uread(uart, RBR);
0321       return BSP_UART_STATUS_BREAK;
0322     }
0323 
0324   if((val & (DR | OE | FE)) ==  1)
0325     {
0326       /* No error, character present */
0327       return BSP_UART_STATUS_CHAR;
0328     }
0329 
0330   if((val & (DR | OE | FE)) == 0)
0331     {
0332       /* Nothing */
0333       return BSP_UART_STATUS_NOCHAR;
0334     }
0335 
0336   /*
0337    * Framing or parity error
0338    * eat character
0339    */
0340   uread(uart, RBR);
0341 
0342   return BSP_UART_STATUS_ERROR;
0343 }
0344 
0345 /*
0346  * Polled mode write function
0347  */
0348 void
0349 BSP_uart_polled_write(int uart, int val)
0350 {
0351   unsigned char val1;
0352 
0353   /* Sanity check */
0354   assert(uart == BSP_UART_COM1 || uart == BSP_UART_COM2);
0355 
0356   for(;;)
0357     {
0358       if((val1=uread(uart, LSR)) & THRE)
0359     {
0360       break;
0361     }
0362     }
0363 
0364   if(uart_data[uart].hwFlow)
0365     {
0366       for(;;)
0367     {
0368       if(uread(uart, MSR) & CTS)
0369         {
0370           break;
0371         }
0372     }
0373     }
0374 
0375   uwrite(uart, THR, val & 0xff);
0376 
0377   /*
0378    * Wait for character to be transmitted.
0379    * This ensures that printk and printf play nicely together
0380    * when using the same serial port.
0381    * Yes, there's a performance hit here, but if we're doing
0382    * polled writes to a serial port we're probably not that
0383    * interested in efficiency anyway.....
0384    */
0385   for(;;)
0386     {
0387       if((val1=uread(uart, LSR)) & THRE)
0388       {
0389       break;
0390       }
0391     }
0392 
0393   return;
0394 }
0395 
0396 void
0397 BSP_output_char_via_serial(char val)
0398 {
0399   BSP_uart_polled_write(BSPConsolePort, val);
0400 }
0401 
0402 /*
0403  * Polled mode read function
0404  */
0405 int
0406 BSP_uart_polled_read(int uart)
0407 {
0408   unsigned char val;
0409 
0410   assert(uart == BSP_UART_COM1 || uart == BSP_UART_COM2);
0411 
0412   for(;;)
0413     {
0414       if(uread(uart, LSR) & DR)
0415     {
0416       break;
0417     }
0418     }
0419 
0420   val = uread(uart, RBR);
0421 
0422   return (int)(val & 0xff);
0423 }
0424 
0425 int
0426 BSP_poll_char_via_serial(void)
0427 {
0428     return BSP_uart_polled_read(BSPConsolePort);
0429 }
0430 
0431 /* ================ Termios support  =================*/
0432 
0433 static volatile int  termios_stopped_com1        = 0;
0434 static volatile int  termios_tx_active_com1      = 0;
0435 static void*         termios_ttyp_com1           = NULL;
0436 static char          termios_tx_hold_com1        = 0;
0437 static volatile char termios_tx_hold_valid_com1  = 0;
0438 
0439 static volatile int  termios_stopped_com2        = 0;
0440 static volatile int  termios_tx_active_com2      = 0;
0441 static void*         termios_ttyp_com2           = NULL;
0442 static char          termios_tx_hold_com2        = 0;
0443 static volatile char termios_tx_hold_valid_com2  = 0;
0444 
0445 static void ( *driver_input_handler_com1 )( void *,  char *, int ) = 0;
0446 static void ( *driver_input_handler_com2 )( void *,  char *, int ) = 0;
0447 
0448 /*
0449  * Set channel parameters
0450  */
0451 void
0452 BSP_uart_termios_set(int uart, void *ttyp)
0453 {
0454   struct rtems_termios_tty *p = (struct rtems_termios_tty *)ttyp;
0455   unsigned char val;
0456   assert(uart == BSP_UART_COM1 || uart == BSP_UART_COM2);
0457 
0458   if(uart == BSP_UART_COM1)
0459     {
0460       uart_data[uart].ioMode = p->device.outputUsesInterrupts;
0461       if(uart_data[uart].hwFlow)
0462     {
0463       val = uread(uart, MSR);
0464 
0465       termios_stopped_com1   = (val & CTS) ? 0 : 1;
0466     }
0467       else
0468     {
0469       termios_stopped_com1 = 0;
0470     }
0471       termios_tx_active_com1      = 0;
0472       termios_ttyp_com1           = ttyp;
0473       termios_tx_hold_com1        = 0;
0474       termios_tx_hold_valid_com1  = 0;
0475     }
0476   else
0477     {
0478       uart_data[uart].ioMode = p->device.outputUsesInterrupts;
0479       if(uart_data[uart].hwFlow)
0480     {
0481       val = uread(uart, MSR);
0482 
0483       termios_stopped_com2   = (val & CTS) ? 0 : 1;
0484     }
0485       else
0486     {
0487       termios_stopped_com2 = 0;
0488     }
0489       termios_tx_active_com2      = 0;
0490       termios_ttyp_com2           = ttyp;
0491       termios_tx_hold_com2        = 0;
0492       termios_tx_hold_valid_com2  = 0;
0493     }
0494 
0495   return;
0496 }
0497 
0498 int
0499 BSP_uart_termios_read_com1(int uart)
0500 {
0501   int     off = (int)0;
0502   char    buf[40];
0503 
0504   /* read bytes */
0505   while (( off < sizeof(buf) ) && ( uread(BSP_UART_COM1, LSR) & DR )) {
0506     buf[off++] = uread(BSP_UART_COM1, RBR);
0507   }
0508 
0509   /* write out data */
0510   if ( off > 0 ) {
0511     rtems_termios_enqueue_raw_characters(termios_ttyp_com1, buf, off);
0512   }
0513 
0514   /* enable receive interrupts */
0515   uart_data[BSP_UART_COM1].ier |= (RECEIVE_ENABLE | RECEIVER_LINE_ST_ENABLE);
0516   uwrite(BSP_UART_COM1, IER, uart_data[BSP_UART_COM1].ier);
0517 
0518   return ( EOF );
0519 }
0520 
0521 int
0522 BSP_uart_termios_read_com2(int uart)
0523 {
0524   int     off = (int)0;
0525   char    buf[40];
0526 
0527   /* read current byte */
0528   while (( off < sizeof(buf) ) && ( uread(BSP_UART_COM2, LSR) & DR )) {
0529     buf[off++] = uread(BSP_UART_COM2, RBR);
0530   }
0531 
0532   /* write out data */
0533   if ( off > 0 ) {
0534     rtems_termios_enqueue_raw_characters(termios_ttyp_com2, buf, off);
0535   }
0536 
0537   /* enable receive interrupts */
0538   uart_data[BSP_UART_COM2].ier |= (RECEIVE_ENABLE | RECEIVER_LINE_ST_ENABLE);
0539   uwrite(BSP_UART_COM2, IER, uart_data[BSP_UART_COM2].ier);
0540 
0541   return ( EOF );
0542 }
0543 
0544 ssize_t
0545 BSP_uart_termios_write_com1(int minor, const char *buf, size_t len)
0546 {
0547   if(len <= 0)
0548     {
0549       return 0;
0550     }
0551 
0552   assert(buf != NULL);
0553 
0554   /* If there TX buffer is busy - something is royally screwed up */
0555   assert((uread(BSP_UART_COM1, LSR) & THRE) != 0);
0556 
0557   if(termios_stopped_com1)
0558     {
0559       /* CTS low */
0560       termios_tx_hold_com1       = *buf;
0561       termios_tx_hold_valid_com1 = 1;
0562       return 0;
0563     }
0564 
0565   /* Write character */
0566   uwrite(BSP_UART_COM1, THR, *buf & 0xff);
0567 
0568   /* Enable interrupts if necessary */
0569   if ( !termios_tx_active_com1 ) {
0570     termios_tx_active_com1 = 1;
0571     uart_data[BSP_UART_COM1].ier |= TRANSMIT_ENABLE;
0572     uwrite(BSP_UART_COM1, IER, uart_data[BSP_UART_COM1].ier);
0573   }
0574 
0575   return 1;
0576 }
0577 
0578 ssize_t
0579 BSP_uart_termios_write_com2(int minor, const char *buf, size_t len)
0580 {
0581   if(len <= 0)
0582     {
0583       return 0;
0584     }
0585 
0586   assert(buf != NULL);
0587 
0588   /* If there TX buffer is busy - something is royally screwed up */
0589   assert((uread(BSP_UART_COM2, LSR) & THRE) != 0);
0590 
0591   if(termios_stopped_com2)
0592     {
0593       /* CTS low */
0594       termios_tx_hold_com2       = *buf;
0595       termios_tx_hold_valid_com2 = 1;
0596       return 0;
0597     }
0598 
0599   /* Write character */
0600   uwrite(BSP_UART_COM2, THR, *buf & 0xff);
0601 
0602   /* Enable interrupts if necessary */
0603   if ( !termios_tx_active_com2 ) {
0604     termios_tx_active_com2 = 1;
0605     uart_data[BSP_UART_COM2].ier |= TRANSMIT_ENABLE;
0606     uwrite(BSP_UART_COM2, IER, uart_data[BSP_UART_COM2].ier);
0607   }
0608 
0609   return 1;
0610 }
0611 
0612 void
0613 BSP_uart_termios_isr_com1(void *ignored)
0614 {
0615   unsigned char buf[40];
0616   unsigned char val;
0617   int      off, ret, vect;
0618 
0619   off = 0;
0620 
0621   for(;;)
0622     {
0623       vect = uread(BSP_UART_COM1, IIR) & 0xf;
0624 
0625       switch(vect)
0626     {
0627     case MODEM_STATUS :
0628       val = uread(BSP_UART_COM1, MSR);
0629       if(uart_data[BSP_UART_COM1].hwFlow)
0630         {
0631           if(val & CTS)
0632         {
0633           /* CTS high */
0634           termios_stopped_com1 = 0;
0635           if(termios_tx_hold_valid_com1)
0636             {
0637               termios_tx_hold_valid_com1 = 0;
0638               BSP_uart_termios_write_com1(0, &termios_tx_hold_com1,
0639                             1);
0640             }
0641         }
0642           else
0643         {
0644           /* CTS low */
0645           termios_stopped_com1 = 1;
0646         }
0647         }
0648       break;
0649     case NO_MORE_INTR :
0650       /* No more interrupts */
0651       if(off != 0)
0652         {
0653           /* Update rx buffer */
0654          if( driver_input_handler_com1 )
0655          {
0656              driver_input_handler_com1( termios_ttyp_com1, (char *)buf, off );
0657          }
0658          else
0659          {
0660             /* Update rx buffer */
0661              rtems_termios_enqueue_raw_characters(termios_ttyp_com1, (char *)buf, off );
0662          }
0663         }
0664       return;
0665     case TRANSMITTER_HODING_REGISTER_EMPTY :
0666       /*
0667        * TX holding empty: we have to disable these interrupts
0668        * if there is nothing more to send.
0669        */
0670 
0671       /* If nothing else to send disable interrupts */
0672       ret = rtems_termios_dequeue_characters(termios_ttyp_com1, 1);
0673           if ( ret == 0 ) {
0674             termios_tx_active_com1 = 0;
0675             uart_data[BSP_UART_COM1].ier &= ~(TRANSMIT_ENABLE);
0676             uwrite(BSP_UART_COM1, IER, uart_data[BSP_UART_COM1].ier);
0677           }
0678       break;
0679     case RECEIVER_DATA_AVAIL :
0680     case CHARACTER_TIMEOUT_INDICATION:
0681           if ( uart_data[BSP_UART_COM1].ioMode == TERMIOS_TASK_DRIVEN ) {
0682             /* ensure interrupts are enabled */
0683             if ( uart_data[BSP_UART_COM1].ier & RECEIVE_ENABLE ) {
0684               /* disable interrupts and notify termios */
0685               uart_data[BSP_UART_COM1].ier &= ~(RECEIVE_ENABLE | RECEIVER_LINE_ST_ENABLE);
0686               uwrite(BSP_UART_COM1, IER, uart_data[BSP_UART_COM1].ier);
0687               rtems_termios_rxirq_occured(termios_ttyp_com1);
0688             }
0689           }
0690           else {
0691         /* RX data ready */
0692         assert(off < sizeof(buf));
0693         buf[off++] = uread(BSP_UART_COM1, RBR);
0694           }
0695       break;
0696     case RECEIVER_ERROR:
0697       /* RX error: eat character */
0698        uartError(BSP_UART_COM1);
0699       break;
0700     default:
0701       /* Should not happen */
0702       assert(0);
0703       return;
0704     }
0705     }
0706 }
0707 
0708 void
0709 BSP_uart_termios_isr_com2(void *ignored)
0710 {
0711   unsigned char buf[40];
0712   unsigned char val;
0713   int      off, ret, vect;
0714 
0715   off = 0;
0716 
0717   for(;;)
0718     {
0719       vect = uread(BSP_UART_COM2, IIR) & 0xf;
0720 
0721       switch(vect)
0722     {
0723     case MODEM_STATUS :
0724       val = uread(BSP_UART_COM2, MSR);
0725       if(uart_data[BSP_UART_COM2].hwFlow)
0726         {
0727           if(val & CTS)
0728         {
0729           /* CTS high */
0730           termios_stopped_com2 = 0;
0731           if(termios_tx_hold_valid_com2)
0732             {
0733               termios_tx_hold_valid_com2 = 0;
0734               BSP_uart_termios_write_com2(0, &termios_tx_hold_com2,
0735                             1);
0736             }
0737         }
0738           else
0739         {
0740           /* CTS low */
0741           termios_stopped_com2 = 1;
0742         }
0743         }
0744       break;
0745     case NO_MORE_INTR :
0746       /* No more interrupts */
0747       if(off != 0)
0748         {
0749           /* Update rx buffer */
0750          if( driver_input_handler_com2 )
0751          {
0752              driver_input_handler_com2( termios_ttyp_com2, (char *)buf, off );
0753          }
0754          else
0755          {
0756             rtems_termios_enqueue_raw_characters(termios_ttyp_com2, (char *)buf, off);
0757          }
0758         }
0759       return;
0760     case TRANSMITTER_HODING_REGISTER_EMPTY :
0761       /*
0762        * TX holding empty: we have to disable these interrupts
0763        * if there is nothing more to send.
0764        */
0765 
0766       /* If nothing else to send disable interrupts */
0767       ret = rtems_termios_dequeue_characters(termios_ttyp_com2, 1);
0768           if ( ret == 0 ) {
0769             termios_tx_active_com2 = 0;
0770             uart_data[BSP_UART_COM2].ier &= ~(TRANSMIT_ENABLE);
0771             uwrite(BSP_UART_COM2, IER, uart_data[BSP_UART_COM2].ier);
0772           }
0773       break;
0774     case RECEIVER_DATA_AVAIL :
0775     case CHARACTER_TIMEOUT_INDICATION:
0776           if ( uart_data[BSP_UART_COM2].ioMode == TERMIOS_TASK_DRIVEN ) {
0777             /* ensure interrupts are enabled */
0778             if ( uart_data[BSP_UART_COM2].ier & RECEIVE_ENABLE ) {
0779               /* disable interrupts and notify termios */
0780               uart_data[BSP_UART_COM2].ier &= ~(RECEIVE_ENABLE | RECEIVER_LINE_ST_ENABLE);
0781               uwrite(BSP_UART_COM2, IER, uart_data[BSP_UART_COM2].ier);
0782               rtems_termios_rxirq_occured(termios_ttyp_com2);
0783             }
0784           }
0785           else {
0786         /* RX data ready */
0787         assert(off < sizeof(buf));
0788         buf[off++] = uread(BSP_UART_COM2, RBR);
0789           }
0790       break;
0791     case RECEIVER_ERROR:
0792       /* RX error: eat character */
0793        uartError(BSP_UART_COM2);
0794       break;
0795     default:
0796       /* Should not happen */
0797       assert(0);
0798       return;
0799     }
0800     }
0801 }
0802 
0803 /* ================= GDB support     ===================*/
0804 int BSP_uart_dbgisr_com_regsav[4] RTEMS_UNUSED;
0805 
0806 /*
0807  * Interrupt service routine for COM1 - all,
0808  * it does it check whether ^C is received
0809  * if yes it will flip TF bit before returning
0810  * Note: it should be installed as raw interrupt
0811  * handler
0812  */
0813 
0814 __asm__ (".p2align 4");
0815 __asm__ (".text");
0816 __asm__ (".globl BSP_uart_dbgisr_com1");
0817 __asm__ ("BSP_uart_dbgisr_com1:");
0818 __asm__ ("    movl %eax, BSP_uart_dbgisr_com_regsav");          /* Save eax */
0819 __asm__ ("    movl %ebx, BSP_uart_dbgisr_com_regsav + 4");      /* Save ebx */
0820 __asm__ ("    movl %edx, BSP_uart_dbgisr_com_regsav + 8");      /* Save edx */
0821 
0822 __asm__ ("    movl $0, %ebx");           /* Clear flag */
0823 
0824 /*
0825  * We know that only receive related interrupts
0826  * are available, eat chars
0827  */
0828 __asm__ ("uart_dbgisr_com1_1:");
0829 __asm__ ("    movw $0x3FD, %dx");
0830 __asm__ ("    inb  %dx, %al"); /* Read LSR */
0831 __asm__ ("    andb $1, %al");
0832 __asm__ ("    cmpb $0, %al");
0833 __asm__ ("    je   uart_dbgisr_com1_2");
0834 __asm__ ("    movw $0x3F8, %dx");
0835 __asm__ ("    inb  %dx, %al");    /* Get input character */
0836 __asm__ ("    cmpb $3, %al");
0837 __asm__ ("    jne  uart_dbgisr_com1_1");
0838 
0839 /* ^C received, set flag */
0840 __asm__ ("    movl $1, %ebx");
0841 __asm__ ("    jmp uart_dbgisr_com1_1");
0842 
0843 /* All chars read */
0844 __asm__ ("uart_dbgisr_com1_2:");
0845 
0846 /* If flag is set we have to tweak TF */
0847 __asm__ ("   cmpl $0, %ebx");
0848 __asm__ ("   je   uart_dbgisr_com1_3");
0849 
0850 /* Flag is set */
0851 __asm__ ("   movl BSP_uart_dbgisr_com_regsav+4, %ebx");     /* Restore ebx */
0852 __asm__ ("   movl BSP_uart_dbgisr_com_regsav+8, %edx");     /* Restore edx */
0853 
0854 /* Set TF bit */
0855 __asm__ ("   popl  %eax");                       /* Pop eip */
0856 __asm__ ("   movl  %eax, BSP_uart_dbgisr_com_regsav + 4");  /* Save it */
0857 __asm__ ("   popl  %eax");                       /* Pop cs */
0858 __asm__ ("   movl  %eax, BSP_uart_dbgisr_com_regsav + 8");  /* Save it */
0859 __asm__ ("   popl  %eax");                       /* Pop flags */
0860 __asm__ ("   orl   $0x100, %eax");               /* Modify it */
0861 __asm__ ("   pushl %eax");                       /* Push it back */
0862 __asm__ ("   movl  BSP_uart_dbgisr_com_regsav+8, %eax");    /* Put back cs */
0863 __asm__ ("   pushl %eax");
0864 __asm__ ("   movl  BSP_uart_dbgisr_com_regsav+4, %eax");    /* Put back eip */
0865 __asm__ ("   pushl %eax");
0866 
0867 /* Acknowledge IRQ */
0868 __asm__ ("   movb  $0x20, %al");
0869 __asm__ ("   outb  %al, $0x20");
0870 __asm__ ("   movl  BSP_uart_dbgisr_com_regsav, %eax");      /* Restore eax */
0871 __asm__ ("   iret");                             /* Done */
0872 
0873 /* Flag is not set */
0874 __asm__ ("uart_dbgisr_com1_3:");
0875 __asm__ ("   movl BSP_uart_dbgisr_com_regsav+4, %ebx");     /* Restore ebx */
0876 __asm__ ("   movl BSP_uart_dbgisr_com_regsav+8, %edx");     /* Restore edx */
0877 
0878 /* Acknowledge irq */
0879 __asm__ ("   movb  $0x20, %al");
0880 __asm__ ("   outb  %al, $0x20");
0881 __asm__ ("   movl  BSP_uart_dbgisr_com_regsav, %eax");      /* Restore eax */
0882 __asm__ ("   iret");                 /* Done */
0883 
0884 /*
0885  * Interrupt service routine for COM2 - all,
0886  * it does it check whether ^C is received
0887  * if yes it will flip TF bit before returning
0888  * Note: it has to be installed as raw interrupt
0889  * handler
0890  */
0891 __asm__ (".p2align 4");
0892 __asm__ (".text");
0893 __asm__ (".globl BSP_uart_dbgisr_com2");
0894 __asm__ ("BSP_uart_dbgisr_com2:");
0895 __asm__ ("    movl %eax, BSP_uart_dbgisr_com_regsav");          /* Save eax */
0896 __asm__ ("    movl %ebx, BSP_uart_dbgisr_com_regsav + 4");      /* Save ebx */
0897 __asm__ ("    movl %edx, BSP_uart_dbgisr_com_regsav + 8");      /* Save edx */
0898 
0899 __asm__ ("    movl $0, %ebx");           /* Clear flag */
0900 
0901 /*
0902  * We know that only receive related interrupts
0903  * are available, eat chars
0904  */
0905 __asm__ ("uart_dbgisr_com2_1:");
0906 __asm__ ("    movw $0x2FD, %dx");
0907 __asm__ ("    inb  %dx, %al"); /* Read LSR */
0908 __asm__ ("    andb $1, %al");
0909 __asm__ ("    cmpb $0, %al");
0910 __asm__ ("    je   uart_dbgisr_com2_2");
0911 __asm__ ("    movw $0x2F8, %dx");
0912 __asm__ ("    inb  %dx, %al");    /* Get input character */
0913 __asm__ ("    cmpb $3, %al");
0914 __asm__ ("    jne  uart_dbgisr_com2_1");
0915 
0916 /* ^C received, set flag */
0917 __asm__ ("    movl $1, %ebx");
0918 __asm__ ("    jmp uart_dbgisr_com2_1");
0919 
0920 /* All chars read */
0921 __asm__ ("uart_dbgisr_com2_2:");
0922 
0923 /* If flag is set we have to tweak TF */
0924 __asm__ ("   cmpl $0, %ebx");
0925 __asm__ ("   je   uart_dbgisr_com2_3");
0926 
0927 /* Flag is set */
0928 __asm__ ("   movl BSP_uart_dbgisr_com_regsav+4, %ebx");     /* Restore ebx */
0929 __asm__ ("   movl BSP_uart_dbgisr_com_regsav+8, %edx");     /* Restore edx */
0930 
0931 /* Set TF bit */
0932 __asm__ ("   popl  %eax");           /* Pop eip */
0933 __asm__ ("   movl  %eax, BSP_uart_dbgisr_com_regsav + 4");  /* Save it */
0934 __asm__ ("   popl  %eax");           /* Pop cs */
0935 __asm__ ("   movl  %eax, BSP_uart_dbgisr_com_regsav + 8");  /* Save it */
0936 __asm__ ("   popl  %eax");           /* Pop flags */
0937 __asm__ ("   orl   $0x100, %eax");   /* Modify it */
0938 __asm__ ("   pushl %eax");           /* Push it back */
0939 __asm__ ("   movl  BSP_uart_dbgisr_com_regsav+8, %eax");    /* Put back cs */
0940 __asm__ ("   pushl %eax");
0941 __asm__ ("   movl  BSP_uart_dbgisr_com_regsav+4, %eax");    /* Put back eip */
0942 __asm__ ("   pushl %eax");
0943 
0944 /* Acknowledge IRQ */
0945 __asm__ ("   movb  $0x20, %al");
0946 __asm__ ("   outb  %al, $0x20");
0947 __asm__ ("   movl  BSP_uart_dbgisr_com_regsav, %eax");      /* Restore eax */
0948 __asm__ ("   iret");                 /* Done */
0949 
0950 /* Flag is not set */
0951 __asm__ ("uart_dbgisr_com2_3:");
0952 __asm__ ("   movl BSP_uart_dbgisr_com_regsav+4, %ebx");     /* Restore ebx */
0953 __asm__ ("   movl BSP_uart_dbgisr_com_regsav+8, %edx");     /* Restore edx */
0954 
0955 /* Acknowledge irq */
0956 __asm__ ("   movb  $0x20, %al");
0957 __asm__ ("   outb  %al, $0x20");
0958 __asm__ ("   movl  BSP_uart_dbgisr_com_regsav, %eax");      /* Restore eax */
0959 __asm__ ("   iret");                 /* Done */