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

4.104.11
Last change on this file since dfddaf1 was dfddaf1, checked in by Ralf Corsepius <ralf.corsepius@…>, on Dec 10, 2009 at 1:55:22 PM

2009-12-10 Ralf Corsépius <ralf.corsepius@…>

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