source: rtems/c/src/lib/libbsp/i386/shared/comm/uart.c @ 888fadaf

4.115
Last change on this file since 888fadaf was 888fadaf, checked in by Joel Sherrill <joel.sherrill@…>, on 10/12/14 at 13:31:32

i386/pc386: Clean up and fix warnings

  • Property mode set to 100644
File size: 23.0 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  if (val == '\n') BSP_uart_polled_write(BSPConsolePort,'\r');
401}
402
403/*
404 * Polled mode read function
405 */
406int
407BSP_uart_polled_read(int uart)
408{
409  unsigned char val;
410
411  assert(uart == BSP_UART_COM1 || uart == BSP_UART_COM2);
412
413  for(;;)
414    {
415      if(uread(uart, LSR) & DR)
416        {
417          break;
418        }
419    }
420
421  val = uread(uart, RBR);
422
423  return (int)(val & 0xff);
424}
425
426int
427BSP_poll_char_via_serial(void)
428{
429        return BSP_uart_polled_read(BSPConsolePort);
430}
431
432/* ================ Termios support  =================*/
433
434static volatile int  termios_stopped_com1        = 0;
435static volatile int  termios_tx_active_com1      = 0;
436static void*         termios_ttyp_com1           = NULL;
437static char          termios_tx_hold_com1        = 0;
438static volatile char termios_tx_hold_valid_com1  = 0;
439
440static volatile int  termios_stopped_com2        = 0;
441static volatile int  termios_tx_active_com2      = 0;
442static void*         termios_ttyp_com2           = NULL;
443static char          termios_tx_hold_com2        = 0;
444static volatile char termios_tx_hold_valid_com2  = 0;
445
446static void ( *driver_input_handler_com1 )( void *,  char *, int ) = 0;
447static void ( *driver_input_handler_com2 )( void *,  char *, int ) = 0;
448
449/*
450 * This routine sets the handler to handle the characters received
451 * from the serial port.
452 */
453static void uart_set_driver_handler(
454  int port,
455  void ( *handler )( void *,  char *, int )
456)
457{
458  switch( port )
459  {
460    case BSP_UART_COM1:
461     driver_input_handler_com1 = handler;
462     break;
463
464    case BSP_UART_COM2:
465     driver_input_handler_com2 = handler;
466     break;
467  }
468}
469
470/*
471 * Set channel parameters
472 */
473void
474BSP_uart_termios_set(int uart, void *ttyp)
475{
476  struct rtems_termios_tty *p = (struct rtems_termios_tty *)ttyp;
477  unsigned char val;
478  assert(uart == BSP_UART_COM1 || uart == BSP_UART_COM2);
479
480  if(uart == BSP_UART_COM1)
481    {
482      uart_data[uart].ioMode = p->device.outputUsesInterrupts;
483      if(uart_data[uart].hwFlow)
484        {
485          val = uread(uart, MSR);
486
487          termios_stopped_com1   = (val & CTS) ? 0 : 1;
488        }
489      else
490        {
491          termios_stopped_com1 = 0;
492        }
493      termios_tx_active_com1      = 0;
494      termios_ttyp_com1           = ttyp;
495      termios_tx_hold_com1        = 0;
496      termios_tx_hold_valid_com1  = 0;
497    }
498  else
499    {
500      uart_data[uart].ioMode = p->device.outputUsesInterrupts;
501      if(uart_data[uart].hwFlow)
502        {
503          val = uread(uart, MSR);
504
505          termios_stopped_com2   = (val & CTS) ? 0 : 1;
506        }
507      else
508        {
509          termios_stopped_com2 = 0;
510        }
511      termios_tx_active_com2      = 0;
512      termios_ttyp_com2           = ttyp;
513      termios_tx_hold_com2        = 0;
514      termios_tx_hold_valid_com2  = 0;
515    }
516
517  return;
518}
519
520int
521BSP_uart_termios_read_com1(int uart)
522{
523  int     off = (int)0;
524  char    buf[40];
525
526  /* read bytes */
527  while (( off < sizeof(buf) ) && ( uread(BSP_UART_COM1, LSR) & DR )) {
528    buf[off++] = uread(BSP_UART_COM1, RBR);
529  }
530
531  /* write out data */
532  if ( off > 0 ) {
533    rtems_termios_enqueue_raw_characters(termios_ttyp_com1, buf, off);
534  }
535
536  /* enable receive interrupts */
537  uart_data[BSP_UART_COM1].ier |= (RECEIVE_ENABLE | RECEIVER_LINE_ST_ENABLE);
538  uwrite(BSP_UART_COM1, IER, uart_data[BSP_UART_COM1].ier);
539
540  return ( EOF );
541}
542
543int
544BSP_uart_termios_read_com2(int uart)
545{
546  int     off = (int)0;
547  char    buf[40];
548
549  /* read current byte */
550  while (( off < sizeof(buf) ) && ( uread(BSP_UART_COM2, LSR) & DR )) {
551    buf[off++] = uread(BSP_UART_COM2, RBR);
552  }
553
554  /* write out data */
555  if ( off > 0 ) {
556    rtems_termios_enqueue_raw_characters(termios_ttyp_com2, buf, off);
557  }
558
559  /* enable receive interrupts */
560  uart_data[BSP_UART_COM2].ier |= (RECEIVE_ENABLE | RECEIVER_LINE_ST_ENABLE);
561  uwrite(BSP_UART_COM2, IER, uart_data[BSP_UART_COM2].ier);
562
563  return ( EOF );
564}
565
566ssize_t
567BSP_uart_termios_write_com1(int minor, const char *buf, size_t len)
568{
569  if(len <= 0)
570    {
571      return 0;
572    }
573
574  assert(buf != NULL);
575
576  /* If there TX buffer is busy - something is royally screwed up */
577  assert((uread(BSP_UART_COM1, LSR) & THRE) != 0);
578
579  if(termios_stopped_com1)
580    {
581      /* CTS low */
582      termios_tx_hold_com1       = *buf;
583      termios_tx_hold_valid_com1 = 1;
584      return 0;
585    }
586
587  /* Write character */
588  uwrite(BSP_UART_COM1, THR, *buf & 0xff);
589
590  /* Enable interrupts if necessary */
591  if ( !termios_tx_active_com1 ) {
592    termios_tx_active_com1 = 1;
593    uart_data[BSP_UART_COM1].ier |= TRANSMIT_ENABLE;
594    uwrite(BSP_UART_COM1, IER, uart_data[BSP_UART_COM1].ier);
595  }
596
597  return 1;
598}
599
600ssize_t
601BSP_uart_termios_write_com2(int minor, const char *buf, size_t len)
602{
603  if(len <= 0)
604    {
605      return 0;
606    }
607
608  assert(buf != NULL);
609
610  /* If there TX buffer is busy - something is royally screwed up */
611  assert((uread(BSP_UART_COM2, LSR) & THRE) != 0);
612
613  if(termios_stopped_com2)
614    {
615      /* CTS low */
616      termios_tx_hold_com2       = *buf;
617      termios_tx_hold_valid_com2 = 1;
618      return 0;
619    }
620
621  /* Write character */
622  uwrite(BSP_UART_COM2, THR, *buf & 0xff);
623
624  /* Enable interrupts if necessary */
625  if ( !termios_tx_active_com2 ) {
626    termios_tx_active_com2 = 1;
627    uart_data[BSP_UART_COM2].ier |= TRANSMIT_ENABLE;
628    uwrite(BSP_UART_COM2, IER, uart_data[BSP_UART_COM2].ier);
629  }
630
631  return 1;
632}
633
634void
635BSP_uart_termios_isr_com1(void)
636{
637  unsigned char buf[40];
638  unsigned char val;
639  int      off, ret, vect;
640
641  off = 0;
642
643  for(;;)
644    {
645      vect = uread(BSP_UART_COM1, IIR) & 0xf;
646
647      switch(vect)
648        {
649        case MODEM_STATUS :
650          val = uread(BSP_UART_COM1, MSR);
651          if(uart_data[BSP_UART_COM1].hwFlow)
652            {
653              if(val & CTS)
654                {
655                  /* CTS high */
656                  termios_stopped_com1 = 0;
657                  if(termios_tx_hold_valid_com1)
658                    {
659                      termios_tx_hold_valid_com1 = 0;
660                      BSP_uart_termios_write_com1(0, &termios_tx_hold_com1,
661                                                    1);
662                    }
663                }
664              else
665                {
666                  /* CTS low */
667                  termios_stopped_com1 = 1;
668                }
669            }
670          break;
671        case NO_MORE_INTR :
672          /* No more interrupts */
673          if(off != 0)
674            {
675              /* Update rx buffer */
676         if( driver_input_handler_com1 )
677         {
678             driver_input_handler_com1( termios_ttyp_com1, (char *)buf, off );
679         }
680         else
681         {
682            /* Update rx buffer */
683                 rtems_termios_enqueue_raw_characters(termios_ttyp_com1, (char *)buf, off );
684         }
685            }
686          return;
687        case TRANSMITTER_HODING_REGISTER_EMPTY :
688          /*
689           * TX holding empty: we have to disable these interrupts
690           * if there is nothing more to send.
691           */
692
693          /* If nothing else to send disable interrupts */
694          ret = rtems_termios_dequeue_characters(termios_ttyp_com1, 1);
695          if ( ret == 0 ) {
696            termios_tx_active_com1 = 0;
697            uart_data[BSP_UART_COM1].ier &= ~(TRANSMIT_ENABLE);
698            uwrite(BSP_UART_COM1, IER, uart_data[BSP_UART_COM1].ier);
699          }
700          break;
701        case RECEIVER_DATA_AVAIL :
702        case CHARACTER_TIMEOUT_INDICATION:
703          if ( uart_data[BSP_UART_COM1].ioMode == TERMIOS_TASK_DRIVEN ) {
704            /* ensure interrupts are enabled */
705            if ( uart_data[BSP_UART_COM1].ier & RECEIVE_ENABLE ) {
706              /* disable interrupts and notify termios */
707              uart_data[BSP_UART_COM1].ier &= ~(RECEIVE_ENABLE | RECEIVER_LINE_ST_ENABLE);
708              uwrite(BSP_UART_COM1, IER, uart_data[BSP_UART_COM1].ier);
709              rtems_termios_rxirq_occured(termios_ttyp_com1);
710            }
711          }
712          else {
713            /* RX data ready */
714            assert(off < sizeof(buf));
715            buf[off++] = uread(BSP_UART_COM1, RBR);
716          }
717          break;
718        case RECEIVER_ERROR:
719          /* RX error: eat character */
720           uartError(BSP_UART_COM1);
721          break;
722        default:
723          /* Should not happen */
724          assert(0);
725          return;
726        }
727    }
728}
729
730void
731BSP_uart_termios_isr_com2(void)
732{
733  unsigned char buf[40];
734  unsigned char val;
735  int      off, ret, vect;
736
737  off = 0;
738
739  for(;;)
740    {
741      vect = uread(BSP_UART_COM2, IIR) & 0xf;
742
743      switch(vect)
744        {
745        case MODEM_STATUS :
746          val = uread(BSP_UART_COM2, MSR);
747          if(uart_data[BSP_UART_COM2].hwFlow)
748            {
749              if(val & CTS)
750                {
751                  /* CTS high */
752                  termios_stopped_com2 = 0;
753                  if(termios_tx_hold_valid_com2)
754                    {
755                      termios_tx_hold_valid_com2 = 0;
756                      BSP_uart_termios_write_com2(0, &termios_tx_hold_com2,
757                                                    1);
758                    }
759                }
760              else
761                {
762                  /* CTS low */
763                  termios_stopped_com2 = 1;
764                }
765            }
766          break;
767        case NO_MORE_INTR :
768          /* No more interrupts */
769          if(off != 0)
770            {
771              /* Update rx buffer */
772         if( driver_input_handler_com2 )
773         {
774             driver_input_handler_com2( termios_ttyp_com2, (char *)buf, off );
775         }
776         else
777         {
778                rtems_termios_enqueue_raw_characters(termios_ttyp_com2, (char *)buf, off);
779         }
780            }
781          return;
782        case TRANSMITTER_HODING_REGISTER_EMPTY :
783          /*
784           * TX holding empty: we have to disable these interrupts
785           * if there is nothing more to send.
786           */
787
788          /* If nothing else to send disable interrupts */
789          ret = rtems_termios_dequeue_characters(termios_ttyp_com2, 1);
790          if ( ret == 0 ) {
791            termios_tx_active_com2 = 0;
792            uart_data[BSP_UART_COM2].ier &= ~(TRANSMIT_ENABLE);
793            uwrite(BSP_UART_COM2, IER, uart_data[BSP_UART_COM2].ier);
794          }
795          break;
796        case RECEIVER_DATA_AVAIL :
797        case CHARACTER_TIMEOUT_INDICATION:
798          if ( uart_data[BSP_UART_COM2].ioMode == TERMIOS_TASK_DRIVEN ) {
799            /* ensure interrupts are enabled */
800            if ( uart_data[BSP_UART_COM2].ier & RECEIVE_ENABLE ) {
801              /* disable interrupts and notify termios */
802              uart_data[BSP_UART_COM2].ier &= ~(RECEIVE_ENABLE | RECEIVER_LINE_ST_ENABLE);
803              uwrite(BSP_UART_COM2, IER, uart_data[BSP_UART_COM2].ier);
804              rtems_termios_rxirq_occured(termios_ttyp_com2);
805            }
806          }
807          else {
808            /* RX data ready */
809            assert(off < sizeof(buf));
810            buf[off++] = uread(BSP_UART_COM2, RBR);
811          }
812          break;
813        case RECEIVER_ERROR:
814          /* RX error: eat character */
815           uartError(BSP_UART_COM2);
816          break;
817        default:
818          /* Should not happen */
819          assert(0);
820          return;
821        }
822    }
823}
824
825/* ================= GDB support     ===================*/
826int BSP_uart_dbgisr_com_regsav[4] __attribute__ ((unused));
827
828/*
829 * Interrupt service routine for COM1 - all,
830 * it does it check whether ^C is received
831 * if yes it will flip TF bit before returning
832 * Note: it should be installed as raw interrupt
833 * handler
834 */
835
836__asm__ (".p2align 4");
837__asm__ (".text");
838__asm__ (".globl BSP_uart_dbgisr_com1");
839__asm__ ("BSP_uart_dbgisr_com1:");
840__asm__ ("    movl %eax, BSP_uart_dbgisr_com_regsav");          /* Save eax */
841__asm__ ("    movl %ebx, BSP_uart_dbgisr_com_regsav + 4");      /* Save ebx */
842__asm__ ("    movl %edx, BSP_uart_dbgisr_com_regsav + 8");      /* Save edx */
843
844__asm__ ("    movl $0, %ebx");           /* Clear flag */
845
846/*
847 * We know that only receive related interrupts
848 * are available, eat chars
849 */
850__asm__ ("uart_dbgisr_com1_1:");
851__asm__ ("    movw $0x3FD, %dx");
852__asm__ ("    inb  %dx, %al"); /* Read LSR */
853__asm__ ("    andb $1, %al");
854__asm__ ("    cmpb $0, %al");
855__asm__ ("    je   uart_dbgisr_com1_2");
856__asm__ ("    movw $0x3F8, %dx");
857__asm__ ("    inb  %dx, %al");    /* Get input character */
858__asm__ ("    cmpb $3, %al");
859__asm__ ("    jne  uart_dbgisr_com1_1");
860
861/* ^C received, set flag */
862__asm__ ("    movl $1, %ebx");
863__asm__ ("    jmp uart_dbgisr_com1_1");
864
865/* All chars read */
866__asm__ ("uart_dbgisr_com1_2:");
867
868/* If flag is set we have to tweak TF */
869__asm__ ("   cmpl $0, %ebx");
870__asm__ ("   je   uart_dbgisr_com1_3");
871
872/* Flag is set */
873__asm__ ("   movl BSP_uart_dbgisr_com_regsav+4, %ebx");     /* Restore ebx */
874__asm__ ("   movl BSP_uart_dbgisr_com_regsav+8, %edx");     /* Restore edx */
875
876/* Set TF bit */
877__asm__ ("   popl  %eax");                               /* Pop eip */
878__asm__ ("   movl  %eax, BSP_uart_dbgisr_com_regsav + 4");  /* Save it */
879__asm__ ("   popl  %eax");                               /* Pop cs */
880__asm__ ("   movl  %eax, BSP_uart_dbgisr_com_regsav + 8");  /* Save it */
881__asm__ ("   popl  %eax");                               /* Pop flags */
882__asm__ ("   orl   $0x100, %eax");                       /* Modify it */
883__asm__ ("   pushl %eax");                               /* Push it back */
884__asm__ ("   movl  BSP_uart_dbgisr_com_regsav+8, %eax");    /* Put back cs */
885__asm__ ("   pushl %eax");
886__asm__ ("   movl  BSP_uart_dbgisr_com_regsav+4, %eax");    /* Put back eip */
887__asm__ ("   pushl %eax");
888
889/* Acknowledge IRQ */
890__asm__ ("   movb  $0x20, %al");
891__asm__ ("   outb  %al, $0x20");
892__asm__ ("   movl  BSP_uart_dbgisr_com_regsav, %eax");      /* Restore eax */
893__asm__ ("   iret");                                     /* Done */
894
895/* Flag is not set */
896__asm__ ("uart_dbgisr_com1_3:");
897__asm__ ("   movl BSP_uart_dbgisr_com_regsav+4, %ebx");     /* Restore ebx */
898__asm__ ("   movl BSP_uart_dbgisr_com_regsav+8, %edx");     /* Restore edx */
899
900/* Acknowledge irq */
901__asm__ ("   movb  $0x20, %al");
902__asm__ ("   outb  %al, $0x20");
903__asm__ ("   movl  BSP_uart_dbgisr_com_regsav, %eax");      /* Restore eax */
904__asm__ ("   iret");                 /* Done */
905
906/*
907 * Interrupt service routine for COM2 - all,
908 * it does it check whether ^C is received
909 * if yes it will flip TF bit before returning
910 * Note: it has to be installed as raw interrupt
911 * handler
912 */
913__asm__ (".p2align 4");
914__asm__ (".text");
915__asm__ (".globl BSP_uart_dbgisr_com2");
916__asm__ ("BSP_uart_dbgisr_com2:");
917__asm__ ("    movl %eax, BSP_uart_dbgisr_com_regsav");          /* Save eax */
918__asm__ ("    movl %ebx, BSP_uart_dbgisr_com_regsav + 4");      /* Save ebx */
919__asm__ ("    movl %edx, BSP_uart_dbgisr_com_regsav + 8");      /* Save edx */
920
921__asm__ ("    movl $0, %ebx");           /* Clear flag */
922
923/*
924 * We know that only receive related interrupts
925 * are available, eat chars
926 */
927__asm__ ("uart_dbgisr_com2_1:");
928__asm__ ("    movw $0x2FD, %dx");
929__asm__ ("    inb  %dx, %al"); /* Read LSR */
930__asm__ ("    andb $1, %al");
931__asm__ ("    cmpb $0, %al");
932__asm__ ("    je   uart_dbgisr_com2_2");
933__asm__ ("    movw $0x2F8, %dx");
934__asm__ ("    inb  %dx, %al");    /* Get input character */
935__asm__ ("    cmpb $3, %al");
936__asm__ ("    jne  uart_dbgisr_com2_1");
937
938/* ^C received, set flag */
939__asm__ ("    movl $1, %ebx");
940__asm__ ("    jmp uart_dbgisr_com2_1");
941
942/* All chars read */
943__asm__ ("uart_dbgisr_com2_2:");
944
945/* If flag is set we have to tweak TF */
946__asm__ ("   cmpl $0, %ebx");
947__asm__ ("   je   uart_dbgisr_com2_3");
948
949/* Flag is set */
950__asm__ ("   movl BSP_uart_dbgisr_com_regsav+4, %ebx");     /* Restore ebx */
951__asm__ ("   movl BSP_uart_dbgisr_com_regsav+8, %edx");     /* Restore edx */
952
953/* Set TF bit */
954__asm__ ("   popl  %eax");           /* Pop eip */
955__asm__ ("   movl  %eax, BSP_uart_dbgisr_com_regsav + 4");  /* Save it */
956__asm__ ("   popl  %eax");           /* Pop cs */
957__asm__ ("   movl  %eax, BSP_uart_dbgisr_com_regsav + 8");  /* Save it */
958__asm__ ("   popl  %eax");           /* Pop flags */
959__asm__ ("   orl   $0x100, %eax");   /* Modify it */
960__asm__ ("   pushl %eax");           /* Push it back */
961__asm__ ("   movl  BSP_uart_dbgisr_com_regsav+8, %eax");    /* Put back cs */
962__asm__ ("   pushl %eax");
963__asm__ ("   movl  BSP_uart_dbgisr_com_regsav+4, %eax");    /* Put back eip */
964__asm__ ("   pushl %eax");
965
966/* Acknowledge IRQ */
967__asm__ ("   movb  $0x20, %al");
968__asm__ ("   outb  %al, $0x20");
969__asm__ ("   movl  BSP_uart_dbgisr_com_regsav, %eax");      /* Restore eax */
970__asm__ ("   iret");                 /* Done */
971
972/* Flag is not set */
973__asm__ ("uart_dbgisr_com2_3:");
974__asm__ ("   movl BSP_uart_dbgisr_com_regsav+4, %ebx");     /* Restore ebx */
975__asm__ ("   movl BSP_uart_dbgisr_com_regsav+8, %edx");     /* Restore edx */
976
977/* Acknowledge irq */
978__asm__ ("   movb  $0x20, %al");
979__asm__ ("   outb  %al, $0x20");
980__asm__ ("   movl  BSP_uart_dbgisr_com_regsav, %eax");      /* Restore eax */
981__asm__ ("   iret");                 /* Done */
Note: See TracBrowser for help on using the repository browser.