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

4.104.114.84.95
Last change on this file since 69ed59f was 69ed59f, checked in by Joel Sherrill <joel.sherrill@…>, on May 14, 2002 at 5:10:17 PM

2001-05-14 Till Straumann <strauman@…>

  • bootloader/misc.c, console/Makefile.am, console/console.c, console/consoleIo.h, console/inch.c, console/polled_io.c, console/uart.c, console/uart.h, include/bsp.h, irq/Makefile.am, irq/irq.c, irq/irq.h, irq/irq_init.c, openpic/openpic.c, openpic/openpic.h, pci/Makefile.am, pci/pci.c, pci/pci.h, residual/Makefile.am, start/start.S, startup/bspstart.c, vectors/vectors.S, vectors/vectors.h, vectors/vectors_init.c: Per PR216, "libbsp/powerpc/shared" BSP has been modified considerably with the goal to make it more flexible and reusable by other BSPs. The main strategies were:
    • eliminate hardcoded base addresses; devices use offsets and a BSP defined base address.
    • separate functionality into different files (e.g. reboot from inch.c to reboot.c) which can be overridden by a 'derived' BSP.
    • separate initialization code into separate files (e.g. PCI bridge detection/initialization was separated from the more generic PCI access routines), also to make it easier for 'derived' BSPs to substitute their own initialization code.

There are also a couple of enhancements and fixes:

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