source: rtems/c/src/lib/libbsp/sparc/erc32/console/erc32_console.c @ e455a12

4.104.115
Last change on this file since e455a12 was e455a12, checked in by Joel Sherrill <joel.sherrill@…>, on 05/07/10 at 12:13:23

2010-04-27 Tiemen Schut <T.Schut@…>

PR 1506/bsps

  • console/console.c: Removed.
  • console/erc32_console.c: New file. Use shared console driver. Make sure interrupt support works. PPPD confirmed on sis.
  • Makefile.am: Reflect changes above.
  • Property mode set to 100644
File size: 7.4 KB
Line 
1/**
2 * @file
3 *
4 * @brief Driver for serial ports on the ERC32.
5 */
6
7/*
8 * Copyright (c) 2010 Tiemen Schut <T.Schut@sron.nl>
9 *
10 * The license and distribution terms for this file may be
11 * found in the file LICENSE in this distribution or at
12 * http://www.rtems.com/license/LICENSE.
13 *
14 * $Id$
15 */
16
17#include <unistd.h>
18#include <termios.h>
19#include <stdlib.h>
20
21#include <rtems.h>
22#include <rtems/libio.h>
23#include <rtems/console.h>
24#include <rtems/termiostypes.h>
25
26#include <libchip/serial.h>
27#include <libchip/sersupp.h>
28
29#include <bsp.h>
30
31#define CONSOLE_BUF_SIZE (16)
32
33#define CONSOLE_UART_A_TRAP  ERC32_TRAP_TYPE(ERC32_INTERRUPT_UART_A_RX_TX)
34#define CONSOLE_UART_B_TRAP  ERC32_TRAP_TYPE(ERC32_INTERRUPT_UART_B_RX_TX)
35
36static uint8_t erc32_console_get_register(uint32_t addr, uint8_t i)
37{
38    volatile uint32_t *reg = (volatile uint32_t *)addr;
39    return (uint8_t) reg [i];
40}
41
42static void erc32_console_set_register(uint32_t addr, uint8_t i, uint8_t val)
43{
44    volatile uint32_t *reg = (volatile uint32_t *)addr;
45    reg [i] = val;
46}
47
48static int erc32_console_first_open(int major, int minor, void *arg);
49static ssize_t erc32_console_write_support_int(int minor, const char *buf, size_t len);
50static void erc32_console_initialize(int minor);
51
52rtems_device_minor_number Console_Port_Minor = 0;
53
54console_fns erc32_fns = {
55    libchip_serial_default_probe,           /* deviceProbe */
56    erc32_console_first_open,               /* deviceFirstOpen */
57    NULL,                                   /* deviceLastClose */
58    NULL,                                   /* deviceRead */
59    erc32_console_write_support_int,        /* deviceWrite */
60    erc32_console_initialize,               /* deviceInitialize */
61    NULL,                                   /* deviceWritePolled */
62    NULL,                                   /* deviceSetAttributes */
63    true                                    /* deviceOutputUsesInterrupts */
64};
65
66console_tbl Console_Port_Tbl [] = {
67    {
68      .sDeviceName = "/dev/console",
69      .deviceType = SERIAL_CUSTOM,
70      .pDeviceFns = &erc32_fns,
71      .deviceProbe = NULL,
72      .pDeviceFlow = NULL,
73      .ulMargin = 16,
74      .ulHysteresis = 8,
75      .pDeviceParams = (void *) 1,
76      .ulCtrlPort1 = 0,
77      .ulCtrlPort2 = 0,
78      .ulDataPort = 0,
79      .getRegister = erc32_console_get_register,
80      .setRegister = erc32_console_set_register,
81      .getData = NULL,
82      .setData = NULL,
83      .ulClock = 16,
84      .ulIntVector = ERC32_INTERRUPT_UART_A_RX_TX
85    },
86    {
87      .sDeviceName = "/dev/console_b",
88      .deviceType = SERIAL_CUSTOM,
89      .pDeviceFns = &erc32_fns,
90      .deviceProbe = NULL,
91      .pDeviceFlow = NULL,
92      .ulMargin = 16,
93      .ulHysteresis = 8,
94      .pDeviceParams = (void *) 1,
95      .ulCtrlPort1 = 0,
96      .ulCtrlPort2 = 0,
97      .ulDataPort = 0,
98      .getRegister = erc32_console_get_register,
99      .setRegister = erc32_console_set_register,
100      .getData = NULL,
101      .setData = NULL,
102      .ulClock = 16,
103      .ulIntVector = ERC32_INTERRUPT_UART_B_RX_TX
104    },
105};
106
107/* always exactly two uarts for erc32 */
108#define ERC32_UART_COUNT (2)
109
110unsigned long Console_Port_Count = ERC32_UART_COUNT;
111
112console_data Console_Port_Data [ERC32_UART_COUNT];
113
114static int erc32_console_first_open(int major, int minor, void *arg)
115{
116    /* Check minor number */
117    if (minor < 0 || minor > 1) {
118        return -1;
119    }
120   
121    rtems_libio_open_close_args_t *oca = arg;
122    struct rtems_termios_tty *tty = oca->iop->data1;
123    console_tbl *ct = &Console_Port_Tbl [minor];
124    console_data *cd = &Console_Port_Data [minor];
125   
126    cd->termios_data = tty;
127    rtems_termios_set_initial_baud(tty, (int32_t)ct->pDeviceParams);
128   
129    return 0;
130}
131
132static ssize_t erc32_console_write_support_int(int minor, const char *buf, size_t len)
133{
134    console_data *cd = &Console_Port_Data[minor];
135    int k = 0;
136
137    if (minor == 0) { /* uart a */
138        for (k = 0; k < len && (ERC32_MEC.UART_Status & ERC32_MEC_UART_STATUS_THEA); k ++) {
139            ERC32_MEC.UART_Channel_A = (unsigned char)buf[k];
140        }
141        ERC32_Force_interrupt(ERC32_INTERRUPT_UART_A_RX_TX);
142    } else { /* uart b */
143        for (k = 0; k < len && (ERC32_MEC.UART_Status & ERC32_MEC_UART_STATUS_THEB); k ++) {
144            ERC32_MEC.UART_Channel_B = (unsigned char)buf[k];
145        }
146        ERC32_Force_interrupt(ERC32_INTERRUPT_UART_B_RX_TX);
147    }
148   
149    if (len > 0) {
150        cd->pDeviceContext = (void *)k;
151        cd->bActive = true;
152    }
153   
154    return 0;
155}
156
157static void erc32_console_isr_a(
158    rtems_vector_number vector
159)
160{
161    console_data *cd = &Console_Port_Data[0];
162
163    /* check for error */
164    if (ERC32_MEC.UART_Status & ERC32_MEC_UART_STATUS_ERRA) {
165        ERC32_MEC.UART_Status = ERC32_MEC_UART_STATUS_CLRA;
166        ERC32_MEC.Control = ERC32_MEC.Control;
167    }
168
169    do {
170        int chars_to_dequeue = (int)cd->pDeviceContext;
171        int rv = 0;
172        int i = 0;
173        char buf[CONSOLE_BUF_SIZE];
174       
175        /* enqueue received chars */
176        while (i < CONSOLE_BUF_SIZE) {
177            if (ERC32_MEC.UART_Status & ERC32_MEC_UART_STATUS_DRA) {
178                buf[i] = ERC32_MEC.UART_Channel_A;
179                ++i;
180            } else {
181                break;
182            }
183        }
184        rtems_termios_enqueue_raw_characters(cd->termios_data, buf, i);
185
186        /* dequeue transmitted chars */
187        cd->pDeviceContext = 0;
188        rv = rtems_termios_dequeue_characters(cd->termios_data, chars_to_dequeue);
189        if (rv == 0 && !(ERC32_MEC.UART_Status & ERC32_MEC_UART_STATUS_DRA)) {
190            cd->bActive = false;
191            ERC32_Clear_interrupt (ERC32_INTERRUPT_UART_A_RX_TX);
192        }
193    } while (ERC32_Is_interrupt_pending (ERC32_INTERRUPT_UART_A_RX_TX));
194}
195
196static void erc32_console_isr_b(
197    rtems_vector_number vector
198)
199{
200    console_data *cd = &Console_Port_Data[1];
201
202    /* check for error */
203    if (ERC32_MEC.UART_Status & ERC32_MEC_UART_STATUS_ERRB) {
204        ERC32_MEC.UART_Status = ERC32_MEC_UART_STATUS_CLRB;
205        ERC32_MEC.Control = ERC32_MEC.Control;
206    }
207
208    do {
209        int chars_to_dequeue = (int)cd->pDeviceContext;
210        int rv = 0;
211        int i = 0;
212        char buf[CONSOLE_BUF_SIZE];
213       
214        /* enqueue received chars */
215        while (i < CONSOLE_BUF_SIZE) {
216            if (ERC32_MEC.UART_Status & ERC32_MEC_UART_STATUS_DRB) {
217                buf[i] = ERC32_MEC.UART_Channel_B;
218                ++i;
219            } else {
220                break;
221            }
222        }
223        rtems_termios_enqueue_raw_characters(cd->termios_data, buf, i);
224
225        /* dequeue transmitted chars */
226        cd->pDeviceContext = 0;
227        rv = rtems_termios_dequeue_characters(cd->termios_data, chars_to_dequeue);
228        if (rv == 0 && !(ERC32_MEC.UART_Status & ERC32_MEC_UART_STATUS_DRB)) {
229            cd->bActive = false;
230            ERC32_Clear_interrupt (ERC32_INTERRUPT_UART_B_RX_TX);
231        }
232    } while (ERC32_Is_interrupt_pending (ERC32_INTERRUPT_UART_B_RX_TX));
233}
234
235
236/*
237 *  Console Device Driver Entry Points
238 *
239 */
240
241static void erc32_console_initialize(
242    int minor
243)
244{
245    console_data *cd = &Console_Port_Data [minor];
246
247    cd->bActive = false;
248    cd->pDeviceContext = 0;
249
250   /*
251    * Initialize the Termios infrastructure.  If Termios has already
252    * been initialized by another device driver, then this call will
253    * have no effect.
254    */
255    rtems_termios_initialize();
256
257   /*
258    *  Initialize Hardware
259    */
260    set_vector(erc32_console_isr_a, CONSOLE_UART_A_TRAP, 1);
261    set_vector(erc32_console_isr_b, CONSOLE_UART_B_TRAP, 1);
262}
Note: See TracBrowser for help on using the repository browser.