source: rtems/c/src/lib/libbsp/powerpc/shared/console/uart.c @ f05b2ac

4.104.114.84.95
Last change on this file since f05b2ac was f05b2ac, checked in by Ralf Corsepius <ralf.corsepius@…>, on 04/21/04 at 16:01:48

Remove duplicate white lines.

  • Property mode set to 100644
File size: 13.2 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 <bsp.h>
11#include <bsp/irq.h>
12#include <bsp/uart.h>
13#include <rtems/libio.h>
14#include <rtems/bspIo.h>
15#include <assert.h>
16
17/*
18 * Basic 16552 driver
19 */
20
21struct uart_data
22{
23  unsigned long                 ioBase;
24  int                                   hwFlow;
25  int                                   baud;
26  BSP_UartBreakCbRec    breakCallback;
27};
28
29/*
30 * Initialization of BSP specific data.
31 * The constants are pulled in from a BSP
32 * specific file, whereas all of the code
33 * in this file is generic and makes no
34 * assumptions about addresses, irq vectors
35 * etc...
36 */
37
38#define UART_UNSUPP ((unsigned long)(-1))
39
40static struct uart_data uart_data[2] = {
41        {
42#ifdef  BSP_UART_IOBASE_COM1
43                BSP_UART_IOBASE_COM1,
44#else
45                UART_UNSUPP,
46#endif
47        },
48        {
49#ifdef  BSP_UART_IOBASE_COM2
50                BSP_UART_IOBASE_COM2,
51#else
52                UART_UNSUPP,
53#endif
54        },
55};
56
57#define MAX_UARTS (sizeof(uart_data)/sizeof(uart_data[0]))
58#define SANITY_CHECK(uart) \
59  assert( MAX_UARTS > (unsigned)(uart) && uart_data[(uart)].ioBase != UART_UNSUPP )
60/*
61 * Macros to read/wirte register of uart, if configuration is
62 * different just rewrite these macros
63 */
64
65static inline unsigned char
66uread(int uart, unsigned int reg)
67{
68
69  return in_8((unsigned char*)(uart_data[uart].ioBase + reg));
70
71}
72
73static inline void
74uwrite(int uart, int reg, unsigned int val)
75{
76  out_8((unsigned char*)(uart_data[uart].ioBase + reg), val);
77}
78
79#define UARTDEBUG
80#ifdef UARTDEBUG
81    static void
82uartError(int uart, void *termiosPrivate)
83{
84  unsigned char uartStatus, dummy;
85  BSP_UartBreakCbProc           h;
86
87  uartStatus = uread(uart, LSR);
88  dummy = uread(uart, RBR);
89
90  if (uartStatus & OE)
91    printk("********* Over run Error **********\n");
92  if (uartStatus & PE)
93    printk("********* Parity Error   **********\n");
94  if (uartStatus & FE)
95    printk("********* Framing Error  **********\n");
96  if (uartStatus & BI) {
97    printk("********* BREAK INTERRUPT *********\n");
98        if ((h=uart_data[uart].breakCallback.handler))
99                h(uart,
100                  (dummy<<8)|uartStatus,
101                  termiosPrivate,
102                  uart_data[uart].breakCallback.private);
103
104  }
105  if (uartStatus & ERFIFO)
106    printk("********* Error receive Fifo **********\n");
107
108}
109#else
110inline void uartError(int uart, void *termiosPrivate)
111{
112  unsigned char uartStatus,dummy;
113  BSP_UartBreakCbProc           h;
114
115  uartStatus = uread(uart, LSR);
116  dummy          = uread(uart, RBR);
117  if ((uartStatus & BI) && (h=uart_data[uart].breakCallback.handler))
118                h(uart,
119                  (dummy<<8)|uartStatus,
120                  termiosPrivate,
121                  uart_data[uart].breakCallback.private);
122}
123#endif
124
125/*
126 * Uart initialization, it is hardcoded to 8 bit, no parity,
127 * one stop bit, FIFO, things to be changed
128 * are baud rate and nad hw flow control,
129 * and longest rx fifo setting
130 */
131void
132BSP_uart_init(int uart, int baud, int hwFlow)
133{
134  unsigned char tmp;
135
136  /* Sanity check */
137  SANITY_CHECK(uart);
138
139  switch(baud)
140    {
141    case 50:
142    case 75:
143    case 110:
144    case 134:
145    case 300:
146    case 600:
147    case 1200:
148    case 2400:
149    case 9600:
150    case 19200:
151    case 38400:
152    case 57600:
153    case 115200:
154      break;
155    default:
156      assert(0);
157      return;
158    }
159
160  /* Set DLAB bit to 1 */
161  uwrite(uart, LCR, DLAB);
162
163  /* Set baud rate */
164  uwrite(uart, DLL,  (BSPBaseBaud/baud) & 0xff);
165  uwrite(uart, DLM,  ((BSPBaseBaud/baud) >> 8) & 0xff);
166
167  /* 8-bit, no parity , 1 stop */
168  uwrite(uart, LCR, CHR_8_BITS);
169
170  /* Set DTR, RTS and OUT2 high */
171  uwrite(uart, MCR, DTR | RTS | OUT_2);
172
173  /* Enable FIFO */
174  uwrite(uart, FCR, FIFO_EN | XMIT_RESET | RCV_RESET | RECEIVE_FIFO_TRIGGER12);
175
176  /* Disable Interrupts */
177  uwrite(uart, IER, 0);
178
179  /* Read status to clear them */
180  tmp = uread(uart, LSR);
181  tmp = uread(uart, RBR);
182  tmp = uread(uart, MSR);
183
184  /* Remember state */
185  uart_data[uart].hwFlow     = hwFlow;
186  uart_data[uart].baud       = baud;
187  return;
188}
189
190/*
191 * Set baud
192 */
193void
194BSP_uart_set_baud(int uart, int baud)
195{
196  unsigned char mcr, ier;
197
198  /* Sanity check */
199  SANITY_CHECK(uart);
200
201  /*
202   * This function may be called whenever TERMIOS parameters
203   * are changed, so we have to make sire that baud change is
204   * indeed required
205   */
206
207  if(baud == uart_data[uart].baud)
208    {
209      return;
210    }
211
212  mcr = uread(uart, MCR);
213  ier = uread(uart, IER);
214
215  BSP_uart_init(uart, baud, uart_data[uart].hwFlow);
216
217  uwrite(uart, MCR, mcr);
218  uwrite(uart, IER, ier);
219
220  return;
221}
222
223/*
224 * Enable/disable interrupts
225 */
226void
227BSP_uart_intr_ctrl(int uart, int cmd)
228{
229
230  SANITY_CHECK(uart);
231
232  switch(cmd)
233    {
234    case BSP_UART_INTR_CTRL_DISABLE:
235      uwrite(uart, IER, INTERRUPT_DISABLE);
236      break;
237    case BSP_UART_INTR_CTRL_ENABLE:
238      if(uart_data[uart].hwFlow)
239        {
240          uwrite(uart, IER,
241                 (RECEIVE_ENABLE  |
242                  TRANSMIT_ENABLE |
243                  RECEIVER_LINE_ST_ENABLE |
244                  MODEM_ENABLE
245                 )
246                );
247        }
248      else
249        {
250          uwrite(uart, IER,
251                 (RECEIVE_ENABLE  |
252                  TRANSMIT_ENABLE |
253                  RECEIVER_LINE_ST_ENABLE
254                 )
255                );
256        }
257      break;
258    case BSP_UART_INTR_CTRL_TERMIOS:
259      if(uart_data[uart].hwFlow)
260        {
261          uwrite(uart, IER,
262                 (RECEIVE_ENABLE  |
263                  RECEIVER_LINE_ST_ENABLE |
264                  MODEM_ENABLE
265                 )
266                );
267        }
268      else
269        {
270          uwrite(uart, IER,
271                 (RECEIVE_ENABLE  |
272                  RECEIVER_LINE_ST_ENABLE
273                 )
274                );
275        }
276      break;
277    case BSP_UART_INTR_CTRL_GDB:
278      uwrite(uart, IER, RECEIVE_ENABLE);
279      break;
280    default:
281      assert(0);
282      break;
283    }
284
285  return;
286}
287
288void
289BSP_uart_throttle(int uart)
290{
291  unsigned int mcr;
292
293  SANITY_CHECK(uart);
294
295  if(!uart_data[uart].hwFlow)
296    {
297      /* Should not happen */
298      assert(0);
299      return;
300    }
301  mcr = uread (uart, MCR);
302  /* RTS down */
303  mcr &= ~RTS;
304  uwrite(uart, MCR, mcr);
305
306  return;
307}
308
309void
310BSP_uart_unthrottle(int uart)
311{
312  unsigned int mcr;
313
314  SANITY_CHECK(uart);
315
316  if(!uart_data[uart].hwFlow)
317    {
318      /* Should not happen */
319      assert(0);
320      return;
321    }
322  mcr = uread (uart, MCR);
323  /* RTS up */
324  mcr |= RTS;
325  uwrite(uart, MCR, mcr);
326
327  return;
328}
329
330/*
331 * Status function, -1 if error
332 * detected, 0 if no received chars available,
333 * 1 if received char available, 2 if break
334 * is detected, it will eat break and error
335 * chars. It ignores overruns - we cannot do
336 * anything about - it execpt count statistics
337 * and we are not counting it.
338 */
339int
340BSP_uart_polled_status(int uart)
341{
342  unsigned char val;
343
344  SANITY_CHECK(uart);
345
346  val = uread(uart, LSR);
347
348  if(val & BI)
349    {
350      /* BREAK found, eat character */
351      uread(uart, RBR);
352      return BSP_UART_STATUS_BREAK;
353    }
354
355  if((val & (DR | OE | FE)) ==  1)
356    {
357      /* No error, character present */
358      return BSP_UART_STATUS_CHAR;
359    }
360
361  if((val & (DR | OE | FE)) == 0)
362    {
363      /* Nothing */
364      return BSP_UART_STATUS_NOCHAR;
365    }
366
367  /*
368   * Framing or parity error
369   * eat character
370   */
371  uread(uart, RBR);
372
373  return BSP_UART_STATUS_ERROR;
374}
375
376/*
377 * Polled mode write function
378 */
379void
380BSP_uart_polled_write(int uart, int val)
381{
382  unsigned char val1;
383
384  /* Sanity check */
385  SANITY_CHECK(uart);
386
387  for(;;)
388    {
389      if((val1=uread(uart, LSR)) & THRE)
390        {
391          break;
392        }
393    }
394
395  if(uart_data[uart].hwFlow)
396    {
397      for(;;)
398        {
399          if(uread(uart, MSR) & CTS)
400            {
401              break;
402            }
403        }
404    }
405
406  uwrite(uart, THR, val & 0xff);
407
408  return;
409}
410
411void
412BSP_output_char_via_serial(const char val)
413{
414  BSP_uart_polled_write(BSPConsolePort, val);
415  if (val == '\n') BSP_uart_polled_write(BSPConsolePort,'\r');
416}
417
418/*
419 * Polled mode read function
420 */
421int
422BSP_uart_polled_read(int uart)
423{
424  unsigned char val;
425
426  SANITY_CHECK(uart);
427
428  for(;;)
429    {
430      if(uread(uart, LSR) & DR)
431        {
432          break;
433        }
434    }
435
436  val = uread(uart, RBR);
437
438  return (int)(val & 0xff);
439}
440
441unsigned
442BSP_poll_char_via_serial()
443{
444        return BSP_uart_polled_read(BSPConsolePort);
445}
446
447static void
448uart_noop(const rtems_irq_connect_data *unused)
449{
450  return;
451}
452
453/* note that the IRQ names contain _ISA_ for legacy
454 * reasons. They can be any interrupt, depending
455 * on the particular BSP...
456 */
457
458static int
459uart_isr_is_on(const rtems_irq_connect_data *irq)
460{
461int uart = (irq->name == BSP_ISA_UART_COM1_IRQ) ?
462                        BSP_UART_COM1 : BSP_UART_COM2;
463  return uread(uart,IER);
464}
465
466static int
467doit(int uart, rtems_irq_hdl handler, int (*p)(const rtems_irq_connect_data*))
468{
469        rtems_irq_connect_data d={0};
470        d.name = (uart == BSP_UART_COM1) ?
471                        BSP_ISA_UART_COM1_IRQ : BSP_ISA_UART_COM2_IRQ;
472        d.off  = d.on = uart_noop;
473        d.isOn = uart_isr_is_on;
474        d.hdl  = handler;
475        return p(&d);
476}
477
478int
479BSP_uart_install_isr(int uart, rtems_irq_hdl handler)
480{
481        return doit(uart, handler, BSP_install_rtems_irq_handler);
482}
483
484int
485BSP_uart_remove_isr(int uart, rtems_irq_hdl handler)
486{
487        return doit(uart, handler, BSP_remove_rtems_irq_handler);
488}
489
490/* ================ Termios support  =================*/
491
492static volatile int  termios_stopped_com[2]        = {0,0};
493static volatile int  termios_tx_active_com[2]      = {0,0};
494static void*         termios_ttyp_com[2]           = {NULL,NULL};
495static char          termios_tx_hold_com[2]        = {0,0};
496static volatile char termios_tx_hold_valid_com[2]  = {0,0};
497
498/*
499 * Set channel parameters
500 */
501void
502BSP_uart_termios_set(int uart, void *ttyp)
503{
504  unsigned char val;
505  SANITY_CHECK(uart);
506
507  if(uart_data[uart].hwFlow)
508    {
509      val = uread(uart, MSR);
510
511      termios_stopped_com[uart]    = (val & CTS) ? 0 : 1;
512    }
513  else
514  {
515      termios_stopped_com[uart] = 0;
516  }
517  termios_tx_active_com[uart]      = 0;
518  termios_ttyp_com[uart]           = ttyp;
519  termios_tx_hold_com[uart]        = 0;
520  termios_tx_hold_valid_com[uart]  = 0;
521
522  return;
523}
524
525int
526BSP_uart_termios_write_com(int minor, const char *buf, int len)
527{
528  int uart=minor;       /* could differ, theoretically */
529  assert(buf != NULL);
530
531  if(len <= 0)
532    {
533      return 0;
534    }
535
536  /* If there TX buffer is busy - something is royally screwed up */
537  /*   assert((uread(BSP_UART_COM1, LSR) & THRE) != 0); */
538
539  if(termios_stopped_com[uart])
540    {
541      /* CTS low */
542      termios_tx_hold_com[uart]       = *buf;
543      termios_tx_hold_valid_com[uart] = 1;
544      return 0;
545    }
546
547  /* Write character */
548  uwrite(uart, THR, *buf & 0xff);
549
550  /* Enable interrupts if necessary */
551  if(!termios_tx_active_com[uart] && uart_data[uart].hwFlow)
552    {
553      termios_tx_active_com[uart] = 1;
554      uwrite(uart, IER,
555             (RECEIVE_ENABLE  |
556              TRANSMIT_ENABLE |
557              RECEIVER_LINE_ST_ENABLE |
558              MODEM_ENABLE
559             )
560            );
561    }
562  else if(!termios_tx_active_com[uart])
563    {
564      termios_tx_active_com[uart] = 1;
565      uwrite(uart, IER,
566             (RECEIVE_ENABLE  |
567              TRANSMIT_ENABLE |
568              RECEIVER_LINE_ST_ENABLE
569             )
570            );
571    }
572
573  return 0;
574}
575
576static void
577BSP_uart_termios_isr_com(int uart)
578{
579  unsigned char buf[40];
580  unsigned char val;
581  int      off, ret, vect;
582
583  off = 0;
584
585  for(;;)
586    {
587      vect = uread(uart, IIR) & 0xf;
588
589      switch(vect)
590        {
591        case MODEM_STATUS :
592          val = uread(uart, MSR);
593          if(uart_data[uart].hwFlow)
594            {
595              if(val & CTS)
596                {
597                  /* CTS high */
598                  termios_stopped_com[uart] = 0;
599                  if(termios_tx_hold_valid_com[uart])
600                    {
601                      termios_tx_hold_valid_com[uart] = 0;
602                      BSP_uart_termios_write_com(uart, &termios_tx_hold_com[uart],
603                                                    1);
604                    }
605                }
606              else
607                {
608                  /* CTS low */
609                  termios_stopped_com[uart] = 1;
610                }
611            }
612          break;
613        case NO_MORE_INTR :
614          /* No more interrupts */
615          if(off != 0)
616            {
617              /* Update rx buffer */
618              rtems_termios_enqueue_raw_characters(termios_ttyp_com[uart],
619                                                   (char *)buf,
620                                                   off);
621            }
622          return;
623        case TRANSMITTER_HODING_REGISTER_EMPTY :
624          /*
625           * TX holding empty: we have to disable these interrupts
626           * if there is nothing more to send.
627           */
628
629          ret = rtems_termios_dequeue_characters(termios_ttyp_com[uart], 1);
630
631          /* If nothing else to send disable interrupts */
632          if(ret == 0 && uart_data[uart].hwFlow)
633            {
634              uwrite(uart, IER,
635                     (RECEIVE_ENABLE  |
636                      RECEIVER_LINE_ST_ENABLE |
637                      MODEM_ENABLE
638                     )
639                    );
640              termios_tx_active_com[uart] = 0;
641            }
642          else if(ret == 0)
643            {
644              uwrite(uart, IER,
645                     (RECEIVE_ENABLE  |
646                      RECEIVER_LINE_ST_ENABLE
647                     )
648                    );
649              termios_tx_active_com[uart] = 0;
650            }
651          break;
652        case RECEIVER_DATA_AVAIL :
653        case CHARACTER_TIMEOUT_INDICATION:
654          /* RX data ready */
655          assert(off < sizeof(buf));
656          buf[off++] = uread(uart, RBR);
657          break;
658        case RECEIVER_ERROR:
659          /* RX error: eat character */
660           uartError(uart, termios_ttyp_com[uart]);
661          break;
662        default:
663          /* Should not happen */
664          assert(0);
665          return;
666        }
667    }
668}
669
670void
671BSP_uart_termios_isr_com1(void)
672{
673        BSP_uart_termios_isr_com(BSP_UART_COM1);
674}
675
676void
677BSP_uart_termios_isr_com2(void)
678{
679        BSP_uart_termios_isr_com(BSP_UART_COM2);
680}
681
682/* retrieve 'break' handler info */
683int
684BSP_uart_get_break_cb(int uart, rtems_libio_ioctl_args_t *arg)
685{
686BSP_UartBreakCb cb=arg->buffer;
687unsigned long flags;
688        SANITY_CHECK(uart);
689        rtems_interrupt_disable(flags);
690                *cb = uart_data[uart].breakCallback;
691        rtems_interrupt_enable(flags);
692        arg->ioctl_return=0;
693        return RTEMS_SUCCESSFUL;
694}
695
696/* install 'break' handler */
697int
698BSP_uart_set_break_cb(int uart, rtems_libio_ioctl_args_t *arg)
699{
700BSP_UartBreakCb cb=arg->buffer;
701unsigned long flags;
702        SANITY_CHECK(uart);
703        rtems_interrupt_disable(flags);
704                uart_data[uart].breakCallback = *cb;
705        rtems_interrupt_enable(flags);
706        arg->ioctl_return=0;
707        return RTEMS_SUCCESSFUL;
708}
Note: See TracBrowser for help on using the repository browser.