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

5
Last change on this file since befae6ab was befae6ab, checked in by Sebastian Huber <sebastian.huber@…>, on 03/07/18 at 09:32:42

bsp/genmcf548x: Fix printk() support

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