source: rtems/c/src/lib/libcpu/mips/mongoosev/duart/mg5uart.c @ 25eab8f

4.115
Last change on this file since 25eab8f was 25eab8f, checked in by Ralf Corsepius <ralf.corsepius@…>, on 01/30/11 at 17:42:26

2011-01-30 Ralf Corsépius <ralf.corsepius@…>

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