source: rtems/c/src/lib/libbsp/m68k/genmcf548x/console/console.c @ 045821e

4.104.115
Last change on this file since 045821e was 045821e, checked in by Thomas Doerfler <Thomas.Doerfler@…>, on Oct 15, 2009 at 2:05:34 PM

add network support, various corrections

  • Property mode set to 100644
File size: 25.8 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            break;
490
491        case 1:
492            MCF548X_INTC_ICR34 =   MCF548X_INTC_ICRn_IL(PSC1_IRQ_LEVEL) |
493                               MCF548X_INTC_ICRn_IP(PSC1_IRQ_PRIORITY);
494            MCF548X_INTC_IMRH &= ~(MCF548X_INTC_IMRH_INT_MASK34);
495            break;
496
497        case 2:
498            MCF548X_INTC_ICR33 =   MCF548X_INTC_ICRn_IL(PSC2_IRQ_LEVEL) |
499                               MCF548X_INTC_ICRn_IP(PSC2_IRQ_PRIORITY);
500            MCF548X_INTC_IMRH &= ~(MCF548X_INTC_IMRH_INT_MASK33);
501            break;
502
503        case 3:
504            MCF548X_INTC_ICR32 =   MCF548X_INTC_ICRn_IL(PSC3_IRQ_LEVEL) |
505                               MCF548X_INTC_ICRn_IP(PSC3_IRQ_PRIORITY);
506            MCF548X_INTC_IMRH &= ~(MCF548X_INTC_IMRH_INT_MASK32);
507            break;
508        }
509                rtems_interrupt_enable(level);
510
511        } /* of chan loop */
512
513
514} /* IntUartInitialise */
515
516/***************************************************************************
517   Function : IntUartInterruptWrite
518
519   Description : This writes a single character to the appropriate uart
520   channel. This is either called during an interrupt or in the user's task
521   to initiate a transmit sequence. Calling this routine enables Tx
522   interrupts.
523 ***************************************************************************/
524static int
525IntUartInterruptWrite (int minor, const char *buf, int len)
526{
527        int level;
528
529        rtems_interrupt_disable(level);
530
531        /* write out character */
532        MCF548X_PSC_TB(minor) = *buf;
533
534        /* enable tx interrupt */
535        IntUartInfo[minor].imr |= MCF548X_PSC_IMR_TXRDY;
536        MCF548X_PSC_IMR(minor) = IntUartInfo[minor].imr;
537
538        rtems_interrupt_enable(level);
539        return 0;
540}
541
542/***************************************************************************
543   Function : IntUartInterruptOpen
544
545   Description : This enables interrupts when the tty is opened.
546 ***************************************************************************/
547static int
548IntUartInterruptOpen(int major, int minor, void *arg)
549{
550        struct IntUartInfoStruct   *info = &IntUartInfo[minor];
551
552        /* enable the uart */
553        MCF548X_PSC_CR(minor) = (MCF548X_PSC_CR_TX_ENABLED | MCF548X_PSC_CR_RX_ENABLED);
554
555        /* check to see if interrupts need to be enabled */
556        if ( info->iomode != TERMIOS_POLLED )
557        {
558                /* enable rx interrupts */
559                info->imr |= MCF548X_PSC_IMR_RXRDY_FU;
560                MCF548X_PSC_IMR(minor) = info->imr;
561        }
562
563        /* check to see if doing hardware flow control */
564        if ( info->hwflow )
565        {
566                /* assert the RTS line */
567                MCF548X_PSC_OPSET(minor) = MCF548X_PSC_OPSET_RTS;
568        }
569
570        return 0;
571}
572
573
574/***************************************************************************
575   Function : IntUartInterruptClose
576
577   Description : This disables interrupts when the tty is closed.
578 ***************************************************************************/
579static int
580IntUartInterruptClose(int major, int minor, void *arg)
581{
582        struct IntUartInfoStruct   *info = &IntUartInfo[minor];
583
584        /* disable the interrupts and the uart */
585        MCF548X_PSC_IMR(minor) = 0;
586        MCF548X_PSC_CR(minor) = (MCF548X_PSC_CR_TX_ENABLED | MCF548X_PSC_CR_RX_ENABLED);
587
588        /* reset values */
589        info->ttyp     = NULL;
590        info->imr       = 0;
591        info->rx_in    = 0;
592        info->rx_out   = 0;
593
594        return 0;
595}
596
597/***************************************************************************
598   Function : IntUartTaskRead
599
600   Description : This reads all available characters from the internal uart
601   and places them into the termios buffer.  The rx interrupts will be
602   re-enabled after all data has been read.
603 ***************************************************************************/
604static int
605IntUartTaskRead(int minor)
606{
607        char                        buffer[RX_BUFFER_SIZE];
608        int                         count;
609        int                         rx_in;
610        int                         index = 0;
611        struct IntUartInfoStruct   *info  = &IntUartInfo[minor];
612
613        /* determine number of values to copy out */
614        rx_in = info->rx_in;
615        if ( info->rx_out <= rx_in )
616        {
617                count = rx_in - info->rx_out;
618        }
619        else
620        {
621                count = (RX_BUFFER_SIZE - info->rx_out) + rx_in;
622        }
623
624        /* copy data into local buffer from rx buffer */
625        while ( ( index < count ) && ( index < RX_BUFFER_SIZE ) )
626        {
627                /* copy data byte */
628                buffer[index] = info->rx_buffer[info->rx_out];
629                index++;
630
631                /* increment rx buffer values */
632                info->rx_out++;
633                if ( info->rx_out >= RX_BUFFER_SIZE )
634                {
635                        info->rx_out = 0;
636                }
637        }
638
639        /* check to see if buffer is not empty */
640        if ( count > 0 )
641        {
642                /* set characters into termios buffer  */
643                rtems_termios_enqueue_raw_characters(info->ttyp, buffer, count);
644        }
645
646        return EOF;
647}
648
649
650/***************************************************************************
651   Function : IntUartPollRead
652
653   Description : This reads a character from the internal uart. It returns
654   to the caller without blocking if not character is waiting.
655 ***************************************************************************/
656static int
657IntUartPollRead (int minor)
658{
659if (!((MCF548X_PSC_SR(minor) & MCF548X_PSC_SR_RXRDY)))
660                return(-1);
661
662        return *((uint8_t *)&MCF548X_PSC_RB(minor));
663}
664
665
666/***************************************************************************
667   Function : IntUartPollWrite
668
669   Description : This writes out each character in the buffer to the
670   appropriate internal uart channel waiting till each one is sucessfully
671   transmitted.
672 ***************************************************************************/
673static int
674IntUartPollWrite (int minor, const char *buf, int len)
675{
676/* loop over buffer */
677        while ( len-- )
678        {
679                /* block until we can transmit */
680                while (!((MCF548X_PSC_SR(minor) & MCF548X_PSC_SR_TXRDY)))
681                        continue;
682                /* transmit data byte */
683                *((uint8_t *)&MCF548X_PSC_TB(minor)) = *buf++;
684        }
685        return 0;
686}
687
688/***************************************************************************
689   Function : console_initialize
690
691   Description : This initialises termios, both sets of uart hardware before
692   registering /dev/tty devices for each channel and the system /dev/console.
693 ***************************************************************************/
694rtems_device_driver console_initialize(
695        rtems_device_major_number  major,
696        rtems_device_minor_number  minor,
697        void  *arg )
698{
699        rtems_status_code status;
700
701
702        /* Set up TERMIOS */
703        rtems_termios_initialize ();
704
705        /* set io modes for the different channels and initialize device */
706    IntUartInfo[minor].iomode = TERMIOS_IRQ_DRIVEN; //TERMIOS_POLLED;
707        IntUartInitialize();
708
709        /* Register the console port */
710        status = rtems_io_register_name ("/dev/console", major, CONSOLE_PORT);
711        if ( status != RTEMS_SUCCESSFUL )
712        {
713                rtems_fatal_error_occurred (status);
714        }
715
716        /* Register the other port */
717        if ( CONSOLE_PORT != 0 )
718        {
719                status = rtems_io_register_name ("/dev/tty00", major, 0);
720                if ( status != RTEMS_SUCCESSFUL )
721                {
722                        rtems_fatal_error_occurred (status);
723                }
724        }
725        if ( CONSOLE_PORT != 1 )
726        {
727                status = rtems_io_register_name ("/dev/tty01", major, 1);
728                if ( status != RTEMS_SUCCESSFUL )
729                {
730                        rtems_fatal_error_occurred (status);
731                }
732        }
733
734        return(RTEMS_SUCCESSFUL);
735}
736
737/***************************************************************************
738   Function : console_open
739
740   Description : This actually opens the device depending on the minor
741   number set during initialisation. The device specific access routines are
742   passed to termios when the devices is opened depending on whether it is
743   polled or not.
744 ***************************************************************************/
745rtems_device_driver console_open(
746        rtems_device_major_number major,
747        rtems_device_minor_number minor,
748        void  * arg)
749{
750    rtems_status_code                status = RTEMS_INVALID_NUMBER;
751        rtems_libio_open_close_args_t   *args   = (rtems_libio_open_close_args_t *)arg;
752        struct IntUartInfoStruct        *info;
753
754        static const rtems_termios_callbacks IntUartPollCallbacks = {
755                NULL,                             /* firstOpen */
756                NULL,                             /* lastClose */
757                IntUartPollRead,          /* pollRead */
758                IntUartPollWrite,         /* write */
759                IntUartSetAttributes, /* setAttributes */
760                NULL,                             /* stopRemoteTx */
761                NULL,                             /* startRemoteTx */
762                TERMIOS_POLLED            /* mode */
763        };
764        static const rtems_termios_callbacks IntUartIntrCallbacks = {
765                IntUartInterruptOpen,  /* firstOpen */
766                IntUartInterruptClose, /* lastClose */
767                NULL,                              /* pollRead */
768                IntUartInterruptWrite, /* write */
769                IntUartSetAttributes,  /* setAttributes */
770                NULL,                              /* stopRemoteTx */
771                NULL,                              /* startRemoteTx */
772                TERMIOS_IRQ_DRIVEN         /* mode */
773        };
774
775        static const rtems_termios_callbacks IntUartTaskCallbacks = {
776                IntUartInterruptOpen,  /* firstOpen */
777                IntUartInterruptClose, /* lastClose */
778                IntUartTaskRead,           /* pollRead */
779                IntUartInterruptWrite, /* write */
780                IntUartSetAttributes,  /* setAttributes */
781                NULL,                              /* stopRemoteTx */
782                NULL,                              /* startRemoteTx */
783                TERMIOS_TASK_DRIVEN        /* mode */
784        };
785
786        /* open the port depending on the minor device number */
787        if ( ( minor >= 0 ) && ( minor < MAX_UART_INFO ) )
788        {
789                info = &IntUartInfo[minor];
790                switch ( info->iomode )
791                {
792                        case TERMIOS_POLLED:
793                                status = rtems_termios_open(major, minor, arg, &IntUartPollCallbacks);
794                                break;
795                        case TERMIOS_IRQ_DRIVEN:
796                                status = rtems_termios_open(major, minor, arg, &IntUartIntrCallbacks);
797                                info->ttyp = args->iop->data1;
798                                break;
799                        case TERMIOS_TASK_DRIVEN:
800                                status = rtems_termios_open(major, minor, arg, &IntUartTaskCallbacks);
801                                info->ttyp = args->iop->data1;
802                                break;
803                }
804        }
805
806        return( status );
807}
808
809/***************************************************************************
810   Function : console_close
811
812   Description : This closes the device via termios
813 ***************************************************************************/
814rtems_device_driver console_close(
815        rtems_device_major_number major,
816        rtems_device_minor_number minor,
817        void   * arg)
818{
819    return(rtems_termios_close (arg));
820}
821
822/***************************************************************************
823   Function : console_read
824
825   Description : Read from the device via termios
826 ***************************************************************************/
827rtems_device_driver console_read(
828        rtems_device_major_number major,
829        rtems_device_minor_number minor,
830        void  * arg)
831{
832    return(rtems_termios_read (arg));
833}
834
835/***************************************************************************
836   Function : console_write
837
838   Description : Write to the device via termios
839 ***************************************************************************/
840rtems_device_driver console_write(
841        rtems_device_major_number major,
842        rtems_device_minor_number minor,
843        void  * arg)
844{
845    return(rtems_termios_write (arg));
846}
847
848/***************************************************************************
849   Function : console_ioctl
850
851   Description : Pass the IOCtl call to termios
852 ***************************************************************************/
853rtems_device_driver console_control(
854        rtems_device_major_number major,
855        rtems_device_minor_number minor,
856        void  * arg)
857{
858    return( rtems_termios_ioctl (arg) );
859}
860
861
862int DEBUG_OUTCHAR(int c)
863{
864    if(c == '\n')
865        DEBUG_OUTCHAR('\r');
866    _BSP_null_char(c);
867    return c;
868}
869void DEBUG_OUTSTR(const char *msg)
870{
871    while (*msg)
872        DEBUG_OUTCHAR(*msg++);
873}
874void DEBUG_OUTNUM(int i)
875{
876    int n;
877    static const char map[] = "0123456789ABCDEF";
878    DEBUG_OUTCHAR(' ');
879    for (n = 28 ; n >= 0 ; n -= 4)
880        DEBUG_OUTCHAR(map[(i >> n) & 0xF]);
881}
882
Note: See TracBrowser for help on using the repository browser.