source: rtems/c/src/lib/libbsp/i386/shared/comm/uart.c @ 1bc0ad2

5
Last change on this file since 1bc0ad2 was 1bc0ad2, checked in by Sebastian Huber <sebastian.huber@…>, on 09/08/17 at 08:38:46

Simplify and unify BSP_output_char

The BSP_output_char should output a char and not mingle with high level
processing, e.g. '\n' to '\r\n' translation. Move this translation to
rtems_putc(). Remove it from all the BSP_output_char implementations.

Close #3122.

  • Property mode set to 100644
File size: 22.6 KB
Line 
1/*
2 * This software is Copyright (C) 1998 by T.sqware - all rights limited
3 * It is provided in to the public domain "as is", can be freely modified
4 * as far as this copyight notice is kept unchanged, but does not imply
5 * an endorsement by T.sqware of the product in which it is included.
6 */
7
8#include <stdio.h>
9#include <bsp.h>
10#include <bsp/irq.h>
11#include <uart.h>
12#include <rtems/libio.h>
13#include <rtems/termiostypes.h>
14#include <termios.h>
15#include <assert.h>
16
17/*
18 * Basic 16552 driver
19 */
20
21struct uart_data
22{
23  int ioMode;
24  int hwFlow;
25  unsigned int  ier;
26  unsigned long baud;
27  unsigned long databits;
28  unsigned long parity;
29  unsigned long stopbits;
30};
31
32static struct uart_data uart_data[2];
33
34/*
35 * Macros to read/write register of uart, if configuration is
36 * different just rewrite these macros
37 */
38
39static inline unsigned char
40uread(int uart, unsigned int reg)
41{
42  register unsigned char val;
43
44  if (uart == 0) {
45    inport_byte(COM1_BASE_IO+reg, val);
46  } else {
47    inport_byte(COM2_BASE_IO+reg, val);
48  }
49
50  return val;
51}
52
53static inline void
54uwrite(int uart, int reg, unsigned int val)
55{
56  if (uart == 0) {
57    outport_byte(COM1_BASE_IO+reg, val);
58  } else {
59    outport_byte(COM2_BASE_IO+reg, val);
60  }
61}
62
63static void
64uartError(int uart)
65{
66  unsigned char uartStatus, dummy;
67
68  uartStatus = uread(uart, LSR);
69  (void) uartStatus; /* avoid set but not used warning */
70  dummy = uread(uart, RBR);
71  (void) dummy;      /* avoid set but not used warning */
72
73#ifdef UARTDEBUG
74  if (uartStatus & OE)
75    printk("********* Over run Error **********\n");
76  if (uartStatus & PE)
77    printk("********* Parity Error   **********\n");
78  if (uartStatus & FE)
79    printk("********* Framing Error  **********\n");
80  if (uartStatus & BI)
81    printk("********* Parity Error   **********\n");
82  if (uartStatus & ERFIFO)
83    printk("********* Error receive Fifo **********\n");
84#endif
85}
86
87/*
88 * Uart initialization, it is hardcoded to 8 bit, no parity,
89 * one stop bit, FIFO, things to be changed
90 * are baud rate and nad hw flow control,
91 * and longest rx fifo setting
92 */
93void
94BSP_uart_init
95(
96  int uart,
97  unsigned long baud,
98  unsigned long databits,
99  unsigned long parity,
100  unsigned long stopbits,
101  int hwFlow
102)
103{
104  /* Sanity check */
105  assert(uart == BSP_UART_COM1 || uart == BSP_UART_COM2);
106
107  switch(baud)
108    {
109    case 50:
110    case 75:
111    case 110:
112    case 134:
113    case 300:
114    case 600:
115    case 1200:
116    case 2400:
117    case 9600:
118    case 19200:
119    case 38400:
120    case 57600:
121    case 115200:
122      break;
123    default:
124      assert(0);
125      return;
126    }
127
128  /* Set DLAB bit to 1 */
129  uwrite(uart, LCR, DLAB);
130
131  /* Set baud rate */
132  uwrite(uart, DLL,  (BSPBaseBaud/baud) & 0xff);
133  uwrite(uart, DLM,  ((BSPBaseBaud/baud) >> 8) & 0xff);
134
135  /* 8-bit, no parity , 1 stop */
136  uwrite(uart, LCR, databits | parity | stopbits);
137
138  /* Set DTR, RTS and OUT2 high */
139  uwrite(uart, MCR, DTR | RTS | OUT_2);
140
141  /* Enable FIFO */
142  uwrite(uart, FCR, FIFO_EN | XMIT_RESET | RCV_RESET | RECEIVE_FIFO_TRIGGER12);
143
144  /* Disable Interrupts */
145  uwrite(uart, IER, 0);
146
147  /* Read status to clear them */
148  uread(uart, LSR);
149  uread(uart, RBR);
150  uread(uart, MSR);
151
152  /* Remember state */
153  uart_data[uart].baud       = baud;
154  uart_data[uart].databits   = databits;
155  uart_data[uart].parity     = parity;
156  uart_data[uart].stopbits   = stopbits;
157  uart_data[uart].hwFlow     = hwFlow;
158  return;
159}
160
161/*
162 * Set baud
163 */
164
165void
166BSP_uart_set_baud(
167  int uart,
168  unsigned long baud
169)
170{
171  /* Sanity check */
172  assert(uart == BSP_UART_COM1 || uart == BSP_UART_COM2);
173
174  BSP_uart_set_attributes( uart, baud, uart_data[uart].databits,
175    uart_data[uart].parity, uart_data[uart].stopbits );
176}
177
178/*
179 *  Set all attributes
180 */
181
182void
183BSP_uart_set_attributes
184(
185  int uart,
186  unsigned long baud,
187  unsigned long databits,
188  unsigned long parity,
189  unsigned long stopbits
190)
191{
192  unsigned char mcr, ier;
193
194  /* Sanity check */
195  assert(uart == BSP_UART_COM1 || uart == BSP_UART_COM2);
196
197  /*
198   * This function may be called whenever TERMIOS parameters
199   * are changed, so we have to make sure that baud change is
200   * indeed required
201   */
202
203  if( (baud     == uart_data[uart].baud)     &&
204      (databits == uart_data[uart].databits) &&
205      (parity   == uart_data[uart].parity)   &&
206      (stopbits == uart_data[uart].stopbits) )
207    {
208      return;
209    }
210
211  mcr = uread(uart, MCR);
212  ier = uread(uart, IER);
213
214  BSP_uart_init(uart, baud, databits, parity, stopbits, uart_data[uart].hwFlow);
215
216  uwrite(uart, MCR, mcr);
217  uwrite(uart, IER, ier);
218
219  return;
220}
221
222/*
223 * Enable/disable interrupts
224 */
225void
226BSP_uart_intr_ctrl(int uart, int cmd)
227{
228  int iStatus = (int)INTERRUPT_DISABLE;
229
230  assert(uart == BSP_UART_COM1 || uart == BSP_UART_COM2);
231
232  switch(cmd)
233    {
234    case BSP_UART_INTR_CTRL_ENABLE:
235      iStatus |= (RECEIVE_ENABLE | RECEIVER_LINE_ST_ENABLE | TRANSMIT_ENABLE);
236      if ( uart_data[uart].hwFlow ) {
237        iStatus |= MODEM_ENABLE;
238      }
239      break;
240    case BSP_UART_INTR_CTRL_TERMIOS:
241      iStatus |= (RECEIVE_ENABLE | RECEIVER_LINE_ST_ENABLE);
242      if ( uart_data[uart].hwFlow ) {
243        iStatus |= MODEM_ENABLE;
244      }
245      break;
246    case BSP_UART_INTR_CTRL_GDB:
247      iStatus |= RECEIVE_ENABLE;
248      break;
249    }
250
251  uart_data[uart].ier = iStatus;
252  uwrite(uart, IER, iStatus);
253
254  return;
255}
256
257void
258BSP_uart_throttle(int uart)
259{
260  unsigned int mcr;
261
262  assert(uart == BSP_UART_COM1 || uart == BSP_UART_COM2);
263
264  if(!uart_data[uart].hwFlow)
265    {
266      /* Should not happen */
267      assert(0);
268      return;
269    }
270  mcr = uread (uart, MCR);
271  /* RTS down */
272  mcr &= ~RTS;
273  uwrite(uart, MCR, mcr);
274
275  return;
276}
277
278void
279BSP_uart_unthrottle(int uart)
280{
281  unsigned int mcr;
282
283  assert(uart == BSP_UART_COM1 || uart == BSP_UART_COM2);
284
285  if(!uart_data[uart].hwFlow)
286    {
287      /* Should not happen */
288      assert(0);
289      return;
290    }
291  mcr = uread (uart, MCR);
292  /* RTS up */
293  mcr |= RTS;
294  uwrite(uart, MCR, mcr);
295
296  return;
297}
298
299/*
300 * Status function, -1 if error
301 * detected, 0 if no received chars available,
302 * 1 if received char available, 2 if break
303 * is detected, it will eat break and error
304 * chars. It ignores overruns - we cannot do
305 * anything about - it execpt count statistics
306 * and we are not counting it.
307 */
308int
309BSP_uart_polled_status(int uart)
310{
311  unsigned char val;
312
313  assert(uart == BSP_UART_COM1 || uart == BSP_UART_COM2);
314
315  val = uread(uart, LSR);
316
317  if(val & BI)
318    {
319      /* BREAK found, eat character */
320      uread(uart, RBR);
321      return BSP_UART_STATUS_BREAK;
322    }
323
324  if((val & (DR | OE | FE)) ==  1)
325    {
326      /* No error, character present */
327      return BSP_UART_STATUS_CHAR;
328    }
329
330  if((val & (DR | OE | FE)) == 0)
331    {
332      /* Nothing */
333      return BSP_UART_STATUS_NOCHAR;
334    }
335
336  /*
337   * Framing or parity error
338   * eat character
339   */
340  uread(uart, RBR);
341
342  return BSP_UART_STATUS_ERROR;
343}
344
345/*
346 * Polled mode write function
347 */
348void
349BSP_uart_polled_write(int uart, int val)
350{
351  unsigned char val1;
352
353  /* Sanity check */
354  assert(uart == BSP_UART_COM1 || uart == BSP_UART_COM2);
355
356  for(;;)
357    {
358      if((val1=uread(uart, LSR)) & THRE)
359        {
360          break;
361        }
362    }
363
364  if(uart_data[uart].hwFlow)
365    {
366      for(;;)
367        {
368          if(uread(uart, MSR) & CTS)
369            {
370              break;
371            }
372        }
373    }
374
375  uwrite(uart, THR, val & 0xff);
376
377  /*
378   * Wait for character to be transmitted.
379   * This ensures that printk and printf play nicely together
380   * when using the same serial port.
381   * Yes, there's a performance hit here, but if we're doing
382   * polled writes to a serial port we're probably not that
383   * interested in efficiency anyway.....
384   */
385  for(;;)
386    {
387      if((val1=uread(uart, LSR)) & THRE)
388      {
389      break;
390      }
391    }
392
393  return;
394}
395
396void
397BSP_output_char_via_serial(char val)
398{
399  BSP_uart_polled_write(BSPConsolePort, val);
400}
401
402/*
403 * Polled mode read function
404 */
405int
406BSP_uart_polled_read(int uart)
407{
408  unsigned char val;
409
410  assert(uart == BSP_UART_COM1 || uart == BSP_UART_COM2);
411
412  for(;;)
413    {
414      if(uread(uart, LSR) & DR)
415        {
416          break;
417        }
418    }
419
420  val = uread(uart, RBR);
421
422  return (int)(val & 0xff);
423}
424
425int
426BSP_poll_char_via_serial(void)
427{
428        return BSP_uart_polled_read(BSPConsolePort);
429}
430
431/* ================ Termios support  =================*/
432
433static volatile int  termios_stopped_com1        = 0;
434static volatile int  termios_tx_active_com1      = 0;
435static void*         termios_ttyp_com1           = NULL;
436static char          termios_tx_hold_com1        = 0;
437static volatile char termios_tx_hold_valid_com1  = 0;
438
439static volatile int  termios_stopped_com2        = 0;
440static volatile int  termios_tx_active_com2      = 0;
441static void*         termios_ttyp_com2           = NULL;
442static char          termios_tx_hold_com2        = 0;
443static volatile char termios_tx_hold_valid_com2  = 0;
444
445static void ( *driver_input_handler_com1 )( void *,  char *, int ) = 0;
446static void ( *driver_input_handler_com2 )( void *,  char *, int ) = 0;
447
448/*
449 * Set channel parameters
450 */
451void
452BSP_uart_termios_set(int uart, void *ttyp)
453{
454  struct rtems_termios_tty *p = (struct rtems_termios_tty *)ttyp;
455  unsigned char val;
456  assert(uart == BSP_UART_COM1 || uart == BSP_UART_COM2);
457
458  if(uart == BSP_UART_COM1)
459    {
460      uart_data[uart].ioMode = p->device.outputUsesInterrupts;
461      if(uart_data[uart].hwFlow)
462        {
463          val = uread(uart, MSR);
464
465          termios_stopped_com1   = (val & CTS) ? 0 : 1;
466        }
467      else
468        {
469          termios_stopped_com1 = 0;
470        }
471      termios_tx_active_com1      = 0;
472      termios_ttyp_com1           = ttyp;
473      termios_tx_hold_com1        = 0;
474      termios_tx_hold_valid_com1  = 0;
475    }
476  else
477    {
478      uart_data[uart].ioMode = p->device.outputUsesInterrupts;
479      if(uart_data[uart].hwFlow)
480        {
481          val = uread(uart, MSR);
482
483          termios_stopped_com2   = (val & CTS) ? 0 : 1;
484        }
485      else
486        {
487          termios_stopped_com2 = 0;
488        }
489      termios_tx_active_com2      = 0;
490      termios_ttyp_com2           = ttyp;
491      termios_tx_hold_com2        = 0;
492      termios_tx_hold_valid_com2  = 0;
493    }
494
495  return;
496}
497
498int
499BSP_uart_termios_read_com1(int uart)
500{
501  int     off = (int)0;
502  char    buf[40];
503
504  /* read bytes */
505  while (( off < sizeof(buf) ) && ( uread(BSP_UART_COM1, LSR) & DR )) {
506    buf[off++] = uread(BSP_UART_COM1, RBR);
507  }
508
509  /* write out data */
510  if ( off > 0 ) {
511    rtems_termios_enqueue_raw_characters(termios_ttyp_com1, buf, off);
512  }
513
514  /* enable receive interrupts */
515  uart_data[BSP_UART_COM1].ier |= (RECEIVE_ENABLE | RECEIVER_LINE_ST_ENABLE);
516  uwrite(BSP_UART_COM1, IER, uart_data[BSP_UART_COM1].ier);
517
518  return ( EOF );
519}
520
521int
522BSP_uart_termios_read_com2(int uart)
523{
524  int     off = (int)0;
525  char    buf[40];
526
527  /* read current byte */
528  while (( off < sizeof(buf) ) && ( uread(BSP_UART_COM2, LSR) & DR )) {
529    buf[off++] = uread(BSP_UART_COM2, RBR);
530  }
531
532  /* write out data */
533  if ( off > 0 ) {
534    rtems_termios_enqueue_raw_characters(termios_ttyp_com2, buf, off);
535  }
536
537  /* enable receive interrupts */
538  uart_data[BSP_UART_COM2].ier |= (RECEIVE_ENABLE | RECEIVER_LINE_ST_ENABLE);
539  uwrite(BSP_UART_COM2, IER, uart_data[BSP_UART_COM2].ier);
540
541  return ( EOF );
542}
543
544ssize_t
545BSP_uart_termios_write_com1(int minor, const char *buf, size_t len)
546{
547  if(len <= 0)
548    {
549      return 0;
550    }
551
552  assert(buf != NULL);
553
554  /* If there TX buffer is busy - something is royally screwed up */
555  assert((uread(BSP_UART_COM1, LSR) & THRE) != 0);
556
557  if(termios_stopped_com1)
558    {
559      /* CTS low */
560      termios_tx_hold_com1       = *buf;
561      termios_tx_hold_valid_com1 = 1;
562      return 0;
563    }
564
565  /* Write character */
566  uwrite(BSP_UART_COM1, THR, *buf & 0xff);
567
568  /* Enable interrupts if necessary */
569  if ( !termios_tx_active_com1 ) {
570    termios_tx_active_com1 = 1;
571    uart_data[BSP_UART_COM1].ier |= TRANSMIT_ENABLE;
572    uwrite(BSP_UART_COM1, IER, uart_data[BSP_UART_COM1].ier);
573  }
574
575  return 1;
576}
577
578ssize_t
579BSP_uart_termios_write_com2(int minor, const char *buf, size_t len)
580{
581  if(len <= 0)
582    {
583      return 0;
584    }
585
586  assert(buf != NULL);
587
588  /* If there TX buffer is busy - something is royally screwed up */
589  assert((uread(BSP_UART_COM2, LSR) & THRE) != 0);
590
591  if(termios_stopped_com2)
592    {
593      /* CTS low */
594      termios_tx_hold_com2       = *buf;
595      termios_tx_hold_valid_com2 = 1;
596      return 0;
597    }
598
599  /* Write character */
600  uwrite(BSP_UART_COM2, THR, *buf & 0xff);
601
602  /* Enable interrupts if necessary */
603  if ( !termios_tx_active_com2 ) {
604    termios_tx_active_com2 = 1;
605    uart_data[BSP_UART_COM2].ier |= TRANSMIT_ENABLE;
606    uwrite(BSP_UART_COM2, IER, uart_data[BSP_UART_COM2].ier);
607  }
608
609  return 1;
610}
611
612void
613BSP_uart_termios_isr_com1(void *ignored)
614{
615  unsigned char buf[40];
616  unsigned char val;
617  int      off, ret, vect;
618
619  off = 0;
620
621  for(;;)
622    {
623      vect = uread(BSP_UART_COM1, IIR) & 0xf;
624
625      switch(vect)
626        {
627        case MODEM_STATUS :
628          val = uread(BSP_UART_COM1, MSR);
629          if(uart_data[BSP_UART_COM1].hwFlow)
630            {
631              if(val & CTS)
632                {
633                  /* CTS high */
634                  termios_stopped_com1 = 0;
635                  if(termios_tx_hold_valid_com1)
636                    {
637                      termios_tx_hold_valid_com1 = 0;
638                      BSP_uart_termios_write_com1(0, &termios_tx_hold_com1,
639                                                    1);
640                    }
641                }
642              else
643                {
644                  /* CTS low */
645                  termios_stopped_com1 = 1;
646                }
647            }
648          break;
649        case NO_MORE_INTR :
650          /* No more interrupts */
651          if(off != 0)
652            {
653              /* Update rx buffer */
654         if( driver_input_handler_com1 )
655         {
656             driver_input_handler_com1( termios_ttyp_com1, (char *)buf, off );
657         }
658         else
659         {
660            /* Update rx buffer */
661                 rtems_termios_enqueue_raw_characters(termios_ttyp_com1, (char *)buf, off );
662         }
663            }
664          return;
665        case TRANSMITTER_HODING_REGISTER_EMPTY :
666          /*
667           * TX holding empty: we have to disable these interrupts
668           * if there is nothing more to send.
669           */
670
671          /* If nothing else to send disable interrupts */
672          ret = rtems_termios_dequeue_characters(termios_ttyp_com1, 1);
673          if ( ret == 0 ) {
674            termios_tx_active_com1 = 0;
675            uart_data[BSP_UART_COM1].ier &= ~(TRANSMIT_ENABLE);
676            uwrite(BSP_UART_COM1, IER, uart_data[BSP_UART_COM1].ier);
677          }
678          break;
679        case RECEIVER_DATA_AVAIL :
680        case CHARACTER_TIMEOUT_INDICATION:
681          if ( uart_data[BSP_UART_COM1].ioMode == TERMIOS_TASK_DRIVEN ) {
682            /* ensure interrupts are enabled */
683            if ( uart_data[BSP_UART_COM1].ier & RECEIVE_ENABLE ) {
684              /* disable interrupts and notify termios */
685              uart_data[BSP_UART_COM1].ier &= ~(RECEIVE_ENABLE | RECEIVER_LINE_ST_ENABLE);
686              uwrite(BSP_UART_COM1, IER, uart_data[BSP_UART_COM1].ier);
687              rtems_termios_rxirq_occured(termios_ttyp_com1);
688            }
689          }
690          else {
691            /* RX data ready */
692            assert(off < sizeof(buf));
693            buf[off++] = uread(BSP_UART_COM1, RBR);
694          }
695          break;
696        case RECEIVER_ERROR:
697          /* RX error: eat character */
698           uartError(BSP_UART_COM1);
699          break;
700        default:
701          /* Should not happen */
702          assert(0);
703          return;
704        }
705    }
706}
707
708void
709BSP_uart_termios_isr_com2(void *ignored)
710{
711  unsigned char buf[40];
712  unsigned char val;
713  int      off, ret, vect;
714
715  off = 0;
716
717  for(;;)
718    {
719      vect = uread(BSP_UART_COM2, IIR) & 0xf;
720
721      switch(vect)
722        {
723        case MODEM_STATUS :
724          val = uread(BSP_UART_COM2, MSR);
725          if(uart_data[BSP_UART_COM2].hwFlow)
726            {
727              if(val & CTS)
728                {
729                  /* CTS high */
730                  termios_stopped_com2 = 0;
731                  if(termios_tx_hold_valid_com2)
732                    {
733                      termios_tx_hold_valid_com2 = 0;
734                      BSP_uart_termios_write_com2(0, &termios_tx_hold_com2,
735                                                    1);
736                    }
737                }
738              else
739                {
740                  /* CTS low */
741                  termios_stopped_com2 = 1;
742                }
743            }
744          break;
745        case NO_MORE_INTR :
746          /* No more interrupts */
747          if(off != 0)
748            {
749              /* Update rx buffer */
750         if( driver_input_handler_com2 )
751         {
752             driver_input_handler_com2( termios_ttyp_com2, (char *)buf, off );
753         }
754         else
755         {
756                rtems_termios_enqueue_raw_characters(termios_ttyp_com2, (char *)buf, off);
757         }
758            }
759          return;
760        case TRANSMITTER_HODING_REGISTER_EMPTY :
761          /*
762           * TX holding empty: we have to disable these interrupts
763           * if there is nothing more to send.
764           */
765
766          /* If nothing else to send disable interrupts */
767          ret = rtems_termios_dequeue_characters(termios_ttyp_com2, 1);
768          if ( ret == 0 ) {
769            termios_tx_active_com2 = 0;
770            uart_data[BSP_UART_COM2].ier &= ~(TRANSMIT_ENABLE);
771            uwrite(BSP_UART_COM2, IER, uart_data[BSP_UART_COM2].ier);
772          }
773          break;
774        case RECEIVER_DATA_AVAIL :
775        case CHARACTER_TIMEOUT_INDICATION:
776          if ( uart_data[BSP_UART_COM2].ioMode == TERMIOS_TASK_DRIVEN ) {
777            /* ensure interrupts are enabled */
778            if ( uart_data[BSP_UART_COM2].ier & RECEIVE_ENABLE ) {
779              /* disable interrupts and notify termios */
780              uart_data[BSP_UART_COM2].ier &= ~(RECEIVE_ENABLE | RECEIVER_LINE_ST_ENABLE);
781              uwrite(BSP_UART_COM2, IER, uart_data[BSP_UART_COM2].ier);
782              rtems_termios_rxirq_occured(termios_ttyp_com2);
783            }
784          }
785          else {
786            /* RX data ready */
787            assert(off < sizeof(buf));
788            buf[off++] = uread(BSP_UART_COM2, RBR);
789          }
790          break;
791        case RECEIVER_ERROR:
792          /* RX error: eat character */
793           uartError(BSP_UART_COM2);
794          break;
795        default:
796          /* Should not happen */
797          assert(0);
798          return;
799        }
800    }
801}
802
803/* ================= GDB support     ===================*/
804int BSP_uart_dbgisr_com_regsav[4] RTEMS_UNUSED;
805
806/*
807 * Interrupt service routine for COM1 - all,
808 * it does it check whether ^C is received
809 * if yes it will flip TF bit before returning
810 * Note: it should be installed as raw interrupt
811 * handler
812 */
813
814__asm__ (".p2align 4");
815__asm__ (".text");
816__asm__ (".globl BSP_uart_dbgisr_com1");
817__asm__ ("BSP_uart_dbgisr_com1:");
818__asm__ ("    movl %eax, BSP_uart_dbgisr_com_regsav");          /* Save eax */
819__asm__ ("    movl %ebx, BSP_uart_dbgisr_com_regsav + 4");      /* Save ebx */
820__asm__ ("    movl %edx, BSP_uart_dbgisr_com_regsav + 8");      /* Save edx */
821
822__asm__ ("    movl $0, %ebx");           /* Clear flag */
823
824/*
825 * We know that only receive related interrupts
826 * are available, eat chars
827 */
828__asm__ ("uart_dbgisr_com1_1:");
829__asm__ ("    movw $0x3FD, %dx");
830__asm__ ("    inb  %dx, %al"); /* Read LSR */
831__asm__ ("    andb $1, %al");
832__asm__ ("    cmpb $0, %al");
833__asm__ ("    je   uart_dbgisr_com1_2");
834__asm__ ("    movw $0x3F8, %dx");
835__asm__ ("    inb  %dx, %al");    /* Get input character */
836__asm__ ("    cmpb $3, %al");
837__asm__ ("    jne  uart_dbgisr_com1_1");
838
839/* ^C received, set flag */
840__asm__ ("    movl $1, %ebx");
841__asm__ ("    jmp uart_dbgisr_com1_1");
842
843/* All chars read */
844__asm__ ("uart_dbgisr_com1_2:");
845
846/* If flag is set we have to tweak TF */
847__asm__ ("   cmpl $0, %ebx");
848__asm__ ("   je   uart_dbgisr_com1_3");
849
850/* Flag is set */
851__asm__ ("   movl BSP_uart_dbgisr_com_regsav+4, %ebx");     /* Restore ebx */
852__asm__ ("   movl BSP_uart_dbgisr_com_regsav+8, %edx");     /* Restore edx */
853
854/* Set TF bit */
855__asm__ ("   popl  %eax");                               /* Pop eip */
856__asm__ ("   movl  %eax, BSP_uart_dbgisr_com_regsav + 4");  /* Save it */
857__asm__ ("   popl  %eax");                               /* Pop cs */
858__asm__ ("   movl  %eax, BSP_uart_dbgisr_com_regsav + 8");  /* Save it */
859__asm__ ("   popl  %eax");                               /* Pop flags */
860__asm__ ("   orl   $0x100, %eax");                       /* Modify it */
861__asm__ ("   pushl %eax");                               /* Push it back */
862__asm__ ("   movl  BSP_uart_dbgisr_com_regsav+8, %eax");    /* Put back cs */
863__asm__ ("   pushl %eax");
864__asm__ ("   movl  BSP_uart_dbgisr_com_regsav+4, %eax");    /* Put back eip */
865__asm__ ("   pushl %eax");
866
867/* Acknowledge IRQ */
868__asm__ ("   movb  $0x20, %al");
869__asm__ ("   outb  %al, $0x20");
870__asm__ ("   movl  BSP_uart_dbgisr_com_regsav, %eax");      /* Restore eax */
871__asm__ ("   iret");                                     /* Done */
872
873/* Flag is not set */
874__asm__ ("uart_dbgisr_com1_3:");
875__asm__ ("   movl BSP_uart_dbgisr_com_regsav+4, %ebx");     /* Restore ebx */
876__asm__ ("   movl BSP_uart_dbgisr_com_regsav+8, %edx");     /* Restore edx */
877
878/* Acknowledge irq */
879__asm__ ("   movb  $0x20, %al");
880__asm__ ("   outb  %al, $0x20");
881__asm__ ("   movl  BSP_uart_dbgisr_com_regsav, %eax");      /* Restore eax */
882__asm__ ("   iret");                 /* Done */
883
884/*
885 * Interrupt service routine for COM2 - all,
886 * it does it check whether ^C is received
887 * if yes it will flip TF bit before returning
888 * Note: it has to be installed as raw interrupt
889 * handler
890 */
891__asm__ (".p2align 4");
892__asm__ (".text");
893__asm__ (".globl BSP_uart_dbgisr_com2");
894__asm__ ("BSP_uart_dbgisr_com2:");
895__asm__ ("    movl %eax, BSP_uart_dbgisr_com_regsav");          /* Save eax */
896__asm__ ("    movl %ebx, BSP_uart_dbgisr_com_regsav + 4");      /* Save ebx */
897__asm__ ("    movl %edx, BSP_uart_dbgisr_com_regsav + 8");      /* Save edx */
898
899__asm__ ("    movl $0, %ebx");           /* Clear flag */
900
901/*
902 * We know that only receive related interrupts
903 * are available, eat chars
904 */
905__asm__ ("uart_dbgisr_com2_1:");
906__asm__ ("    movw $0x2FD, %dx");
907__asm__ ("    inb  %dx, %al"); /* Read LSR */
908__asm__ ("    andb $1, %al");
909__asm__ ("    cmpb $0, %al");
910__asm__ ("    je   uart_dbgisr_com2_2");
911__asm__ ("    movw $0x2F8, %dx");
912__asm__ ("    inb  %dx, %al");    /* Get input character */
913__asm__ ("    cmpb $3, %al");
914__asm__ ("    jne  uart_dbgisr_com2_1");
915
916/* ^C received, set flag */
917__asm__ ("    movl $1, %ebx");
918__asm__ ("    jmp uart_dbgisr_com2_1");
919
920/* All chars read */
921__asm__ ("uart_dbgisr_com2_2:");
922
923/* If flag is set we have to tweak TF */
924__asm__ ("   cmpl $0, %ebx");
925__asm__ ("   je   uart_dbgisr_com2_3");
926
927/* Flag is set */
928__asm__ ("   movl BSP_uart_dbgisr_com_regsav+4, %ebx");     /* Restore ebx */
929__asm__ ("   movl BSP_uart_dbgisr_com_regsav+8, %edx");     /* Restore edx */
930
931/* Set TF bit */
932__asm__ ("   popl  %eax");           /* Pop eip */
933__asm__ ("   movl  %eax, BSP_uart_dbgisr_com_regsav + 4");  /* Save it */
934__asm__ ("   popl  %eax");           /* Pop cs */
935__asm__ ("   movl  %eax, BSP_uart_dbgisr_com_regsav + 8");  /* Save it */
936__asm__ ("   popl  %eax");           /* Pop flags */
937__asm__ ("   orl   $0x100, %eax");   /* Modify it */
938__asm__ ("   pushl %eax");           /* Push it back */
939__asm__ ("   movl  BSP_uart_dbgisr_com_regsav+8, %eax");    /* Put back cs */
940__asm__ ("   pushl %eax");
941__asm__ ("   movl  BSP_uart_dbgisr_com_regsav+4, %eax");    /* Put back eip */
942__asm__ ("   pushl %eax");
943
944/* Acknowledge IRQ */
945__asm__ ("   movb  $0x20, %al");
946__asm__ ("   outb  %al, $0x20");
947__asm__ ("   movl  BSP_uart_dbgisr_com_regsav, %eax");      /* Restore eax */
948__asm__ ("   iret");                 /* Done */
949
950/* Flag is not set */
951__asm__ ("uart_dbgisr_com2_3:");
952__asm__ ("   movl BSP_uart_dbgisr_com_regsav+4, %ebx");     /* Restore ebx */
953__asm__ ("   movl BSP_uart_dbgisr_com_regsav+8, %edx");     /* Restore edx */
954
955/* Acknowledge irq */
956__asm__ ("   movb  $0x20, %al");
957__asm__ ("   outb  %al, $0x20");
958__asm__ ("   movl  BSP_uart_dbgisr_com_regsav, %eax");      /* Restore eax */
959__asm__ ("   iret");                 /* Done */
Note: See TracBrowser for help on using the repository browser.