source: rtems/c/src/lib/libbsp/m68k/genmcf548x/console/console.c @ 8d292011

4.115
Last change on this file since 8d292011 was 8d292011, checked in by Sebastian Huber <sebastian.huber@…>, on 12/05/13 at 16:26:41

bsp/genmcf548x: Add initial values for INTC_ICRn

According to the manual the application must use unique and
non-overlapping level and priority definitions for enabled interrupts.

  • Property mode set to 100644
File size: 25.5 KB
RevLine 
[69effbb4]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
[39a9f8e]71static ssize_t IntUartPollWrite(int minor, const char *buf, size_t len);
[69effbb4]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}
[989938f1]89BSP_output_char_function_type     BSP_output_char = _BSP_null_char;
90BSP_polling_getchar_function_type BSP_poll_char = NULL;
[69effbb4]91
92#define MAX_UART_INFO     4
93#define RX_BUFFER_SIZE    248
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{
[a9d0c6ec]114        int baud = BSP_CONSOLE_BAUD;
[69effbb4]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 */
[5ea4e63]294#ifdef HAS_DBUG
295        int                         baud     = DBUG_SETTINGS.console_baudrate;
296#else
[a9d0c6ec]297        int                         baud     = (int)BSP_CONSOLE_BAUD;
[5ea4e63]298#endif
[69effbb4]299        int                         databits = (int)MCF548X_PSC_MR_BC_8;
300        int                         parity   = (int)MCF548X_PSC_MR_PM_NONE;
301        int                         stopbits = (int)MCF548X_PSC_MR_SB_STOP_BITS_1;
302        int                         hwflow   = (int)1;
303        struct IntUartInfoStruct   *info     = &IntUartInfo[minor];
304
305        /* check to see if input is valid */
306        if ( t != (const struct termios *)0 )
307        {
308                /* determine baud rate index */
309                baud = GetBaud( t->c_cflag & CBAUD );
310
311                /* determine data bits */
312                switch ( t->c_cflag & CSIZE )
313                {
314                        case CS5:
315                                databits = (int)MCF548X_PSC_MR_BC_5;
316                                break;
317                        case CS6:
318                                databits = (int)MCF548X_PSC_MR_BC_6;
319                                break;
320                        case CS7:
321                                databits = (int)MCF548X_PSC_MR_BC_7;
322                                break;
323                        case CS8:
324                                databits = (int)MCF548X_PSC_MR_BC_8;
325                                break;
326                }
327
328                /* determine if parity is enabled */
329                if ( t->c_cflag & PARENB )
330                {
331                        if ( t->c_cflag & PARODD )
332                        {
333                                /* odd parity */
334                                parity = (int)MCF548X_PSC_MR_PM_ODD;
335                        }
336                        else
337                        {
338                                /* even parity */
339                                parity = (int)MCF548X_PSC_MR_PM_EVEN;
340                        }
341                }
342
343                /* determine stop bits */
344                if ( t->c_cflag & CSTOPB )
345                {
346                        /* two stop bits */
347                        stopbits = (int)MCF548X_PSC_MR_SB_STOP_BITS_2;
348                }
349
350                /* check to see if hardware flow control */
351                if ( t->c_cflag & CRTSCTS )
352                {
353                        hwflow = 1;
354                }
355        }
356
357        /* check to see if values have changed */
358        if ( ( baud     != info->baud     ) ||
359                 ( databits != info->databits ) ||
360                 ( parity   != info->parity   ) ||
361                 ( stopbits != info->stopbits ) ||
362                 ( hwflow   != info->hwflow   ) )
363        {
364
365                /* call function to set values */
366                IntUartSet(minor, baud, databits, parity, stopbits, hwflow);
367        }
368
369return RTEMS_SUCCESSFUL;
370
371}
372
373/***************************************************************************
374   Function : IntUartInterruptHandler
375
376   Description : This is the interrupt handler for the internal uart. It
377   determines which channel caused the interrupt before queueing any received
378   chars and dequeueing chars waiting for transmission.
379 ***************************************************************************/
380static rtems_isr
381IntUartInterruptHandler(rtems_vector_number v)
382{
383        unsigned int                chan = v - UART_INTC0_IRQ_VECTOR(0);
384        struct IntUartInfoStruct   *info = &IntUartInfo[chan];
385
386        /* check to see if received data */
387        if ( MCF548X_PSC_ISR(chan) & MCF548X_PSC_ISR_RXRDY_FU )
388        {
389                /* read data and put into the receive buffer */
390                while ( MCF548X_PSC_SR(chan) & MCF548X_PSC_SR_RXRDY )
391                {
392
393                   /* put data in rx buffer */
[5ea4e63]394                        info->rx_buffer[info->rx_in] = *((volatile uint8_t *)&MCF548X_PSC_RB(chan));
[69effbb4]395
396           /* check for errors */
397           if ( MCF548X_PSC_SR(chan) & MCF548X_PSC_SR_ERROR )
398                        {
399                                /* clear the error */
400                                MCF548X_PSC_CR(chan) = MCF548X_PSC_CR_RESET_ERROR;
401                        }
402
403                        /* update buffer values */
404                        info->rx_in++;
405
406                        if ( info->rx_in >= RX_BUFFER_SIZE )
407                        {
408                                info->rx_in = 0;
409                        }
410                }
411                /* Make sure the port has been opened */
412                if ( info->ttyp )
413                {
414
415                        /* check to see if task driven */
416                        if ( info->iomode == TERMIOS_TASK_DRIVEN )
417                        {
418                                /* notify rx task that rx buffer has data */
419                                rtems_termios_rxirq_occured(info->ttyp);
420                        }
421                        else
422                        {
423                                /* Push up the received data */
424                                rtems_termios_enqueue_raw_characters(info->ttyp, info->rx_buffer, info->rx_in);
425                                info->rx_in    = 0;
426                        }
427                }
428        }
429
430        /* check to see if data needs to be transmitted */
431        if ( ( info->imr & MCF548X_PSC_IMR_TXRDY ) &&
432                 ( MCF548X_PSC_ISR(chan) & MCF548X_PSC_ISR_TXRDY ) )
433        {
434
435                /* disable tx interrupts */
436                info->imr &= ~MCF548X_PSC_IMR_TXRDY;
437                MCF548X_PSC_IMR(chan) = info->imr;
438
439                /* tell upper level that character has been sent */
440                if ( info->ttyp )
441                        rtems_termios_dequeue_characters(info->ttyp, 1);
442        }
443
444}
445
446/***************************************************************************
447   Function : IntUartInitialize
448
449   Description : This initialises the internal uart hardware for all
450   internal uarts. If the internal uart is to be interrupt driven then the
451   interrupt vectors are hooked.
452 ***************************************************************************/
453static void
454IntUartInitialize(void)
455{
456    unsigned int        chan;
457        struct IntUartInfoStruct   *info;
458        rtems_isr_entry old_handler;
459    int level;
460
461        for ( chan = 0; chan < MAX_UART_INFO; chan++ )
462        {
463                info = &IntUartInfo[chan];
464
465                info->ttyp     = NULL;
466                info->rx_in    = 0;
467                info->rx_out   = 0;
468                info->baud     = -1;
469                info->databits = -1;
470                info->parity   = -1;
471                info->stopbits = -1;
472                info->hwflow   = -1;
473
474                MCF548X_PSC_ACR(chan) = 0;
475                MCF548X_PSC_IMR(chan) = 0;
476                if ( info->iomode != TERMIOS_POLLED )
477                {
478                        rtems_interrupt_catch (IntUartInterruptHandler,
479                                                                   UART_INTC0_IRQ_VECTOR(chan),
480                                                                   &old_handler);
481                }
482
483                /* set uart default values */
484                IntUartSetAttributes(chan, NULL);
485
486        /* unmask interrupt */
487                rtems_interrupt_disable(level);
488        switch(chan) {
489        case 0:
[045821e]490            MCF548X_INTC_IMRH &= ~(MCF548X_INTC_IMRH_INT_MASK35);
[69effbb4]491            break;
492
493        case 1:
[045821e]494            MCF548X_INTC_IMRH &= ~(MCF548X_INTC_IMRH_INT_MASK34);
[69effbb4]495            break;
496
497        case 2:
[045821e]498            MCF548X_INTC_IMRH &= ~(MCF548X_INTC_IMRH_INT_MASK33);
[69effbb4]499            break;
500
501        case 3:
[045821e]502            MCF548X_INTC_IMRH &= ~(MCF548X_INTC_IMRH_INT_MASK32);
[69effbb4]503            break;
504        }
505                rtems_interrupt_enable(level);
506
507        } /* of chan loop */
508
509
510} /* IntUartInitialise */
511
512/***************************************************************************
513   Function : IntUartInterruptWrite
514
515   Description : This writes a single character to the appropriate uart
516   channel. This is either called during an interrupt or in the user's task
517   to initiate a transmit sequence. Calling this routine enables Tx
518   interrupts.
519 ***************************************************************************/
[39a9f8e]520static ssize_t
521IntUartInterruptWrite (int minor, const char *buf, size_t len)
[69effbb4]522{
[e18db9f]523        if (len > 0) {
524                /* write out character */
525                *(volatile uint8_t *)(&MCF548X_PSC_TB(minor)) = *buf;
[69effbb4]526
[e18db9f]527                /* enable tx interrupt */
528                IntUartInfo[minor].imr |= MCF548X_PSC_IMR_TXRDY;
529                MCF548X_PSC_IMR(minor) = IntUartInfo[minor].imr;
530        }
[69effbb4]531
532        return 0;
533}
534
535/***************************************************************************
536   Function : IntUartInterruptOpen
537
538   Description : This enables interrupts when the tty is opened.
539 ***************************************************************************/
540static int
541IntUartInterruptOpen(int major, int minor, void *arg)
542{
543        struct IntUartInfoStruct   *info = &IntUartInfo[minor];
544
545        /* enable the uart */
546        MCF548X_PSC_CR(minor) = (MCF548X_PSC_CR_TX_ENABLED | MCF548X_PSC_CR_RX_ENABLED);
547
548        /* check to see if interrupts need to be enabled */
549        if ( info->iomode != TERMIOS_POLLED )
550        {
551                /* enable rx interrupts */
552                info->imr |= MCF548X_PSC_IMR_RXRDY_FU;
553                MCF548X_PSC_IMR(minor) = info->imr;
554        }
555
556        /* check to see if doing hardware flow control */
557        if ( info->hwflow )
558        {
559                /* assert the RTS line */
560                MCF548X_PSC_OPSET(minor) = MCF548X_PSC_OPSET_RTS;
561        }
562
563        return 0;
564}
565
566
567/***************************************************************************
568   Function : IntUartInterruptClose
569
570   Description : This disables interrupts when the tty is closed.
571 ***************************************************************************/
572static int
573IntUartInterruptClose(int major, int minor, void *arg)
574{
575        struct IntUartInfoStruct   *info = &IntUartInfo[minor];
576
577        /* disable the interrupts and the uart */
578        MCF548X_PSC_IMR(minor) = 0;
579        MCF548X_PSC_CR(minor) = (MCF548X_PSC_CR_TX_ENABLED | MCF548X_PSC_CR_RX_ENABLED);
580
581        /* reset values */
582        info->ttyp     = NULL;
583        info->imr       = 0;
584        info->rx_in    = 0;
585        info->rx_out   = 0;
586
587        return 0;
588}
589
590/***************************************************************************
591   Function : IntUartTaskRead
592
593   Description : This reads all available characters from the internal uart
594   and places them into the termios buffer.  The rx interrupts will be
595   re-enabled after all data has been read.
596 ***************************************************************************/
597static int
598IntUartTaskRead(int minor)
599{
600        char                        buffer[RX_BUFFER_SIZE];
601        int                         count;
602        int                         rx_in;
603        int                         index = 0;
604        struct IntUartInfoStruct   *info  = &IntUartInfo[minor];
605
606        /* determine number of values to copy out */
607        rx_in = info->rx_in;
608        if ( info->rx_out <= rx_in )
609        {
610                count = rx_in - info->rx_out;
611        }
612        else
613        {
614                count = (RX_BUFFER_SIZE - info->rx_out) + rx_in;
615        }
616
617        /* copy data into local buffer from rx buffer */
618        while ( ( index < count ) && ( index < RX_BUFFER_SIZE ) )
619        {
620                /* copy data byte */
621                buffer[index] = info->rx_buffer[info->rx_out];
622                index++;
623
624                /* increment rx buffer values */
625                info->rx_out++;
626                if ( info->rx_out >= RX_BUFFER_SIZE )
627                {
628                        info->rx_out = 0;
629                }
630        }
631
632        /* check to see if buffer is not empty */
633        if ( count > 0 )
634        {
635                /* set characters into termios buffer  */
636                rtems_termios_enqueue_raw_characters(info->ttyp, buffer, count);
637        }
638
639        return EOF;
640}
641
642
643/***************************************************************************
644   Function : IntUartPollRead
645
646   Description : This reads a character from the internal uart. It returns
647   to the caller without blocking if not character is waiting.
648 ***************************************************************************/
649static int
650IntUartPollRead (int minor)
651{
652if (!((MCF548X_PSC_SR(minor) & MCF548X_PSC_SR_RXRDY)))
653                return(-1);
654
655        return *((uint8_t *)&MCF548X_PSC_RB(minor));
656}
657
658
659/***************************************************************************
660   Function : IntUartPollWrite
661
662   Description : This writes out each character in the buffer to the
663   appropriate internal uart channel waiting till each one is sucessfully
664   transmitted.
665 ***************************************************************************/
[39a9f8e]666static ssize_t
667IntUartPollWrite (int minor, const char *buf, size_t len)
[69effbb4]668{
[39a9f8e]669        size_t retval = len;
[69effbb4]670/* loop over buffer */
671        while ( len-- )
672        {
673                /* block until we can transmit */
674                while (!((MCF548X_PSC_SR(minor) & MCF548X_PSC_SR_TXRDY)))
675                        continue;
676                /* transmit data byte */
677                *((uint8_t *)&MCF548X_PSC_TB(minor)) = *buf++;
678        }
[39a9f8e]679        return retval;
[69effbb4]680}
681
682/***************************************************************************
683   Function : console_initialize
684
685   Description : This initialises termios, both sets of uart hardware before
686   registering /dev/tty devices for each channel and the system /dev/console.
687 ***************************************************************************/
688rtems_device_driver console_initialize(
689        rtems_device_major_number  major,
690        rtems_device_minor_number  minor,
691        void  *arg )
692{
693        rtems_status_code status;
694
695
696        /* Set up TERMIOS */
697        rtems_termios_initialize ();
698
699        /* set io modes for the different channels and initialize device */
700    IntUartInfo[minor].iomode = TERMIOS_IRQ_DRIVEN; //TERMIOS_POLLED;
701        IntUartInitialize();
702
703        /* Register the console port */
704        status = rtems_io_register_name ("/dev/console", major, CONSOLE_PORT);
705        if ( status != RTEMS_SUCCESSFUL )
706        {
707                rtems_fatal_error_occurred (status);
708        }
709
710        /* Register the other port */
711        if ( CONSOLE_PORT != 0 )
712        {
713                status = rtems_io_register_name ("/dev/tty00", major, 0);
714                if ( status != RTEMS_SUCCESSFUL )
715                {
716                        rtems_fatal_error_occurred (status);
717                }
718        }
719        if ( CONSOLE_PORT != 1 )
720        {
721                status = rtems_io_register_name ("/dev/tty01", major, 1);
722                if ( status != RTEMS_SUCCESSFUL )
723                {
724                        rtems_fatal_error_occurred (status);
725                }
726        }
727
728        return(RTEMS_SUCCESSFUL);
729}
730
731/***************************************************************************
732   Function : console_open
733
734   Description : This actually opens the device depending on the minor
735   number set during initialisation. The device specific access routines are
736   passed to termios when the devices is opened depending on whether it is
737   polled or not.
738 ***************************************************************************/
739rtems_device_driver console_open(
740        rtems_device_major_number major,
741        rtems_device_minor_number minor,
742        void  * arg)
743{
744    rtems_status_code                status = RTEMS_INVALID_NUMBER;
745        rtems_libio_open_close_args_t   *args   = (rtems_libio_open_close_args_t *)arg;
746        struct IntUartInfoStruct        *info;
747
748        static const rtems_termios_callbacks IntUartPollCallbacks = {
749                NULL,                             /* firstOpen */
750                NULL,                             /* lastClose */
751                IntUartPollRead,          /* pollRead */
752                IntUartPollWrite,         /* write */
753                IntUartSetAttributes, /* setAttributes */
754                NULL,                             /* stopRemoteTx */
755                NULL,                             /* startRemoteTx */
756                TERMIOS_POLLED            /* mode */
757        };
758        static const rtems_termios_callbacks IntUartIntrCallbacks = {
759                IntUartInterruptOpen,  /* firstOpen */
760                IntUartInterruptClose, /* lastClose */
761                NULL,                              /* pollRead */
762                IntUartInterruptWrite, /* write */
763                IntUartSetAttributes,  /* setAttributes */
764                NULL,                              /* stopRemoteTx */
765                NULL,                              /* startRemoteTx */
766                TERMIOS_IRQ_DRIVEN         /* mode */
767        };
768
769        static const rtems_termios_callbacks IntUartTaskCallbacks = {
770                IntUartInterruptOpen,  /* firstOpen */
771                IntUartInterruptClose, /* lastClose */
772                IntUartTaskRead,           /* pollRead */
773                IntUartInterruptWrite, /* write */
774                IntUartSetAttributes,  /* setAttributes */
775                NULL,                              /* stopRemoteTx */
776                NULL,                              /* startRemoteTx */
777                TERMIOS_TASK_DRIVEN        /* mode */
778        };
779
780        /* open the port depending on the minor device number */
781        if ( ( minor >= 0 ) && ( minor < MAX_UART_INFO ) )
782        {
783                info = &IntUartInfo[minor];
784                switch ( info->iomode )
785                {
786                        case TERMIOS_POLLED:
787                                status = rtems_termios_open(major, minor, arg, &IntUartPollCallbacks);
788                                break;
789                        case TERMIOS_IRQ_DRIVEN:
790                                status = rtems_termios_open(major, minor, arg, &IntUartIntrCallbacks);
791                                info->ttyp = args->iop->data1;
792                                break;
793                        case TERMIOS_TASK_DRIVEN:
794                                status = rtems_termios_open(major, minor, arg, &IntUartTaskCallbacks);
795                                info->ttyp = args->iop->data1;
796                                break;
797                }
798        }
799
800        return( status );
801}
802
803/***************************************************************************
804   Function : console_close
805
806   Description : This closes the device via termios
807 ***************************************************************************/
808rtems_device_driver console_close(
809        rtems_device_major_number major,
810        rtems_device_minor_number minor,
811        void   * arg)
812{
813    return(rtems_termios_close (arg));
814}
815
816/***************************************************************************
817   Function : console_read
818
819   Description : Read from the device via termios
820 ***************************************************************************/
821rtems_device_driver console_read(
822        rtems_device_major_number major,
823        rtems_device_minor_number minor,
824        void  * arg)
825{
826    return(rtems_termios_read (arg));
827}
828
829/***************************************************************************
830   Function : console_write
831
832   Description : Write to the device via termios
833 ***************************************************************************/
834rtems_device_driver console_write(
835        rtems_device_major_number major,
836        rtems_device_minor_number minor,
837        void  * arg)
838{
839    return(rtems_termios_write (arg));
840}
841
842/***************************************************************************
843   Function : console_ioctl
844
845   Description : Pass the IOCtl call to termios
846 ***************************************************************************/
847rtems_device_driver console_control(
848        rtems_device_major_number major,
849        rtems_device_minor_number minor,
850        void  * arg)
851{
852    return( rtems_termios_ioctl (arg) );
853}
854
855
856int DEBUG_OUTCHAR(int c)
857{
858    if(c == '\n')
859        DEBUG_OUTCHAR('\r');
860    _BSP_null_char(c);
861    return c;
862}
863void DEBUG_OUTSTR(const char *msg)
864{
865    while (*msg)
866        DEBUG_OUTCHAR(*msg++);
867}
868void DEBUG_OUTNUM(int i)
869{
870    int n;
871    static const char map[] = "0123456789ABCDEF";
872    DEBUG_OUTCHAR(' ');
873    for (n = 28 ; n >= 0 ; n -= 4)
874        DEBUG_OUTCHAR(map[(i >> n) & 0xF]);
875}
876
Note: See TracBrowser for help on using the repository browser.