source: rtems/c/src/lib/libbsp/powerpc/mvme2307/console/console.c @ 19ca797

4.104.114.84.95
Last change on this file since 19ca797 was 19ca797, checked in by Joel Sherrill <joel.sherrill@…>, on 10/04/99 at 20:41:28

Motorola MVME2307 BSP submitted by Jay Kulpinski <jskulpin@…>.
No modifications made.

  • Property mode set to 100644
File size: 11.2 KB
RevLine 
[19ca797]1/*
2 *  This file contains the hardware specific portions of the TTY driver
3 *  for the serial port on the MVME230x.
4 *
5 *  COPYRIGHT (c) 1989-1997.
6 *  On-Line Applications Research Corporation (OAR).
7 *  Copyright assigned to U.S. Government, 1994.
8 *
9 *  The license and distribution terms for this file may be
10 *  found in the file LICENSE in this distribution or at
11 *  http://www.OARcorp.com/rtems/license.html.
12 *
13 *  $Id$
14 */
15
16#include <termios.h>
17#include <bsp.h>
18#include <rtems/libio.h>
19#include <stdlib.h>
20
21/* PC16550D register definitions */
22#define UART_BASE_ADDR ((char *) IO_TO_LOCAL(0x03f8))
23
24#define RBR 0
25#define THR 0
26#define DLL 0
27#define DLM 1
28
29#define LCR 3
30#   define FIVE_BITS     0x2
31#   define SIX_BITS      0x2
32#   define SEVEN_BITS    0x2
33#   define EIGHT_BITS    0x3
34#   define ONE_STOP_BIT  0x0
35#   define TWO_STOP_BITS 0x4
36#   define NO_PARITY     0x00
37#   define ODD_PARITY    0x08
38#   define EVEN_PARITY   0x18
39#   define DLAB          0x80
40
41#define LSR 5
42#   define DR 0x01
43#   define OE 0x02
44#   define PE 0x04
45#   define FE 0x08
46#   define BI 0x10
47#   define THRE 0x20
48#   define TEMT 0x40
49#   define ERR_IN_FIFO 0x40
50
51#define FCR 2
52#   define ENABLE_FIFOS  0x01
53#   define RESET_RC_FIFO 0x02
54#   define RESET_TX_FIFO 0x04
55#   define FIFO_MODE_1   0x08
56#   define RX_TRIGGER_1  0x00
57#   define RX_TRIGGER_4  0x40
58#   define RX_TRIGGER_8  0x80
59#   define RX_TRIGGER_14 0xC0
60
61#define IIR 2
62#   define NO_INTS_PENDING 0x01
63#   define RX_ERROR        0x06
64#   define RX_DATA_READY   0x04
65#   define TX_NOT_FULL     0x02
66#   define MODEM_STATUS    0x00
67#   define INT_ID_MASK     0x06
68
69#define IER 1
70#   define ENA_RX_READY_INT     0x1
71#   define ENA_TX_EMPTY_INT     0x2
72#   define ENA_RX_ERROR_INT     0x4
73#   define ENA_MODEM_STATUS_INT 0x8
74
75#define MSR 6
76#   define DELTA_CTS   0x01
77#   define DELTA_DSR   0x02
78#   define END_OF_RING 0x04
79#   define DELTA_DCD   0x08
80#   define CTS         0x10
81#   define DSR         0x20
82#   define RING        0x40
83#   define DCD         0x80
84
85#define MCR 4
86#   define DTR      0x01
87#   define RTS      0x02
88#   define OUT1     0x04
89#   define OUT2     0x08
90#   define LOOPBACK 0x10
91
92#define SCR 7
93
94int use_polled_io = CONSOLE_USE_POLLED;
95void *tty_ptr_for_irq;
96
97/*
98 * Hardware-dependent portion of tcsetattr().
99 */
100static int
101setAttributes (int minor, const struct termios *t)
102{
103        int divisor;
104    volatile char *uart = UART_BASE_ADDR;
105    char lcr_image = 0;
106
107    /* set character size */
108    switch (t->c_cflag & CSIZE) {
109        case CS5:   lcr_image = FIVE_BITS;   break;
110        case CS6:   lcr_image = SIX_BITS;    break;
111        case CS7:   lcr_image = SEVEN_BITS;  break;
112        case CS8:   lcr_image = EIGHT_BITS;  break;
113    }
114
115    /* set number of stop bits */
116    if (t->c_cflag & CSTOPB) {
117        lcr_image |= TWO_STOP_BITS;
118    } else {
119        lcr_image |= ONE_STOP_BIT;
120    }
121
122    /* set parity */
123    if ((t->c_cflag & PARENB) == 0) {
124        lcr_image |= NO_PARITY;
125    } else if (t->c_cflag & PARODD) {
126        lcr_image |= ODD_PARITY;
127    } else {
128        lcr_image |= EVEN_PARITY;
129    }
130
131    /* set the baud rate */
132        switch (t->c_cflag & CBAUD) {
133        default:            divisor = -1;       break;
134        case B50:           divisor = 2304;     break;
135        case B75:           divisor = 1536;     break;
136        case B110:          divisor = 1047;     break;
137        case B134:          divisor = 857;      break;
138        case B150:          divisor = 768;      break;
139        case B200:          divisor = 576;      break;
140        case B300:          divisor = 384;      break;
141        case B600:          divisor = 192;      break;
142        case B1200:         divisor = 96;       break;
143        case B1800:         divisor = 64;       break;
144        case B2400:         divisor = 48;       break;
145        case B4800:         divisor = 24;       break;
146        case B9600:         divisor = 12;       break;
147        case B19200:    divisor = 6;    break;
148        case B38400:    divisor = 3;    break;
149        case B57600:    divisor = 2;    break;
150        case B115200:   divisor = -1;   break;
151        case B230400:   divisor = -1;   break;
152        case B460800:   divisor = -1;   break;
153        }
154    if (divisor > 0) {
155                uart[LCR] = (lcr_image |= DLAB);
156        uart[DLM] = divisor >> 8;
157        uart[DLL] = divisor;
158        lcr_image &= ~DLAB;
159    }
160
161    /* activate the new configuration */
162    uart[LCR] = lcr_image;
163        return 0;
164}
165
166/*
167 * Interrupt handler
168 */
169static rtems_isr consoleInterruptHandler (rtems_vector_number v)
170{
171    volatile char *uart = UART_BASE_ADDR;
172    volatile char ignore;
173    char buffer[16], iir_image;
174    int len;
175
176    while (((iir_image = uart[IIR]) & NO_INTS_PENDING) == 0) {
177        switch (iir_image & INT_ID_MASK) {
178            case RX_ERROR:
179                /*
180                 *  read the line status register to clear condition.
181                 *  nothing done with the information at this point.
182                 */
183                ignore = uart[LSR];
184                break;
185            case RX_DATA_READY:
186                /*
187                 *  empty the receive fifo and transfer bytes to termios layer
188                 */
189                len = 0;
190                do {
191                    buffer[len++] = uart[RBR];
192                } while (len < sizeof(buffer) && (uart[LSR] & DR));
193                rtems_termios_enqueue_raw_characters(tty_ptr_for_irq,
194                                                     buffer, len);
195                break;
196            case TX_NOT_FULL:
197                /*
198                 *  notify termios layer that characters have been sent
199                 */
200                len = uart[SCR];
201                /* we'll get one interrupt when we start - ignore it */
202                if (len) {
203                    rtems_termios_dequeue_characters(tty_ptr_for_irq, len);
204                }
205                break;
206            case MODEM_STATUS:
207                /*
208                 *  read the modem status register to clear condition.
209                 *  nothing done with the information at this point.
210                 */
211                ignore = uart[MSR];
212                break;
213        }
214    }
215}
216
217/*
218 *  console_inbyte_nonblocking
219 *
220 *  This routine polls for a character.
221 */
222
223int console_inbyte_nonblocking(
224  int port
225)
226{
227    volatile char *uart = UART_BASE_ADDR;
228
229    if (uart[LSR] & DR) {
230        return uart[RBR];
231    } else {
232        return -1;
233    }
234}
235
236
237/*
238 *  Console Termios Support Entry Points
239 *
240 */
241
242int console_write_polled (
243    int minor,
244    const char *buf,
245    int len
246)
247{
248    int nwrite = 0;
249    volatile char *uart = UART_BASE_ADDR;
250
251    while (nwrite < len) {
252        /* wait as long as needed for transmit buffer to empty */
253        while ((uart[LSR] & THRE) == 0) ;
254        uart[THR] = *buf++;
255        nwrite++;
256    }
257
258    /* return value seems to be ignored by termios layer, we'll return count */
259    return nwrite;
260}
261
262int console_write_interrupts (
263    int minor,
264    const char *buf,
265    int len
266)
267{
268    const int FIFO_depth = 16;
269    int nwrite;
270    volatile char *uart = UART_BASE_ADDR;
271
272    /* write up to len characters, stopping if FIFO fills */
273    for (nwrite = 0; nwrite < len && nwrite < FIFO_depth; nwrite++) {
274        uart[THR] = *buf++;
275    }
276
277    /* save count of bytes sent so interrupt can report it to termios layer */
278    uart[SCR] = nwrite;
279
280    /* return value seems to be ignored by termios layer, we'll return count */
281    return nwrite;
282}
283
284/*
285 *  Console Device Driver Entry Points
286 *
287 */
288 
289/*
290 * Initialize and register the device
291 */
292rtems_device_driver console_initialize(
293    rtems_device_major_number  major,
294    rtems_device_minor_number  minor,
295    void                      *arg
296)
297{
298    rtems_status_code status;
299    volatile char *uart = UART_BASE_ADDR;
300
301    rtems_termios_initialize();
302
303    /*
304    *  Register Device Names
305    */
306
307    status = rtems_io_register_name( "/dev/console", major, 0 );
308    if (status != RTEMS_SUCCESSFUL) {
309        rtems_fatal_error_occurred(status);
310    }
311    /* default mode:  9600 bps, 8 bits, 1 stop, no parity */
312#   define DEFAULT_MODE (EIGHT_BITS | ONE_STOP_BIT | NO_PARITY)
313    uart[LCR] = DEFAULT_MODE | DLAB;
314    uart[DLM] = 0;
315    uart[DLL] = 12;
316    uart[LCR] = DEFAULT_MODE;
317   
318    /* enable the receive and transmit FIFOs */
319    uart[FCR] = ENABLE_FIFOS | RESET_RC_FIFO | RESET_TX_FIFO | RX_TRIGGER_1;
320   
321    /* set modem control lines */
322    uart[MCR] = DTR | RTS;
323
324    /* zero the scratch register - this will hold a count of tx characters */
325    uart[SCR] = 0;
326   
327    /* initialize interrupts */
328    if (!use_polled_io) {
329        rtems_isr_entry old_handler;
330        rtems_status_code sc;
331
332        sc = bsp_interrupt_catch(consoleInterruptHandler, IRQ_UART,
333                                 &old_handler);
334        sc = bsp_interrupt_enable(IRQ_UART, PRIORITY_ISA_INT);
335        uart[IER] = ENA_RX_READY_INT | ENA_TX_EMPTY_INT;
336    } else {
337        uart[IER] = 0;
338    }
339    return RTEMS_SUCCESSFUL;
340}
341
342/*
343 * Open the device
344 */
345rtems_device_driver console_open(
346    rtems_device_major_number major,
347    rtems_device_minor_number minor,
348    void                    * arg
349)
350{
351    rtems_status_code sc;
352    static const rtems_termios_callbacks pollCallbacks = {
353        NULL,                        /* firstOpen */
354        NULL,                        /* lastClose */
355        console_inbyte_nonblocking,  /* pollRead */
356        console_write_polled,        /* write */
357        setAttributes,               /* setAttributes */
358        NULL,                        /* stopRemoteTx */
359        NULL,                        /* startRemoteTx */
360        0                            /* outputUsesInterrupts */
361    };
362    static const rtems_termios_callbacks intrCallbacks = {
363        NULL,                        /* firstOpen */
364        NULL,                        /* lastClose */
365        NULL,                        /* pollRead */
366        console_write_interrupts,    /* write */
367        setAttributes,               /* setAttributes */
368        NULL,                        /* stopRemoteTx */
369        NULL,                        /* startRemoteTx */
370        1                            /* outputUsesInterrupts */
371    };
372
373
374    if ( minor > 1 )
375        return RTEMS_INVALID_NUMBER;
376
377    if (use_polled_io) {
378        sc = rtems_termios_open (major, minor, arg, &pollCallbacks );
379    } else {
380        sc = rtems_termios_open (major, minor, arg, &intrCallbacks );
381        tty_ptr_for_irq = ((rtems_libio_open_close_args_t *)arg)->iop->data1;
382    }
383    return RTEMS_SUCCESSFUL;
384}
385 
386/*
387 * Close the device
388 */
389rtems_device_driver console_close(
390      rtems_device_major_number major,
391      rtems_device_minor_number minor,
392      void                    * arg
393)
394{
395  return rtems_termios_close (arg);
396}
397 
398/*
399 * Read from the device
400 */
401rtems_device_driver console_read(
402    rtems_device_major_number major,
403    rtems_device_minor_number minor,
404    void                    * arg
405)
406{
407    return rtems_termios_read (arg);
408}
409 
410/*
411 * Write to the device
412 */
413rtems_device_driver console_write(
414    rtems_device_major_number major,
415    rtems_device_minor_number minor,
416    void                    * arg
417)
418{
419    return rtems_termios_write (arg);
420}
421 
422/*
423 * Handle ioctl request.
424 */
425rtems_device_driver console_control(
426    rtems_device_major_number major,
427    rtems_device_minor_number minor,
428    void                    * arg
429)
430{
431    return rtems_termios_ioctl (arg);
432}
433
434/*
435 * Reserve resources consumed by this driver
436 */
437void console_reserve_resources(
438    rtems_configuration_table *configuration
439)
440{
441    rtems_termios_reserve_resources( configuration, 1 );
442}
Note: See TracBrowser for help on using the repository browser.