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

Last change on this file since f97536d was f97536d, checked in by Sebastian Huber <sebastian.huber@…>, on Oct 16, 2015 at 6:21:48 AM

basdefs.h: Add and use RTEMS_UNUSED

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