source: rtems/c/src/lib/libbsp/mips/genmongoosev/console/mg5uart.c @ 2dac965

4.115
Last change on this file since 2dac965 was 2dac965, checked in by Joel Sherrill <joel.sherrill@…>, on 10/13/14 at 00:17:11

mips/genmongoosev: Fix warnings

  • Property mode set to 100644
File size: 20.3 KB
Line 
1/**
2 *  @file
3 * 
4 *  This file contains the termios TTY driver for the UART found
5 *  on the Synova Mongoose-V.
6 */
7
8/*
9 *  COPYRIGHT (c) 1989-2012.
10 *  On-Line Applications Research Corporation (OAR).
11 *
12 *  The license and distribution terms for this file may be
13 *  found in the file LICENSE in this distribution or at
14 *  http://www.rtems.org/license/LICENSE.
15 */
16
17#include <rtems.h>
18#include <rtems/libio.h>
19#include <rtems/score/sysstate.h>
20#include <stdlib.h>
21
22#include <libchip/serial.h>
23#include <libchip/sersupp.h>
24#include <bsp/mg5uart.h>
25#include <bsp/mongoose-v.h>
26
27#include <bsp/irq.h>
28#include <bsp.h>
29
30/*
31 *  Indices of registers
32 */
33
34/*
35 *  Per chip context control
36 */
37
38typedef struct _mg5uart_context
39{
40  int            mate;
41} mg5uart_context;
42
43/*
44 *  Define MG5UART_STATIC to nothing while debugging so the entry points
45 *  will show up in the symbol table.
46 */
47/* #define MG5UART_STATIC */
48#define MG5UART_STATIC static
49
50#define MG5UART_SETREG( _base, _register, _value ) \
51        MONGOOSEV_WRITE_REGISTER( _base, _register, _value )
52
53#define MG5UART_GETREG( _base, _register ) \
54        MONGOOSEV_READ_REGISTER( _base, _register )
55
56/*
57 *  Console Device Driver Support Functions
58 */
59
60MG5UART_STATIC int mg5uart_baud_rate(
61  int        minor,
62  uint32_t   baud,
63  uint32_t  *code
64);
65
66MG5UART_STATIC void mg5uart_enable_interrupts(
67  int minor,
68  int mask
69);
70
71/*
72 *  mg5uart_isr_XXX
73 *
74 *  This is the single interrupt entry point which parcels interrupts
75 *  out to the handlers for specific sources and makes sure that the
76 *  shared handler gets the right arguments.
77 *
78 *  NOTE: Yes .. this is ugly but it provides 5 interrupt source
79 *  wrappers which are nearly functionally identical.
80 */
81extern void mips_default_isr(int vector);
82
83#define __ISR(_TYPE, _OFFSET) \
84  MG5UART_STATIC void mg5uart_process_isr_ ## _TYPE ( \
85    int  minor \
86  ); \
87  \
88  MG5UART_STATIC rtems_isr mg5uart_isr_ ## _TYPE ( \
89    void *arg \
90  ) \
91  { \
92    rtems_vector_number vector = (rtems_vector_number) arg; \
93    int   minor; \
94    \
95    for(minor=0 ; minor<Console_Port_Count ; minor++) { \
96      if( Console_Port_Tbl[minor]->deviceType == SERIAL_MG5UART && \
97          vector == Console_Port_Tbl[minor]->ulIntVector + _OFFSET ) { \
98        mg5uart_process_isr_ ## _TYPE (minor); \
99        return; \
100      } \
101    } \
102    mips_default_isr( vector ); \
103  }
104
105__ISR(rx_frame_error, MG5UART_IRQ_RX_FRAME_ERROR)
106__ISR(rx_overrun_error, MG5UART_IRQ_RX_OVERRUN_ERROR)
107__ISR(tx_empty, MG5UART_IRQ_TX_EMPTY)
108__ISR(tx_ready, MG5UART_IRQ_TX_READY)
109__ISR(rx_ready, MG5UART_IRQ_RX_READY)
110
111/*
112 *  mg5uart_set_attributes
113 *
114 *  This function sets the UART channel to reflect the requested termios
115 *  port settings.
116 */
117MG5UART_STATIC int mg5uart_set_attributes(
118  int minor,
119  const struct termios *t
120)
121{
122  uint32_t               pMG5UART_port;
123  uint32_t               pMG5UART;
124  uint32_t               cmd, cmdSave;
125  uint32_t               baudcmd;
126  uint32_t               shift;
127  rtems_interrupt_level  Irql;
128
129  pMG5UART      = Console_Port_Tbl[minor]->ulCtrlPort1;
130  pMG5UART_port = Console_Port_Tbl[minor]->ulCtrlPort2;
131
132  /*
133   *  Set the baud rate
134   */
135
136  if (mg5uart_baud_rate( minor, t->c_cflag, &baudcmd ) == -1)
137    return -1;
138
139  /*
140   *  Base settings
141   */
142
143  /*
144   *  Base settings
145   */
146
147  cmd = MONGOOSEV_UART_CMD_RX_ENABLE | MONGOOSEV_UART_CMD_TX_ENABLE;
148
149  /*
150   *  Parity
151   */
152
153  if (t->c_cflag & PARENB) {
154    cmd |= MONGOOSEV_UART_CMD_PARITY_ENABLE;
155    if (t->c_cflag & PARODD)
156      cmd |= MONGOOSEV_UART_CMD_PARITY_ODD;
157    else
158      cmd |= MONGOOSEV_UART_CMD_PARITY_EVEN;
159  } else {
160    cmd |= MONGOOSEV_UART_CMD_PARITY_DISABLE;
161  }
162
163  /*
164   *  Character Size
165   */
166
167  if (t->c_cflag & CSIZE) {
168    switch (t->c_cflag & CSIZE) {
169      case CS5:
170      case CS6:
171      case CS7:
172        return -1;
173        break;
174      case CS8:
175        /* Mongoose-V only supports CS8 */
176        break;
177
178    }
179  } /* else default to CS8 */
180
181  /*
182   *  Stop Bits
183   */
184
185#if 0
186  if (t->c_cflag & CSTOPB) {
187    /* 2 stop bits not supported by Mongoose-V uart */
188    return -1;
189  }
190#endif
191
192  /*
193   *  XXX what about CTS/RTS
194   */
195
196  /* XXX */
197
198  /*
199   *  Now write the registers
200   */
201
202  if ( Console_Port_Tbl[minor]->ulDataPort == MG5UART_UART0 )
203    shift = MONGOOSEV_UART0_CMD_SHIFT;
204  else
205    shift = MONGOOSEV_UART1_CMD_SHIFT;
206
207
208
209  rtems_interrupt_disable(Irql);
210
211  cmdSave = MG5UART_GETREG( pMG5UART, MG5UART_COMMAND_REGISTER );
212
213  MG5UART_SETREG( pMG5UART,
214                  MG5UART_COMMAND_REGISTER,
215                  (cmdSave & ~(MONGOOSEV_UART_ALL_STATUS_BITS << shift)) | (cmd << shift) );
216
217  MG5UART_SETREG( pMG5UART_port, MG5UART_BAUD_RATE, baudcmd );
218
219  rtems_interrupt_enable(Irql);
220  return 0;
221}
222
223/*
224 *  mg5uart_initialize_context
225 *
226 *  This function sets the default values of the per port context structure.
227 */
228MG5UART_STATIC void mg5uart_initialize_context(
229  int               minor,
230  mg5uart_context  *pmg5uartContext
231)
232{
233  int          port;
234  unsigned int pMG5UART;
235  unsigned int pMG5UART_port;
236
237  pMG5UART      = Console_Port_Tbl[minor]->ulCtrlPort1;
238  pMG5UART_port = Console_Port_Tbl[minor]->ulCtrlPort2;
239
240  pmg5uartContext->mate = -1;
241
242  for (port=0 ; port<Console_Port_Count ; port++ ) {
243    if ( Console_Port_Tbl[port]->ulCtrlPort1 == pMG5UART &&
244         Console_Port_Tbl[port]->ulCtrlPort2 != pMG5UART_port ) {
245      pmg5uartContext->mate = port;
246      break;
247    }
248  }
249
250}
251
252/*
253 *  mg5uart_init
254 *
255 *  This function initializes the DUART to a quiecsent state.
256 */
257MG5UART_STATIC void mg5uart_init(int minor)
258{
259  uint32_t              pMG5UART;
260  uint32_t              cmdSave;
261  uint32_t              shift;
262
263  mg5uart_context        *pmg5uartContext;
264
265  pmg5uartContext = (mg5uart_context *) malloc(sizeof(mg5uart_context));
266
267  Console_Port_Data[minor].pDeviceContext = (void *)pmg5uartContext;
268
269  mg5uart_initialize_context( minor, pmg5uartContext );
270
271  pMG5UART      = Console_Port_Tbl[minor]->ulCtrlPort1;
272
273  if ( Console_Port_Tbl[minor]->ulDataPort == MG5UART_UART0 )
274     shift = MONGOOSEV_UART0_CMD_SHIFT;
275  else
276     shift = MONGOOSEV_UART1_CMD_SHIFT;
277
278  /*
279   *  Disable the uart and leave this port disabled.
280   */
281
282  cmdSave = MG5UART_GETREG(pMG5UART, MG5UART_COMMAND_REGISTER) & ~(MONGOOSEV_UART_ALL_STATUS_BITS << shift);
283
284  MG5UART_SETREG( pMG5UART, MG5UART_COMMAND_REGISTER, cmdSave );
285
286  /*
287   *  Disable interrupts on RX and TX for this port
288   */
289  mg5uart_enable_interrupts( minor, MG5UART_DISABLE_ALL );
290}
291
292/*
293 *  mg5uart_open
294 *
295 *  This function opens a port for communication.
296 *
297 *  Default state is 9600 baud, 8 bits, No parity, and 1 stop bit.
298 */
299MG5UART_STATIC int mg5uart_open(
300  int      major,
301  int      minor,
302  void    *arg
303)
304{
305  uint32_t      pMG5UART;
306  uint32_t      pMG5UART_port;
307  uint32_t      cmd, cmdSave;
308  uint32_t      baudcmd;
309  uint32_t      shift;
310
311  rtems_interrupt_level  Irql;
312
313  pMG5UART      = Console_Port_Tbl[minor]->ulCtrlPort1;
314  pMG5UART_port = Console_Port_Tbl[minor]->ulCtrlPort2;
315
316  if ( Console_Port_Tbl[minor]->ulDataPort == MG5UART_UART0 )
317    shift = MONGOOSEV_UART0_CMD_SHIFT;
318  else
319    shift = MONGOOSEV_UART1_CMD_SHIFT;
320
321  /* XXX default baud rate could be from configuration table */
322
323  (void) mg5uart_baud_rate( minor, B19200, &baudcmd );
324
325  /*
326   *  Set the DUART channel to a default useable state
327   *  B19200, 8Nx since there is no stop bit control.
328   */
329
330  cmd = MONGOOSEV_UART_CMD_TX_ENABLE | MONGOOSEV_UART_CMD_RX_ENABLE;
331
332  rtems_interrupt_disable(Irql);
333
334  cmdSave = MG5UART_GETREG( pMG5UART, MG5UART_COMMAND_REGISTER );
335
336  MG5UART_SETREG( pMG5UART_port, MG5UART_BAUD_RATE, baudcmd );
337
338  MG5UART_SETREG( pMG5UART,
339                  MG5UART_COMMAND_REGISTER,
340                  cmd = (cmdSave & ~(MONGOOSEV_UART_ALL_STATUS_BITS << shift)) | (cmd << shift) );
341
342  rtems_interrupt_enable(Irql);
343
344  return RTEMS_SUCCESSFUL;
345}
346
347/*
348 *  mg5uart_close
349 *
350 *  This function shuts down the requested port.
351 */
352MG5UART_STATIC int mg5uart_close(
353  int      major,
354  int      minor,
355  void    *arg
356)
357{
358  uint32_t      pMG5UART;
359  uint32_t      cmd, cmdSave;
360  uint32_t      shift;
361  rtems_interrupt_level  Irql;
362
363  pMG5UART      = Console_Port_Tbl[minor]->ulCtrlPort1;
364
365  /*
366   *  Disable interrupts from this channel and then disable it totally.
367   */
368
369  /* XXX interrupts */
370
371  cmd = MONGOOSEV_UART_CMD_TX_DISABLE | MONGOOSEV_UART_CMD_RX_DISABLE;
372
373  if ( Console_Port_Tbl[minor]->ulDataPort == MG5UART_UART0 )
374    shift = MONGOOSEV_UART0_CMD_SHIFT;
375  else
376    shift = MONGOOSEV_UART1_CMD_SHIFT;
377
378
379  rtems_interrupt_disable(Irql);
380  cmdSave = MG5UART_GETREG( pMG5UART, MG5UART_COMMAND_REGISTER );
381
382  MG5UART_SETREG( pMG5UART,
383                  MG5UART_COMMAND_REGISTER,
384                  (cmdSave & ~(MONGOOSEV_UART_ALL_STATUS_BITS << shift)) | (cmd << shift) );
385  rtems_interrupt_enable(Irql);
386
387  return(RTEMS_SUCCESSFUL);
388}
389
390/*
391 *  mg5uart_write_polled
392 *
393 *  This routine polls out the requested character.
394 */
395MG5UART_STATIC void mg5uart_write_polled(
396  int   minor,
397  char  c
398)
399{
400  uint32_t                pMG5UART;
401  uint32_t                pMG5UART_port;
402  uint32_t                status;
403  int                     shift;
404  int                     timeout;
405
406  pMG5UART      = Console_Port_Tbl[minor]->ulCtrlPort1;
407  pMG5UART_port = Console_Port_Tbl[minor]->ulCtrlPort2;
408
409  if ( Console_Port_Tbl[minor]->ulDataPort == MG5UART_UART0 )
410    shift = MONGOOSEV_UART0_IRQ_SHIFT;
411  else
412    shift = MONGOOSEV_UART1_IRQ_SHIFT;
413
414  /*
415   * wait for transmitter holding register to be empty
416   */
417  timeout = 2000;
418
419  while( --timeout )
420  {
421    status = MG5UART_GETREG(pMG5UART, MG5UART_STATUS_REGISTER) >> shift;
422
423    /*
424    if ( (status & (MONGOOSEV_UART_TX_READY | MONGOOSEV_UART_TX_EMPTY)) ==
425            (MONGOOSEV_UART_TX_READY | MONGOOSEV_UART_TX_EMPTY) )
426      break;
427    */
428
429    if( (status & (MONGOOSEV_UART_TX_READY | MONGOOSEV_UART_TX_EMPTY)) )
430       break;
431
432    /*
433     * Yield while we wait
434     */
435
436#if 0
437     if(_System_state_Is_up(_System_state_Get()))
438     {
439       rtems_task_wake_after(RTEMS_YIELD_PROCESSOR);
440     }
441#endif
442  }
443
444  /*
445   * transmit character
446   */
447
448  MG5UART_SETREG(pMG5UART_port, MG5UART_TX_BUFFER, c);
449}
450
451MG5UART_STATIC void mg5uart_process_isr_rx_error(
452   int  minor,
453   uint32_t   mask
454)
455{
456  uint32_t                pMG5UART;
457  int                     shift;
458
459  pMG5UART      = Console_Port_Tbl[minor]->ulCtrlPort1;
460
461  if ( Console_Port_Tbl[minor]->ulDataPort == MG5UART_UART0 )
462    shift = MONGOOSEV_UART0_IRQ_SHIFT;
463  else
464    shift = MONGOOSEV_UART1_IRQ_SHIFT;
465
466  /* now clear the error */
467
468  MG5UART_SETREG(
469     pMG5UART,
470     MG5UART_STATUS_REGISTER,
471     mask << shift );
472}
473
474MG5UART_STATIC void mg5uart_process_isr_rx_frame_error(
475  int  minor
476)
477{
478   mg5uart_process_isr_rx_error( minor, MONGOOSEV_UART_RX_FRAME_ERROR );
479}
480
481MG5UART_STATIC void mg5uart_process_isr_rx_overrun_error(
482  int  minor
483)
484{
485   mg5uart_process_isr_rx_error( minor, MONGOOSEV_UART_RX_OVERRUN_ERROR );
486}
487
488MG5UART_STATIC void mg5uart_process_tx_isr(
489   int        minor,
490   uint32_t   source
491)
492{
493   uint32_t        pMG5UART;
494   int             shift;
495
496   pMG5UART      = Console_Port_Tbl[minor]->ulCtrlPort1;
497
498   mg5uart_enable_interrupts(minor, MG5UART_ENABLE_ALL_EXCEPT_TX);
499
500   if ( Console_Port_Tbl[minor]->ulDataPort == MG5UART_UART0 )
501      shift = MONGOOSEV_UART0_IRQ_SHIFT;
502   else
503      shift = MONGOOSEV_UART1_IRQ_SHIFT;
504
505   MG5UART_SETREG(
506      pMG5UART,
507      MG5UART_STATUS_REGISTER,
508      source << shift );
509
510   if( rtems_termios_dequeue_characters( Console_Port_Data[minor].termios_data, 1) )
511   {
512      mg5uart_enable_interrupts(minor, MG5UART_ENABLE_ALL);
513      return;
514   }
515
516   /*
517    *  There are no more characters to transmit.  The tx interrupts are be cleared
518    *  by writing data to the uart, so just disable the tx interrupt sources.
519    */
520
521   Console_Port_Data[minor].bActive = FALSE;
522
523   /* mg5uart_enable_interrupts(minor, MG5UART_ENABLE_ALL_EXCEPT_TX); */
524}
525
526MG5UART_STATIC void mg5uart_process_isr_tx_empty(
527  int  minor
528)
529{
530   /* mg5uart_process_tx_isr( minor, MONGOOSEV_UART_TX_EMPTY ); */
531}
532
533MG5UART_STATIC void mg5uart_process_isr_tx_ready(
534  int  minor
535)
536{
537   mg5uart_process_tx_isr( minor, MONGOOSEV_UART_TX_READY );
538}
539
540MG5UART_STATIC void mg5uart_process_isr_rx_ready(
541  int  minor
542)
543{
544  uint32_t   pMG5UART_port;
545  char       c;
546
547  pMG5UART_port = Console_Port_Tbl[minor]->ulCtrlPort2;
548
549  /* reading the RX buffer automatically resets the interrupt flag */
550
551  c = (char) MG5UART_GETREG(pMG5UART_port, MG5UART_RX_BUFFER);
552
553  rtems_termios_enqueue_raw_characters(
554     Console_Port_Data[minor].termios_data,
555     &c,
556    1
557  );
558}
559
560static rtems_irq_connect_data mg5uart_rx_frame_error_cd  = {  \
561  0,                             /* filled in at initialization */
562  mg5uart_isr_rx_frame_error,   /* filled in at initialization */
563  NULL,   /* (void *) minor */
564  NULL,
565  NULL,
566  NULL
567};
568
569static rtems_irq_connect_data mg5uart_rx_overrun_error_cd  = {  \
570  0,                             /* filled in at initialization */
571  mg5uart_isr_rx_overrun_error,   /* filled in at initialization */
572  NULL,   /* (void *) minor */
573  NULL,
574  NULL,
575  NULL
576};
577
578static rtems_irq_connect_data mg5uart_tx_empty_cd  = {  \
579  0,                             /* filled in at initialization */
580  mg5uart_isr_tx_empty,   /* filled in at initialization */
581  NULL,   /* (void *) minor */
582  NULL,
583  NULL,
584  NULL
585};
586
587static rtems_irq_connect_data mg5uart_tx_ready_cd  = {  \
588  0,                             /* filled in at initialization */
589  mg5uart_isr_tx_ready,   /* filled in at initialization */
590  NULL,   /* (void *) minor */
591  NULL,
592  NULL,
593  NULL
594};
595
596static rtems_irq_connect_data mg5uart_rx_ready_cd  = {  \
597  0,                             /* filled in at initialization */
598  mg5uart_isr_rx_ready,   /* filled in at initialization */
599  NULL,   /* (void *) minor */
600  NULL,
601  NULL,
602  NULL
603};
604
605
606/*
607 *  mg5uart_initialize_interrupts
608 *
609 *  This routine initializes the console's receive and transmit
610 *  ring buffers and loads the appropriate vectors to handle the interrupts.
611 */
612
613MG5UART_STATIC void mg5uart_initialize_interrupts(int minor)
614{
615  unsigned long v;
616  mg5uart_init(minor);
617
618  Console_Port_Data[minor].bActive = FALSE;
619  v = Console_Port_Tbl[minor]->ulIntVector;
620
621  mg5uart_rx_frame_error_cd.name    =  v + MG5UART_IRQ_RX_FRAME_ERROR;
622  mg5uart_rx_overrun_error_cd.name  =  v + MG5UART_IRQ_RX_OVERRUN_ERROR;
623  mg5uart_tx_empty_cd.name          =  v + MG5UART_IRQ_TX_EMPTY; 
624  mg5uart_tx_ready_cd.name          =  v + MG5UART_IRQ_TX_READY;
625  mg5uart_rx_ready_cd.name          =  v + MG5UART_IRQ_RX_READY;
626
627  mg5uart_rx_frame_error_cd.handle    =  (void *)mg5uart_rx_frame_error_cd.name;
628  mg5uart_rx_overrun_error_cd.handle  =  (void *)mg5uart_rx_overrun_error_cd.name;
629  mg5uart_tx_empty_cd.handle          =  (void *)mg5uart_tx_empty_cd.name; 
630  mg5uart_tx_ready_cd.handle          =  (void *)mg5uart_tx_ready_cd.name;
631  mg5uart_rx_ready_cd.handle          =  (void *)mg5uart_rx_ready_cd.name;
632
633 
634  BSP_install_rtems_irq_handler( &mg5uart_rx_frame_error_cd );
635  BSP_install_rtems_irq_handler( &mg5uart_rx_overrun_error_cd );
636  BSP_install_rtems_irq_handler( &mg5uart_tx_empty_cd );
637  BSP_install_rtems_irq_handler( &mg5uart_tx_ready_cd );
638  BSP_install_rtems_irq_handler( &mg5uart_rx_ready_cd );
639
640  mg5uart_enable_interrupts(minor, MG5UART_ENABLE_ALL_EXCEPT_TX);
641}
642
643/*
644 *  mg5uart_write_support_int
645 *
646 *  Console Termios output entry point when using interrupt driven output.
647 */
648MG5UART_STATIC int mg5uart_write_support_int(
649  int         minor,
650  const char *buf,
651  size_t      len
652)
653{
654  uint32_t        pMG5UART_port;
655
656  pMG5UART_port = Console_Port_Tbl[minor]->ulCtrlPort2;
657
658  /*
659   *  We are using interrupt driven output and termios only sends us
660   *  one character at a time.
661   */
662
663  if ( !len )
664     return 0;
665
666  /*
667   *  Put the character out and enable interrupts if necessary.
668   */
669
670  MG5UART_SETREG(pMG5UART_port, MG5UART_TX_BUFFER, *buf);
671
672  if( Console_Port_Data[minor].bActive == FALSE )
673  {
674     Console_Port_Data[minor].bActive = TRUE;
675     mg5uart_enable_interrupts(minor, MG5UART_ENABLE_ALL);
676  }
677
678  return 1;
679}
680
681
682
683
684/*
685 *  mg5uart_write_support_polled
686 *
687 *  Console Termios output entry point when using polled output.
688 *
689 */
690
691MG5UART_STATIC ssize_t mg5uart_write_support_polled(
692  int         minor,
693  const char *buf,
694  size_t      len
695)
696{
697  int nwrite = 0;
698
699  /*
700   * poll each byte in the string out of the port.
701   */
702  while (nwrite < len)
703  {
704    mg5uart_write_polled(minor, *buf++);
705    nwrite++;
706  }
707
708  /*
709   * return the number of bytes written.
710   */
711  return nwrite;
712}
713
714/*
715 *  mg5uart_inbyte_nonblocking_polled
716 *
717 *  Console Termios polling input entry point.
718 */
719
720MG5UART_STATIC int mg5uart_inbyte_nonblocking_polled(
721  int minor
722)
723{
724  uint32_t                pMG5UART;
725  uint32_t                pMG5UART_port;
726  uint32_t                status;
727  uint32_t                tmp,shift;
728
729  pMG5UART      = Console_Port_Tbl[minor]->ulCtrlPort1;
730  pMG5UART_port = Console_Port_Tbl[minor]->ulCtrlPort2;
731
732  if ( Console_Port_Tbl[minor]->ulDataPort == MG5UART_UART0 )
733    shift = MONGOOSEV_UART0_IRQ_SHIFT;
734  else
735    shift = MONGOOSEV_UART1_IRQ_SHIFT;
736
737  /* reset overrrun or framing errors */
738  status = MG5UART_GETREG(pMG5UART, MG5UART_STATUS_REGISTER) >> shift;
739
740  if( (tmp = (status & 0x3)) )
741  {
742     MG5UART_SETREG(pMG5UART, MG5UART_STATUS_REGISTER, (tmp << shift) );
743     status = MG5UART_GETREG(pMG5UART, MG5UART_STATUS_REGISTER) >> shift;
744  }
745
746  if ( status & MONGOOSEV_UART_RX_READY )
747  {
748     return (int) MG5UART_GETREG(pMG5UART_port, MG5UART_RX_BUFFER);
749  }
750  else
751  {
752     return -1;
753  }
754}
755
756/*
757 *  mg5uart_baud_rate
758 */
759
760MG5UART_STATIC int mg5uart_baud_rate(
761  int           minor,
762  uint32_t      baud,
763  uint32_t     *code
764)
765{
766  uint32_t   clock;
767  uint32_t   tmp_code;
768  uint32_t   baud_requested;
769
770  baud_requested = baud & CBAUD;
771  if (!baud_requested)
772    baud_requested = B9600;              /* default to 9600 baud */
773
774  baud_requested = rtems_termios_baud_to_number( baud_requested );
775
776  clock = (uint32_t) Console_Port_Tbl[minor]->ulClock;
777  if (!clock)
778    rtems_fatal_error_occurred(RTEMS_INVALID_NUMBER);
779
780  /*
781   *  Formula is Code = round(ClockFrequency / Baud - 1).
782   *
783   *  Since this is integer math, we will divide by twice the baud and
784   *  check the remaining odd bit.
785   */
786
787  tmp_code = (clock / baud_requested) - 1;
788
789  /*
790   *  From section 12.7, "Keep C>100 for best receiver operation."
791   *  That is 100 cycles which is not a lot of instructions.  It is
792   *  reasonable to think that the Mongoose-V could not keep
793   *  up with C < 100.
794   */
795
796  if ( tmp_code < 100 )
797    return RTEMS_INVALID_NUMBER;
798
799  /*
800   *  upper word is receiver baud and lower word is transmitter baud
801   */
802
803  *code = (tmp_code << 16) | tmp_code;
804
805  return 0;
806}
807
808
809
810
811/*
812 *  mg5uart_enable_interrupts
813 *
814 *  This function enables specific interrupt sources on the DUART.
815 */
816
817MG5UART_STATIC void mg5uart_enable_interrupts(
818  int minor,
819  int mask
820)
821{
822  uint32_t              pMG5UART;
823  uint32_t              maskSave;
824  uint32_t              shift;
825  rtems_interrupt_level  Irql;
826
827  pMG5UART = Console_Port_Tbl[minor]->ulCtrlPort1;
828
829  /*
830   *  Enable interrupts on RX and TX -- not break
831   */
832
833  if ( Console_Port_Tbl[minor]->ulDataPort == MG5UART_UART0 )
834    shift = MONGOOSEV_UART0_IRQ_SHIFT;
835  else
836    shift = MONGOOSEV_UART1_IRQ_SHIFT;
837
838
839  rtems_interrupt_disable(Irql);
840
841  maskSave = MG5UART_GETREG( pMG5UART, MG5UART_INTERRUPT_MASK_REGISTER );
842
843  MG5UART_SETREG(
844     pMG5UART,
845     MG5UART_INTERRUPT_MASK_REGISTER,
846     (maskSave & ~(MONGOOSEV_UART_ALL_STATUS_BITS << shift)) | (mask << shift) );
847
848  rtems_interrupt_enable(Irql);
849}
850
851
852
853/*
854 * Flow control is only supported when using interrupts
855 */
856
857const console_fns mg5uart_fns =
858{
859  libchip_serial_default_probe,   /* deviceProbe */
860  mg5uart_open,                   /* deviceFirstOpen */
861  NULL,                           /* deviceLastClose */
862  NULL,                           /* deviceRead */
863  mg5uart_write_support_int,      /* deviceWrite */
864  mg5uart_initialize_interrupts,  /* deviceInitialize */
865  mg5uart_write_polled,           /* deviceWritePolled */
866  mg5uart_set_attributes,         /* deviceSetAttributes */
867  TRUE                            /* deviceOutputUsesInterrupts */
868};
869
870const console_fns mg5uart_fns_polled =
871{
872  libchip_serial_default_probe,        /* deviceProbe */
873  mg5uart_open,                        /* deviceFirstOpen */
874  mg5uart_close,                       /* deviceLastClose */
875  mg5uart_inbyte_nonblocking_polled,   /* deviceRead */
876  mg5uart_write_support_polled,        /* deviceWrite */
877  mg5uart_init,                        /* deviceInitialize */
878  mg5uart_write_polled,                /* deviceWritePolled */
879  mg5uart_set_attributes,              /* deviceSetAttributes */
880  FALSE,                               /* deviceOutputUsesInterrupts */
881};
Note: See TracBrowser for help on using the repository browser.