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

4.104.114.84.95
Last change on this file since dc3848d0 was b9ff276c, checked in by Joel Sherrill <joel.sherrill@…>, on 08/16/01 at 20:52:05

2001-08-16 Mike Siers <mikes@…>

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