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

4.115
Last change on this file since e18db9f was e18db9f, checked in by Sebastian Huber <sebastian.huber@…>, on 06/24/13 at 15:29:11

termios: Update due to API changes

Termios notifies now the driver about an inactive transmit with the
length argument set to zero.

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