source: rtems/c/src/lib/libbsp/m68k/genmcf548x/console/console.c @ 69effbb4

4.104.114.95
Last change on this file since 69effbb4 was 69effbb4, checked in by Thomas Doerfler <Thomas.Doerfler@…>, on Jul 11, 2008 at 10:00:41 AM

added variant to gen68360 BSP
added genmcf548x BSP

  • Property mode set to 100644
File size: 26.1 KB
Line 
1/*===============================================================*\
2| Project: RTEMS generic mcf548x BSP                              |
3+-----------------------------------------------------------------+
4| File: console.c                                                 |
5+-----------------------------------------------------------------+
6| The file contains the console driver code of generic MCF548x    |
7| BSP.                                                            |
8+-----------------------------------------------------------------+
9|                    Copyright (c) 2007                           |
10|                    Embedded Brains GmbH                         |
11|                    Obere Lagerstr. 30                           |
12|                    D-82178 Puchheim                             |
13|                    Germany                                      |
14|                    rtems@embedded-brains.de                     |
15+-----------------------------------------------------------------+
16|                                                                 |
17| Parts of the code has been derived from the "dBUG source code"  |
18| package Freescale is providing for M548X EVBs. The usage of     |
19| the modified or unmodified code and it's integration into the   |
20| generic mcf548x BSP has been done according to the Freescale    |
21| license terms.                                                  |
22|                                                                 |
23| The Freescale license terms can be reviewed in the file         |
24|                                                                 |
25|    Freescale_license.txt                                        |
26|                                                                 |
27+-----------------------------------------------------------------+
28|                                                                 |
29| The generic mcf548x BSP has been developed on the basic         |
30| structures and modules of the av5282 BSP.                       |
31|                                                                 |
32+-----------------------------------------------------------------+
33|                                                                 |
34| The license and distribution terms for this file may be         |
35| found in the file LICENSE in this distribution or at            |
36|                                                                 |
37| http://www.rtems.com/license/LICENSE.                           |
38|                                                                 |
39+-----------------------------------------------------------------+
40|                                                                 |
41|   date                      history                        ID   |
42| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
43| 12.11.07                    1.0                            ras  |
44|                                                                 |
45\*===============================================================*/
46
47 /*
48  *  Multi UART console serial I/O.
49  *
50  * TO DO: Add DMA input/output
51  */
52
53#include <stdio.h>
54#include <fcntl.h>
55#include <rtems/libio.h>
56#include <rtems/termiostypes.h>
57#include <termios.h>
58#include <bsp.h>
59#include <malloc.h>
60#include <rtems/mw_uid.h>
61
62#include <rtems/bspIo.h>
63
64#define UART_INTC0_IRQ_VECTOR(x) (64+35-(x))
65
66#define MCF548X_PSC_SR_ERROR ( MCF548X_PSC_SR_RB_NEOF   | \
67                           MCF548X_PSC_SR_FE_PHYERR | \
68                           MCF548X_PSC_SR_PE_CRCERR | \
69                           MCF548X_PSC_SR_OE )
70
71static int IntUartPollWrite(int minor, const char *buf, int len);
72static int IntUartPollRead (int minor);
73
74static void
75_BSP_null_char( char c )
76{
77        int level;
78
79    if (c == '\n')
80        _BSP_null_char('\r');
81        rtems_interrupt_disable(level);
82    while (!((MCF548X_PSC_SR(CONSOLE_PORT) & MCF548X_PSC_SR_TXRDY)))
83        continue;
84    *((uint8_t *) &MCF548X_PSC_TB(CONSOLE_PORT)) = c;
85    while (!((MCF548X_PSC_SR(CONSOLE_PORT) & MCF548X_PSC_SR_TXRDY)))
86        continue;
87        rtems_interrupt_enable(level);
88}
89BSP_output_char_function_type BSP_output_char = _BSP_null_char;
90
91#define MAX_UART_INFO     4
92#define RX_BUFFER_SIZE    248
93
94
95struct IntUartInfoStruct
96{
97        int                    iomode;
98        volatile int           imr;
99        int                    baud;
100        int                    databits;
101        int                    parity;
102        int                    stopbits;
103        int                    hwflow;
104        int                    rx_in;
105        int                    rx_out;
106        char                   rx_buffer[RX_BUFFER_SIZE];
107        void                  *ttyp;
108};
109
110struct IntUartInfoStruct IntUartInfo[MAX_UART_INFO];
111
112static int GetBaud( int baudHandle )
113{
114        int baud = 9600;
115        switch(baudHandle)
116        {
117                case B0:
118                        baud = (int)0;
119                        break;
120                case B1200:
121                        baud = (int)1200;
122                        break;
123                case B2400:
124                        baud = (int)2400;
125                        break;
126                case B4800:
127                        baud = (int)4800;
128                        break;
129                case B9600:
130                        baud = (int)9600;
131                        break;
132                case B19200:
133                        baud = (int)19200;
134                        break;
135                case B38400:
136                        baud = (int)38400;
137                        break;
138                case B57600:
139                        baud = (int)57600;
140                        break;
141                case B115200:
142                        baud = (int)115200;
143                        break;
144        }
145        return baud;
146}
147
148/***************************************************************************
149   Function : IntUartSet
150
151   Description : This updates the hardware UART settings.
152 ***************************************************************************/
153static void
154IntUartSet(int minor, int baud, int databits, int parity, int stopbits, int hwflow)
155{
156        uint8_t                    psc_mode_1 = 0, psc_mode_2 = 0;
157        uint16_t                   divider;
158        int                        level;
159        struct IntUartInfoStruct   *info = &IntUartInfo[minor];
160
161        rtems_interrupt_disable(level);
162
163        /* disable interrupts, clear RTS line, and disable the UARTS */
164        /* Mask all psc interrupts */
165        MCF548X_PSC_IMR(minor) = 0x0000;
166
167        /* Clear RTS to send */
168        MCF548X_PSC_OPSET(minor) &= ~(MCF548X_PSC_OPSET_RTS);
169
170        /* Disable receiver and transmitter */
171    MCF548X_PSC_CR(minor) &= ~(MCF548X_PSC_CR_RX_ENABLED | MCF548X_PSC_CR_TX_ENABLED);
172
173    /* provide gpio settings */
174    switch (minor)
175          {
176      case 0:
177        MCF548X_GPIO_PAR_PSC0    = (0 | MCF548X_GPIO_PAR_PSC0_PAR_TXD0 | MCF548X_GPIO_PAR_PSC0_PAR_RXD0);
178
179        if(hwflow)
180          {
181          MCF548X_GPIO_PAR_PSC0 |= (0 | MCF548X_GPIO_PAR_PSC0_PAR_CTS0_CTS | MCF548X_GPIO_PAR_PSC0_PAR_RTS0_RTS);
182          }
183        break;
184      case 1:
185        MCF548X_GPIO_PAR_PSC1    = (0 | MCF548X_GPIO_PAR_PSC1_PAR_TXD1 | MCF548X_GPIO_PAR_PSC1_PAR_RXD1);
186
187        if(hwflow)
188          {
189          MCF548X_GPIO_PAR_PSC1 |= (0 | MCF548X_GPIO_PAR_PSC1_PAR_CTS1_CTS | MCF548X_GPIO_PAR_PSC1_PAR_RTS1_RTS);
190          }
191        break;
192      case 2:
193        MCF548X_GPIO_PAR_PSC2    = (0 | MCF548X_GPIO_PAR_PSC2_PAR_TXD2 | MCF548X_GPIO_PAR_PSC2_PAR_RXD2);
194
195        if(hwflow)
196          {
197          MCF548X_GPIO_PAR_PSC2 |= (0 | MCF548X_GPIO_PAR_PSC2_PAR_CTS2_CTS | MCF548X_GPIO_PAR_PSC2_PAR_RTS2_RTS);
198          }
199        break;
200      case 3:
201        MCF548X_GPIO_PAR_PSC3    = (0 | MCF548X_GPIO_PAR_PSC3_PAR_TXD3 | MCF548X_GPIO_PAR_PSC3_PAR_RXD3);
202
203        if(hwflow)
204          {
205          MCF548X_GPIO_PAR_PSC3 |= (0 | MCF548X_GPIO_PAR_PSC3_PAR_CTS3_CTS | MCF548X_GPIO_PAR_PSC3_PAR_RTS3_RTS);
206          }
207        break;
208      default:
209        break;
210        }
211
212    /* save the current values */
213        info->imr      = 0;
214        info->baud     = baud;
215        info->databits = databits;
216        info->parity   = parity;
217        info->stopbits = stopbits;
218        info->hwflow   = hwflow;
219
220    /* Put PSC in UART mode */
221        MCF548X_PSC_SICR(minor) = MCF548X_PSC_SICR_SIM_UART;
222
223    /* set the baud rate values */
224        MCF548X_PSC_CSR(minor) = (0 | MCF548X_PSC_CSR_RCSEL_SYS_CLK | MCF548X_PSC_CSR_TCSEL_SYS_CLK);
225
226        /* Calculate baud settings */
227        divider = (uint16_t)((get_CPU_clock_speed())/(baud * 32));
228        MCF548X_PSC_CTUR(minor) =  (uint8_t) ((divider >> 8) & 0xFF);
229        MCF548X_PSC_CTLR(minor) =  (uint8_t) (divider & 0xFF);
230
231        /* Reset transmitter, receiver, mode register, and error conditions */
232        MCF548X_PSC_CR(minor) = MCF548X_PSC_CR_RESET_RX;
233        MCF548X_PSC_CR(minor) = MCF548X_PSC_CR_RESET_TX;
234        MCF548X_PSC_CR(minor) = MCF548X_PSC_CR_RESET_ERROR;
235        MCF548X_PSC_CR(minor) = MCF548X_PSC_CR_BKCHGINT;
236        MCF548X_PSC_CR(minor) = MCF548X_PSC_CR_RESET_MR;
237
238        /* check to see if doing hardware flow control */
239        if ( hwflow )
240        {
241                /* set hardware flow options */
242                psc_mode_1 = MCF548X_PSC_MR_RXRTS;
243        psc_mode_2 = MCF548X_PSC_MR_TXCTS;
244        }
245
246    /* set mode registers */
247        psc_mode_1 |= (uint8_t)(parity | databits);
248    psc_mode_2 |= (uint8_t)(stopbits);
249
250    /* set mode registers */
251        MCF548X_PSC_MR(minor) = psc_mode_1;
252    MCF548X_PSC_MR(minor) = psc_mode_2;
253
254    /* Setup FIFO Alarms */
255    MCF548X_PSC_RFAR(minor) = MCF548X_PSC_RFAR_ALARM(248);
256        MCF548X_PSC_TFAR(minor) = MCF548X_PSC_TFAR_ALARM(248);
257
258        /* check to see if interrupts need to be enabled */
259        if ( info->iomode != TERMIOS_POLLED )
260        {
261                /* enable rx interrupts */
262                info->imr |= MCF548X_PSC_IMR_RXRDY_FU;
263                MCF548X_PSC_IMR(minor) = info->imr;
264        }
265
266        /* check to see if doing hardware flow control */
267        if ( hwflow )
268        {
269                /* assert the RTS line */
270                MCF548X_PSC_OPSET(minor) = MCF548X_PSC_OPSET_RTS;
271        }
272
273        rtems_interrupt_enable(level);
274
275    /* Enable receiver and transmitter */
276        MCF548X_PSC_CR(minor) =(0 | MCF548X_PSC_CR_RX_ENABLED | MCF548X_PSC_CR_TX_ENABLED);
277
278
279}
280
281/***************************************************************************
282   Function : IntUartSetAttributes
283
284   Description : This provides the hardware-dependent portion of tcsetattr().
285   value and sets it. At the moment this just sets the baud rate.
286
287   Note: The highest baudrate is 115200 as this stays within
288   an error of +/- 5% at 25MHz processor clock
289 ***************************************************************************/
290static int
291IntUartSetAttributes(int minor, const struct termios *t)
292{
293/* set default index values */
294        int                         baud     = (int)9600;
295        int                         databits = (int)MCF548X_PSC_MR_BC_8;
296        int                         parity   = (int)MCF548X_PSC_MR_PM_NONE;
297        int                         stopbits = (int)MCF548X_PSC_MR_SB_STOP_BITS_1;
298        int                         hwflow   = (int)1;
299        struct IntUartInfoStruct   *info     = &IntUartInfo[minor];
300
301        /* check to see if input is valid */
302        if ( t != (const struct termios *)0 )
303        {
304                /* determine baud rate index */
305                baud = GetBaud( t->c_cflag & CBAUD );
306
307                /* determine data bits */
308                switch ( t->c_cflag & CSIZE )
309                {
310                        case CS5:
311                                databits = (int)MCF548X_PSC_MR_BC_5;
312                                break;
313                        case CS6:
314                                databits = (int)MCF548X_PSC_MR_BC_6;
315                                break;
316                        case CS7:
317                                databits = (int)MCF548X_PSC_MR_BC_7;
318                                break;
319                        case CS8:
320                                databits = (int)MCF548X_PSC_MR_BC_8;
321                                break;
322                }
323
324                /* determine if parity is enabled */
325                if ( t->c_cflag & PARENB )
326                {
327                        if ( t->c_cflag & PARODD )
328                        {
329                                /* odd parity */
330                                parity = (int)MCF548X_PSC_MR_PM_ODD;
331                        }
332                        else
333                        {
334                                /* even parity */
335                                parity = (int)MCF548X_PSC_MR_PM_EVEN;
336                        }
337                }
338
339                /* determine stop bits */
340                if ( t->c_cflag & CSTOPB )
341                {
342                        /* two stop bits */
343                        stopbits = (int)MCF548X_PSC_MR_SB_STOP_BITS_2;
344                }
345
346                /* check to see if hardware flow control */
347                if ( t->c_cflag & CRTSCTS )
348                {
349                        hwflow = 1;
350                }
351        }
352
353        /* check to see if values have changed */
354        if ( ( baud     != info->baud     ) ||
355                 ( databits != info->databits ) ||
356                 ( parity   != info->parity   ) ||
357                 ( stopbits != info->stopbits ) ||
358                 ( hwflow   != info->hwflow   ) )
359        {
360
361                /* call function to set values */
362                IntUartSet(minor, baud, databits, parity, stopbits, hwflow);
363        }
364
365return RTEMS_SUCCESSFUL;
366
367}
368
369/***************************************************************************
370   Function : IntUartInterruptHandler
371
372   Description : This is the interrupt handler for the internal uart. It
373   determines which channel caused the interrupt before queueing any received
374   chars and dequeueing chars waiting for transmission.
375 ***************************************************************************/
376static rtems_isr
377IntUartInterruptHandler(rtems_vector_number v)
378{
379        unsigned int                chan = v - UART_INTC0_IRQ_VECTOR(0);
380        struct IntUartInfoStruct   *info = &IntUartInfo[chan];
381
382        /* check to see if received data */
383        if ( MCF548X_PSC_ISR(chan) & MCF548X_PSC_ISR_RXRDY_FU )
384        {
385                /* read data and put into the receive buffer */
386                while ( MCF548X_PSC_SR(chan) & MCF548X_PSC_SR_RXRDY )
387                {
388
389                   /* put data in rx buffer */
390                        info->rx_buffer[info->rx_in] = *((uint8_t *)&MCF548X_PSC_RB(chan));
391
392           /* check for errors */
393           if ( MCF548X_PSC_SR(chan) & MCF548X_PSC_SR_ERROR )
394                        {
395                                /* clear the error */
396                                MCF548X_PSC_CR(chan) = MCF548X_PSC_CR_RESET_ERROR;
397                        }
398
399                        /* update buffer values */
400                        info->rx_in++;
401
402                        if ( info->rx_in >= RX_BUFFER_SIZE )
403                        {
404                                info->rx_in = 0;
405                        }
406                }
407                /* Make sure the port has been opened */
408                if ( info->ttyp )
409                {
410
411                        /* check to see if task driven */
412                        if ( info->iomode == TERMIOS_TASK_DRIVEN )
413                        {
414                                /* notify rx task that rx buffer has data */
415                                rtems_termios_rxirq_occured(info->ttyp);
416                        }
417                        else
418                        {
419                                /* Push up the received data */
420                                rtems_termios_enqueue_raw_characters(info->ttyp, info->rx_buffer, info->rx_in);
421                                info->rx_in    = 0;
422                        }
423                }
424        }
425
426        /* check to see if data needs to be transmitted */
427        if ( ( info->imr & MCF548X_PSC_IMR_TXRDY ) &&
428                 ( MCF548X_PSC_ISR(chan) & MCF548X_PSC_ISR_TXRDY ) )
429        {
430
431                /* disable tx interrupts */
432                info->imr &= ~MCF548X_PSC_IMR_TXRDY;
433                MCF548X_PSC_IMR(chan) = info->imr;
434
435                /* tell upper level that character has been sent */
436                if ( info->ttyp )
437                        rtems_termios_dequeue_characters(info->ttyp, 1);
438        }
439
440}
441
442/***************************************************************************
443   Function : IntUartInitialize
444
445   Description : This initialises the internal uart hardware for all
446   internal uarts. If the internal uart is to be interrupt driven then the
447   interrupt vectors are hooked.
448 ***************************************************************************/
449static void
450IntUartInitialize(void)
451{
452    unsigned int        chan;
453        struct IntUartInfoStruct   *info;
454        rtems_isr_entry old_handler;
455    int level;
456
457        for ( chan = 0; chan < MAX_UART_INFO; chan++ )
458        {
459                info = &IntUartInfo[chan];
460
461                info->ttyp     = NULL;
462                info->rx_in    = 0;
463                info->rx_out   = 0;
464                info->baud     = -1;
465                info->databits = -1;
466                info->parity   = -1;
467                info->stopbits = -1;
468                info->hwflow   = -1;
469
470                MCF548X_PSC_ACR(chan) = 0;
471                MCF548X_PSC_IMR(chan) = 0;
472                if ( info->iomode != TERMIOS_POLLED )
473                {
474                        rtems_interrupt_catch (IntUartInterruptHandler,
475                                                                   UART_INTC0_IRQ_VECTOR(chan),
476                                                                   &old_handler);
477                }
478
479                /* set uart default values */
480                IntUartSetAttributes(chan, NULL);
481
482        /* unmask interrupt */
483                rtems_interrupt_disable(level);
484        switch(chan) {
485        case 0:
486            MCF548X_INTC_ICR35 =   MCF548X_INTC_ICRn_IL(PSC0_IRQ_LEVEL) |
487                               MCF548X_INTC_ICRn_IP(PSC0_IRQ_PRIORITY);
488            MCF548X_INTC_IMRH &= ~(MCF548X_INTC_IMRH_INT_MASK35 |
489                                    MCF548X_INTC_IMRL_MASKALL);
490            break;
491
492        case 1:
493            MCF548X_INTC_ICR34 =   MCF548X_INTC_ICRn_IL(PSC1_IRQ_LEVEL) |
494                               MCF548X_INTC_ICRn_IP(PSC1_IRQ_PRIORITY);
495            MCF548X_INTC_IMRH &= ~(MCF548X_INTC_IMRH_INT_MASK34 |
496                                    MCF548X_INTC_IMRL_MASKALL);
497            break;
498
499        case 2:
500            MCF548X_INTC_ICR33 =   MCF548X_INTC_ICRn_IL(PSC2_IRQ_LEVEL) |
501                               MCF548X_INTC_ICRn_IP(PSC2_IRQ_PRIORITY);
502            MCF548X_INTC_IMRH &= ~(MCF548X_INTC_IMRH_INT_MASK33 |
503                                    MCF548X_INTC_IMRL_MASKALL);
504            break;
505
506        case 3:
507            MCF548X_INTC_ICR32 =   MCF548X_INTC_ICRn_IL(PSC3_IRQ_LEVEL) |
508                               MCF548X_INTC_ICRn_IP(PSC3_IRQ_PRIORITY);
509            MCF548X_INTC_IMRH &= ~(MCF548X_INTC_IMRH_INT_MASK32 |
510                                    MCF548X_INTC_IMRL_MASKALL);
511            break;
512        }
513                rtems_interrupt_enable(level);
514
515        } /* of chan loop */
516
517
518} /* IntUartInitialise */
519
520/***************************************************************************
521   Function : IntUartInterruptWrite
522
523   Description : This writes a single character to the appropriate uart
524   channel. This is either called during an interrupt or in the user's task
525   to initiate a transmit sequence. Calling this routine enables Tx
526   interrupts.
527 ***************************************************************************/
528static int
529IntUartInterruptWrite (int minor, const char *buf, int len)
530{
531        int level;
532
533        rtems_interrupt_disable(level);
534
535        /* write out character */
536        MCF548X_PSC_TB(minor) = *buf;
537
538        /* enable tx interrupt */
539        IntUartInfo[minor].imr |= MCF548X_PSC_IMR_TXRDY;
540        MCF548X_PSC_IMR(minor) = IntUartInfo[minor].imr;
541
542        rtems_interrupt_enable(level);
543        return 0;
544}
545
546/***************************************************************************
547   Function : IntUartInterruptOpen
548
549   Description : This enables interrupts when the tty is opened.
550 ***************************************************************************/
551static int
552IntUartInterruptOpen(int major, int minor, void *arg)
553{
554        struct IntUartInfoStruct   *info = &IntUartInfo[minor];
555
556        /* enable the uart */
557        MCF548X_PSC_CR(minor) = (MCF548X_PSC_CR_TX_ENABLED | MCF548X_PSC_CR_RX_ENABLED);
558
559        /* check to see if interrupts need to be enabled */
560        if ( info->iomode != TERMIOS_POLLED )
561        {
562                /* enable rx interrupts */
563                info->imr |= MCF548X_PSC_IMR_RXRDY_FU;
564                MCF548X_PSC_IMR(minor) = info->imr;
565        }
566
567        /* check to see if doing hardware flow control */
568        if ( info->hwflow )
569        {
570                /* assert the RTS line */
571                MCF548X_PSC_OPSET(minor) = MCF548X_PSC_OPSET_RTS;
572        }
573
574        return 0;
575}
576
577
578/***************************************************************************
579   Function : IntUartInterruptClose
580
581   Description : This disables interrupts when the tty is closed.
582 ***************************************************************************/
583static int
584IntUartInterruptClose(int major, int minor, void *arg)
585{
586        struct IntUartInfoStruct   *info = &IntUartInfo[minor];
587
588        /* disable the interrupts and the uart */
589        MCF548X_PSC_IMR(minor) = 0;
590        MCF548X_PSC_CR(minor) = (MCF548X_PSC_CR_TX_ENABLED | MCF548X_PSC_CR_RX_ENABLED);
591
592        /* reset values */
593        info->ttyp     = NULL;
594        info->imr       = 0;
595        info->rx_in    = 0;
596        info->rx_out   = 0;
597
598        return 0;
599}
600
601/***************************************************************************
602   Function : IntUartTaskRead
603
604   Description : This reads all available characters from the internal uart
605   and places them into the termios buffer.  The rx interrupts will be
606   re-enabled after all data has been read.
607 ***************************************************************************/
608static int
609IntUartTaskRead(int minor)
610{
611        char                        buffer[RX_BUFFER_SIZE];
612        int                         count;
613        int                         rx_in;
614        int                         index = 0;
615        struct IntUartInfoStruct   *info  = &IntUartInfo[minor];
616
617        /* determine number of values to copy out */
618        rx_in = info->rx_in;
619        if ( info->rx_out <= rx_in )
620        {
621                count = rx_in - info->rx_out;
622        }
623        else
624        {
625                count = (RX_BUFFER_SIZE - info->rx_out) + rx_in;
626        }
627
628        /* copy data into local buffer from rx buffer */
629        while ( ( index < count ) && ( index < RX_BUFFER_SIZE ) )
630        {
631                /* copy data byte */
632                buffer[index] = info->rx_buffer[info->rx_out];
633                index++;
634
635                /* increment rx buffer values */
636                info->rx_out++;
637                if ( info->rx_out >= RX_BUFFER_SIZE )
638                {
639                        info->rx_out = 0;
640                }
641        }
642
643        /* check to see if buffer is not empty */
644        if ( count > 0 )
645        {
646                /* set characters into termios buffer  */
647                rtems_termios_enqueue_raw_characters(info->ttyp, buffer, count);
648        }
649
650        return EOF;
651}
652
653
654/***************************************************************************
655   Function : IntUartPollRead
656
657   Description : This reads a character from the internal uart. It returns
658   to the caller without blocking if not character is waiting.
659 ***************************************************************************/
660static int
661IntUartPollRead (int minor)
662{
663if (!((MCF548X_PSC_SR(minor) & MCF548X_PSC_SR_RXRDY)))
664                return(-1);
665
666        return *((uint8_t *)&MCF548X_PSC_RB(minor));
667}
668
669
670/***************************************************************************
671   Function : IntUartPollWrite
672
673   Description : This writes out each character in the buffer to the
674   appropriate internal uart channel waiting till each one is sucessfully
675   transmitted.
676 ***************************************************************************/
677static int
678IntUartPollWrite (int minor, const char *buf, int len)
679{
680/* loop over buffer */
681        while ( len-- )
682        {
683                /* block until we can transmit */
684                while (!((MCF548X_PSC_SR(minor) & MCF548X_PSC_SR_TXRDY)))
685                        continue;
686                /* transmit data byte */
687                *((uint8_t *)&MCF548X_PSC_TB(minor)) = *buf++;
688        }
689        return 0;
690}
691
692/***************************************************************************
693   Function : console_initialize
694
695   Description : This initialises termios, both sets of uart hardware before
696   registering /dev/tty devices for each channel and the system /dev/console.
697 ***************************************************************************/
698rtems_device_driver console_initialize(
699        rtems_device_major_number  major,
700        rtems_device_minor_number  minor,
701        void  *arg )
702{
703        rtems_status_code status;
704
705
706        /* Set up TERMIOS */
707        rtems_termios_initialize ();
708
709        /* set io modes for the different channels and initialize device */
710    IntUartInfo[minor].iomode = TERMIOS_IRQ_DRIVEN; //TERMIOS_POLLED;
711        IntUartInitialize();
712
713        /* Register the console port */
714        status = rtems_io_register_name ("/dev/console", major, CONSOLE_PORT);
715        if ( status != RTEMS_SUCCESSFUL )
716        {
717                rtems_fatal_error_occurred (status);
718        }
719
720        /* Register the other port */
721        if ( CONSOLE_PORT != 0 )
722        {
723                status = rtems_io_register_name ("/dev/tty00", major, 0);
724                if ( status != RTEMS_SUCCESSFUL )
725                {
726                        rtems_fatal_error_occurred (status);
727                }
728        }
729        if ( CONSOLE_PORT != 1 )
730        {
731                status = rtems_io_register_name ("/dev/tty01", major, 1);
732                if ( status != RTEMS_SUCCESSFUL )
733                {
734                        rtems_fatal_error_occurred (status);
735                }
736        }
737
738        return(RTEMS_SUCCESSFUL);
739}
740
741/***************************************************************************
742   Function : console_open
743
744   Description : This actually opens the device depending on the minor
745   number set during initialisation. The device specific access routines are
746   passed to termios when the devices is opened depending on whether it is
747   polled or not.
748 ***************************************************************************/
749rtems_device_driver console_open(
750        rtems_device_major_number major,
751        rtems_device_minor_number minor,
752        void  * arg)
753{
754    rtems_status_code                status = RTEMS_INVALID_NUMBER;
755        rtems_libio_open_close_args_t   *args   = (rtems_libio_open_close_args_t *)arg;
756        struct IntUartInfoStruct        *info;
757
758        static const rtems_termios_callbacks IntUartPollCallbacks = {
759                NULL,                             /* firstOpen */
760                NULL,                             /* lastClose */
761                IntUartPollRead,          /* pollRead */
762                IntUartPollWrite,         /* write */
763                IntUartSetAttributes, /* setAttributes */
764                NULL,                             /* stopRemoteTx */
765                NULL,                             /* startRemoteTx */
766                TERMIOS_POLLED            /* mode */
767        };
768        static const rtems_termios_callbacks IntUartIntrCallbacks = {
769                IntUartInterruptOpen,  /* firstOpen */
770                IntUartInterruptClose, /* lastClose */
771                NULL,                              /* pollRead */
772                IntUartInterruptWrite, /* write */
773                IntUartSetAttributes,  /* setAttributes */
774                NULL,                              /* stopRemoteTx */
775                NULL,                              /* startRemoteTx */
776                TERMIOS_IRQ_DRIVEN         /* mode */
777        };
778
779        static const rtems_termios_callbacks IntUartTaskCallbacks = {
780                IntUartInterruptOpen,  /* firstOpen */
781                IntUartInterruptClose, /* lastClose */
782                IntUartTaskRead,           /* pollRead */
783                IntUartInterruptWrite, /* write */
784                IntUartSetAttributes,  /* setAttributes */
785                NULL,                              /* stopRemoteTx */
786                NULL,                              /* startRemoteTx */
787                TERMIOS_TASK_DRIVEN        /* mode */
788        };
789
790        /* open the port depending on the minor device number */
791        if ( ( minor >= 0 ) && ( minor < MAX_UART_INFO ) )
792        {
793                info = &IntUartInfo[minor];
794                switch ( info->iomode )
795                {
796                        case TERMIOS_POLLED:
797                                status = rtems_termios_open(major, minor, arg, &IntUartPollCallbacks);
798                                break;
799                        case TERMIOS_IRQ_DRIVEN:
800                                status = rtems_termios_open(major, minor, arg, &IntUartIntrCallbacks);
801                                info->ttyp = args->iop->data1;
802                                break;
803                        case TERMIOS_TASK_DRIVEN:
804                                status = rtems_termios_open(major, minor, arg, &IntUartTaskCallbacks);
805                                info->ttyp = args->iop->data1;
806                                break;
807                }
808        }
809
810        return( status );
811}
812
813/***************************************************************************
814   Function : console_close
815
816   Description : This closes the device via termios
817 ***************************************************************************/
818rtems_device_driver console_close(
819        rtems_device_major_number major,
820        rtems_device_minor_number minor,
821        void   * arg)
822{
823    return(rtems_termios_close (arg));
824}
825
826/***************************************************************************
827   Function : console_read
828
829   Description : Read from the device via termios
830 ***************************************************************************/
831rtems_device_driver console_read(
832        rtems_device_major_number major,
833        rtems_device_minor_number minor,
834        void  * arg)
835{
836    return(rtems_termios_read (arg));
837}
838
839/***************************************************************************
840   Function : console_write
841
842   Description : Write to the device via termios
843 ***************************************************************************/
844rtems_device_driver console_write(
845        rtems_device_major_number major,
846        rtems_device_minor_number minor,
847        void  * arg)
848{
849    return(rtems_termios_write (arg));
850}
851
852/***************************************************************************
853   Function : console_ioctl
854
855   Description : Pass the IOCtl call to termios
856 ***************************************************************************/
857rtems_device_driver console_control(
858        rtems_device_major_number major,
859        rtems_device_minor_number minor,
860        void  * arg)
861{
862    return( rtems_termios_ioctl (arg) );
863}
864
865
866int DEBUG_OUTCHAR(int c)
867{
868    if(c == '\n')
869        DEBUG_OUTCHAR('\r');
870    _BSP_null_char(c);
871    return c;
872}
873void DEBUG_OUTSTR(const char *msg)
874{
875    while (*msg)
876        DEBUG_OUTCHAR(*msg++);
877}
878void DEBUG_OUTNUM(int i)
879{
880    int n;
881    static const char map[] = "0123456789ABCDEF";
882    DEBUG_OUTCHAR(' ');
883    for (n = 28 ; n >= 0 ; n -= 4)
884        DEBUG_OUTCHAR(map[(i >> n) & 0xF]);
885}
886
Note: See TracBrowser for help on using the repository browser.