1 |
30 |
unneback |
/*
|
2 |
|
|
* 68340/68349 console serial I/O.
|
3 |
|
|
*
|
4 |
|
|
* Author:
|
5 |
|
|
* Geoffroy Montel
|
6 |
|
|
* France Telecom - CNET/DSM/TAM/CAT
|
7 |
|
|
* 4, rue du Clos Courtel
|
8 |
|
|
* 35512 CESSON-SEVIGNE
|
9 |
|
|
* FRANCE
|
10 |
|
|
*
|
11 |
|
|
* e-mail: g_montel@yahoo.com
|
12 |
|
|
*
|
13 |
|
|
* COPYRIGHT (c) 1989-1999.
|
14 |
|
|
* On-Line Applications Research Corporation (OAR).
|
15 |
|
|
*
|
16 |
|
|
* The license and distribution terms for this file may be
|
17 |
|
|
* found in the file LICENSE in this distribution or at
|
18 |
|
|
*
|
19 |
|
|
* http://www.OARcorp.com/rtems/license.html.
|
20 |
|
|
*
|
21 |
|
|
* $Id: console.c,v 1.2 2001-09-27 12:00:07 chris Exp $
|
22 |
|
|
*/
|
23 |
|
|
|
24 |
|
|
#include <termios.h>
|
25 |
|
|
#include <bsp.h>
|
26 |
|
|
#include <rtems/libio.h>
|
27 |
|
|
#include <m68340.h>
|
28 |
|
|
#include <m340uart.h>
|
29 |
|
|
#include <m340timer.h>
|
30 |
|
|
|
31 |
|
|
#include <stdarg.h>
|
32 |
|
|
#include <stdio.h>
|
33 |
|
|
#include <stdlib.h>
|
34 |
|
|
|
35 |
|
|
#define CONSOLE_VECTOR 121
|
36 |
|
|
#define CONSOLE_IRQ_LEVEL 3
|
37 |
|
|
#define CONSOLE_INTERRUPT_ARBITRATION 2
|
38 |
|
|
|
39 |
|
|
static void *ttypA; /* to remember which tty has been opened on channel A
|
40 |
|
|
used when interrupts are enabled */
|
41 |
|
|
|
42 |
|
|
static void *ttypB; /* to remember which tty has been opened on channel B
|
43 |
|
|
used when interrupts are enabled */
|
44 |
|
|
|
45 |
|
|
unsigned char DUIER_mirror = 0 ; /* reflects the state of IER register, which is Write Only */
|
46 |
|
|
unsigned char Error_Status_A = 0; /* error status on Channel A */
|
47 |
|
|
unsigned char Error_Status_B = 0; /* error status on Channel A */
|
48 |
|
|
|
49 |
|
|
/*
|
50 |
|
|
* Device-specific routines
|
51 |
|
|
*/
|
52 |
|
|
|
53 |
|
|
#define USE_INTERRUPTS_A (m340_uart_config[UART_CHANNEL_A].mode==UART_INTERRUPTS)
|
54 |
|
|
#define USE_INTERRUPTS_B (m340_uart_config[UART_CHANNEL_B].mode==UART_INTERRUPTS)
|
55 |
|
|
#define CHANNEL_ENABLED_A m340_uart_config[UART_CHANNEL_A].enable
|
56 |
|
|
#define CHANNEL_ENABLED_B m340_uart_config[UART_CHANNEL_B].enable
|
57 |
|
|
|
58 |
|
|
#define set_DUIER(a) DUIER_mirror |= (a); DUIER = DUIER_mirror
|
59 |
|
|
#define unset_DUIER(a) DUIER_mirror &= ~(a); DUIER = DUIER_mirror
|
60 |
|
|
|
61 |
|
|
#define Enable_Interrupts_Tx_A if (USE_INTERRUPTS_A) set_DUIER(m340_TxRDYA)
|
62 |
|
|
#define Disable_Interrupts_Tx_A if (USE_INTERRUPTS_A) unset_DUIER(m340_TxRDYA)
|
63 |
|
|
|
64 |
|
|
#define Enable_Interrupts_Tx_B if (USE_INTERRUPTS_B) set_DUIER(m340_TxRDYB)
|
65 |
|
|
#define Disable_Interrupts_Tx_B if (USE_INTERRUPTS_B) unset_DUIER(m340_TxRDYB)
|
66 |
|
|
|
67 |
|
|
/******************************************************
|
68 |
|
|
Name: InterruptHandler
|
69 |
|
|
Input parameters: vector number
|
70 |
|
|
Output parameters: -
|
71 |
|
|
Description: UART ISR Routine, called by _RTEMS_ISR
|
72 |
|
|
*****************************************************/
|
73 |
|
|
rtems_isr
|
74 |
|
|
InterruptHandler (rtems_vector_number v)
|
75 |
|
|
{
|
76 |
|
|
char ch;
|
77 |
|
|
|
78 |
|
|
/*****************************************************************************
|
79 |
|
|
** CHANNEL A **
|
80 |
|
|
*****************************************************************************/
|
81 |
|
|
|
82 |
|
|
/* check Received Break*/
|
83 |
|
|
if (DUSRA & m340_RB) {
|
84 |
|
|
Error_Status_A |= m340_RB;
|
85 |
|
|
/* reset error status */
|
86 |
|
|
DUCRA = m340_Reset_Error_Status;
|
87 |
|
|
}
|
88 |
|
|
|
89 |
|
|
/* buffer received ? */
|
90 |
|
|
if (DUSRA & m340_Rx_RDY) {
|
91 |
|
|
do {
|
92 |
|
|
/* error encountered? */
|
93 |
|
|
if (DUSRA & (m340_OE | m340_PE | m340_FE | m340_RB)) {
|
94 |
|
|
Error_Status_A |= DUSRA;
|
95 |
|
|
/* reset error status */
|
96 |
|
|
DUCRA = m340_Reset_Error_Status;
|
97 |
|
|
/* all the characters in the queue may not be good */
|
98 |
|
|
while (DUSRA & m340_Rx_RDY)
|
99 |
|
|
/* push them in a trash */
|
100 |
|
|
ch = DURBA;
|
101 |
|
|
}
|
102 |
|
|
else {
|
103 |
|
|
/* this is necessary, otherwise it blocks when FIFO is full */
|
104 |
|
|
ch = DURBA;
|
105 |
|
|
rtems_termios_enqueue_raw_characters(ttypA,&ch,1);
|
106 |
|
|
}
|
107 |
|
|
} while (DUSRA & m340_Rx_RDY);
|
108 |
|
|
Restart_Fifo_Full_A_Timer(); /* only if necessary (pointer to a fake function if
|
109 |
|
|
not in FIFO full mode) */
|
110 |
|
|
}
|
111 |
|
|
|
112 |
|
|
else /* if no character has been received */
|
113 |
|
|
Restart_Check_A_Timer(); /* same remark */
|
114 |
|
|
|
115 |
|
|
/* ready to accept a character ? */
|
116 |
|
|
if (DUISR & DUIER_mirror & m340_TxRDYA) {
|
117 |
|
|
Disable_Interrupts_Tx_A;
|
118 |
|
|
/* one character has been transmitted */
|
119 |
|
|
rtems_termios_dequeue_characters(ttypA,1);
|
120 |
|
|
}
|
121 |
|
|
|
122 |
|
|
/*****************************************************************************
|
123 |
|
|
** CHANNEL B **
|
124 |
|
|
*****************************************************************************/
|
125 |
|
|
|
126 |
|
|
/* check Received Break*/
|
127 |
|
|
if (DUSRB & m340_RB) {
|
128 |
|
|
Error_Status_B |= m340_RB;
|
129 |
|
|
/* reset error status */
|
130 |
|
|
DUCRB = m340_Reset_Error_Status;
|
131 |
|
|
}
|
132 |
|
|
|
133 |
|
|
/* buffer received ? */
|
134 |
|
|
if (DUSRB & m340_Rx_RDY) {
|
135 |
|
|
do {
|
136 |
|
|
if (DUSRB & (m340_OE | m340_PE | m340_FE | m340_RB)) {
|
137 |
|
|
Error_Status_B |= DUSRB;
|
138 |
|
|
/* reset error status */
|
139 |
|
|
DUCRB = m340_Reset_Error_Status;
|
140 |
|
|
/* all the characters in the queue may not be good */
|
141 |
|
|
while (DUSRB & m340_Rx_RDY)
|
142 |
|
|
/* push them in a trash */
|
143 |
|
|
ch = DURBB;
|
144 |
|
|
}
|
145 |
|
|
else {
|
146 |
|
|
ch = DURBB;
|
147 |
|
|
rtems_termios_enqueue_raw_characters(ttypB,&ch,1);
|
148 |
|
|
}
|
149 |
|
|
|
150 |
|
|
} while (DUSRB & m340_Rx_RDY);
|
151 |
|
|
Restart_Fifo_Full_B_Timer();
|
152 |
|
|
}
|
153 |
|
|
else /* if no character has been received */
|
154 |
|
|
Restart_Check_B_Timer();
|
155 |
|
|
|
156 |
|
|
/* ready to accept a character ? */
|
157 |
|
|
if (DUISR & DUIER_mirror & m340_TxRDYB) {
|
158 |
|
|
Disable_Interrupts_Tx_B;
|
159 |
|
|
/* one character has been transmitted */
|
160 |
|
|
rtems_termios_dequeue_characters(ttypB,1);
|
161 |
|
|
}
|
162 |
|
|
}
|
163 |
|
|
|
164 |
|
|
/******************************************************
|
165 |
|
|
Name: InterruptWrite
|
166 |
|
|
Input parameters: minor = channel, pointer to buffer,
|
167 |
|
|
and length of buffer to transmit
|
168 |
|
|
Output parameters: -
|
169 |
|
|
Description: write the first character of buf only
|
170 |
|
|
may be called by either console_write
|
171 |
|
|
or rtems_termios_enqueue_raw_characters
|
172 |
|
|
*****************************************************/
|
173 |
|
|
static int
|
174 |
|
|
InterruptWrite (int minor, const char *buf, int len)
|
175 |
|
|
{
|
176 |
|
|
if (minor==UART_CHANNEL_A) {
|
177 |
|
|
if (len>0) (char)DUTBA=*buf;
|
178 |
|
|
Enable_Interrupts_Tx_A;
|
179 |
|
|
}
|
180 |
|
|
else if (minor==UART_CHANNEL_B) {
|
181 |
|
|
if (len>0) (char)DUTBB=*buf;
|
182 |
|
|
Enable_Interrupts_Tx_B;
|
183 |
|
|
}
|
184 |
|
|
return 0;
|
185 |
|
|
}
|
186 |
|
|
|
187 |
|
|
/******************************************************
|
188 |
|
|
Name: dbug_out_char
|
189 |
|
|
Input parameters: channel, character to emit
|
190 |
|
|
Output parameters: -
|
191 |
|
|
Description: wait for the UART to be ready to emit
|
192 |
|
|
a character and send it
|
193 |
|
|
*****************************************************/
|
194 |
|
|
void dbug_out_char( int minor, int ch )
|
195 |
|
|
{
|
196 |
|
|
if (minor==UART_CHANNEL_A) {
|
197 |
|
|
while (!(DUSRA & m340_Tx_RDY)) continue;
|
198 |
|
|
DUTBA=ch;
|
199 |
|
|
}
|
200 |
|
|
else if (minor==UART_CHANNEL_B) {
|
201 |
|
|
while (!(DUSRB & m340_Tx_RDY)) continue;
|
202 |
|
|
DUTBB=ch;
|
203 |
|
|
}
|
204 |
|
|
}
|
205 |
|
|
|
206 |
|
|
/******************************************************
|
207 |
|
|
Name: dbug_in_char
|
208 |
|
|
Input parameters: -
|
209 |
|
|
Output parameters: received character
|
210 |
|
|
Description: return the character in the UART
|
211 |
|
|
*****************************************************/
|
212 |
|
|
int dbug_in_char( int minor )
|
213 |
|
|
{
|
214 |
|
|
if (minor==UART_CHANNEL_A) {
|
215 |
|
|
return DURBA;
|
216 |
|
|
}
|
217 |
|
|
else if (minor==UART_CHANNEL_B) {
|
218 |
|
|
return DURBB;
|
219 |
|
|
}
|
220 |
|
|
return 0;
|
221 |
|
|
}
|
222 |
|
|
|
223 |
|
|
/******************************************************
|
224 |
|
|
Name: dbug_char_present
|
225 |
|
|
Input parameters: channel #
|
226 |
|
|
Output parameters: TRUE or FALSE
|
227 |
|
|
Description: return whether there's a character
|
228 |
|
|
in the receive buffer
|
229 |
|
|
*****************************************************/
|
230 |
|
|
int dbug_char_present( int minor )
|
231 |
|
|
{
|
232 |
|
|
if (minor==UART_CHANNEL_A) {
|
233 |
|
|
return (DUSRA & m340_Rx_RDY);
|
234 |
|
|
}
|
235 |
|
|
else if (minor==UART_CHANNEL_B) {
|
236 |
|
|
return (DUSRB & m340_Rx_RDY);
|
237 |
|
|
}
|
238 |
|
|
return 0;
|
239 |
|
|
}
|
240 |
|
|
|
241 |
|
|
/******************************************************
|
242 |
|
|
Name: dbugInitialise
|
243 |
|
|
Input parameters: -
|
244 |
|
|
Output parameters: -
|
245 |
|
|
Description: Init the UART
|
246 |
|
|
*****************************************************/
|
247 |
|
|
static void
|
248 |
|
|
dbugInitialise ()
|
249 |
|
|
{
|
250 |
|
|
t_baud_speed_table uart_config; /* configuration of UARTS */
|
251 |
|
|
|
252 |
|
|
/*
|
253 |
|
|
* Reset Receiver
|
254 |
|
|
*/
|
255 |
|
|
DUCRA = m340_Reset_Receiver;
|
256 |
|
|
DUCRB = m340_Reset_Receiver;
|
257 |
|
|
|
258 |
|
|
/*
|
259 |
|
|
* Reset Transmitter
|
260 |
|
|
*/
|
261 |
|
|
DUCRA = m340_Reset_Transmitter;
|
262 |
|
|
DUCRB = m340_Reset_Transmitter;
|
263 |
|
|
|
264 |
|
|
/*
|
265 |
|
|
* Enable serial module for normal operation, ignore FREEZE, select the crystal clock,
|
266 |
|
|
* supervisor/user serial registers unrestricted
|
267 |
|
|
* interrupt arbitration at priority CONSOLE_INTERRUPT_ARBITRATION
|
268 |
|
|
* WARNING : 8 bits access only on this UART!
|
269 |
|
|
*/
|
270 |
|
|
DUMCRH = 0x00;
|
271 |
|
|
DUMCRL = CONSOLE_INTERRUPT_ARBITRATION;
|
272 |
|
|
|
273 |
|
|
/*
|
274 |
|
|
* Interrupt level register
|
275 |
|
|
*/
|
276 |
|
|
DUILR = CONSOLE_IRQ_LEVEL;
|
277 |
|
|
|
278 |
|
|
/* sets the IVR */
|
279 |
|
|
DUIVR = CONSOLE_VECTOR;
|
280 |
|
|
|
281 |
|
|
/* search for a correct m340 uart configuration */
|
282 |
|
|
uart_config = Find_Right_m340_UART_Config(m340_uart_config[UART_CHANNEL_A].rx_baudrate,
|
283 |
|
|
m340_uart_config[UART_CHANNEL_A].tx_baudrate,
|
284 |
|
|
CHANNEL_ENABLED_A,
|
285 |
|
|
m340_uart_config[UART_CHANNEL_B].rx_baudrate,
|
286 |
|
|
m340_uart_config[UART_CHANNEL_B].tx_baudrate,
|
287 |
|
|
CHANNEL_ENABLED_B);
|
288 |
|
|
|
289 |
|
|
/*****************************************************************************
|
290 |
|
|
** CHANNEL A **
|
291 |
|
|
*****************************************************************************/
|
292 |
|
|
if (CHANNEL_ENABLED_A) {
|
293 |
|
|
|
294 |
|
|
if (USE_INTERRUPTS_A) {
|
295 |
|
|
rtems_isr_entry old_handler;
|
296 |
|
|
rtems_status_code sc;
|
297 |
|
|
|
298 |
|
|
extern void _Debug_ISR_Handler_Console(void);
|
299 |
|
|
|
300 |
|
|
sc = rtems_interrupt_catch (InterruptHandler,
|
301 |
|
|
CONSOLE_VECTOR,
|
302 |
|
|
&old_handler);
|
303 |
|
|
|
304 |
|
|
/* uncomment this if you want to pass control to your own ISR handler
|
305 |
|
|
it may be usefull to do so to check for performances with an oscilloscope */
|
306 |
|
|
/*
|
307 |
|
|
{
|
308 |
|
|
proc_ptr ignored;
|
309 |
|
|
_CPU_ISR_install_raw_handler( CONSOLE_VECTOR, _Debug_ISR_Handler_Console, &ignored );
|
310 |
|
|
}
|
311 |
|
|
*/
|
312 |
|
|
|
313 |
|
|
/*
|
314 |
|
|
* Interrupt Enable Register
|
315 |
|
|
* Enable Interrupts on Channel A Receiver Ready
|
316 |
|
|
*/
|
317 |
|
|
set_DUIER(m340_RxRDYA);
|
318 |
|
|
}
|
319 |
|
|
else {
|
320 |
|
|
/*
|
321 |
|
|
* Disable Interrupts on channel A
|
322 |
|
|
*/
|
323 |
|
|
unset_DUIER(m340_RxRDYA&m340_TxRDYA);
|
324 |
|
|
}
|
325 |
|
|
|
326 |
|
|
/*
|
327 |
|
|
* Change set of baud speeds
|
328 |
|
|
* disable input control
|
329 |
|
|
*/
|
330 |
|
|
/* no good uart configuration ? */
|
331 |
|
|
if (uart_config.nb<1) rtems_fatal_error_occurred (-1);
|
332 |
|
|
|
333 |
|
|
if (uart_config.baud_speed_table[UART_CHANNEL_A].set==1)
|
334 |
|
|
DUACR = m340_BRG_Set1;
|
335 |
|
|
else
|
336 |
|
|
DUACR = m340_BRG_Set2;
|
337 |
|
|
|
338 |
|
|
/*
|
339 |
|
|
* make OPCR an auxiliary function serving the communication channels
|
340 |
|
|
*/
|
341 |
|
|
DUOPCR = m340_OPCR_Aux;
|
342 |
|
|
|
343 |
|
|
/* poll the XTAL_RDY bit until it is cleared to ensure that an unstable crystal
|
344 |
|
|
input is not applied to the baud rate generator */
|
345 |
|
|
while (DUISR & m340_XTAL_RDY) continue;
|
346 |
|
|
|
347 |
|
|
/*
|
348 |
|
|
* Serial Channel Baud Speed
|
349 |
|
|
*/
|
350 |
|
|
DUCSRA = (uart_config.baud_speed_table[UART_CHANNEL_A].rcs << 4)
|
351 |
|
|
| (uart_config.baud_speed_table[UART_CHANNEL_A].tcs);
|
352 |
|
|
|
353 |
|
|
/*
|
354 |
|
|
* Serial Channel Configuration
|
355 |
|
|
*/
|
356 |
|
|
DUMR1A = m340_uart_config[UART_CHANNEL_A].parity_mode
|
357 |
|
|
| m340_uart_config[UART_CHANNEL_A].bits_per_char
|
358 |
|
|
| m340_RxRTS;
|
359 |
|
|
|
360 |
|
|
if (m340_uart_config[UART_CHANNEL_A].rx_mode==UART_FIFO_FULL) DUMR1A |= m340_R_F | m340_ERR;
|
361 |
|
|
|
362 |
|
|
/*
|
363 |
|
|
* Serial Channel Configuration 2
|
364 |
|
|
*/
|
365 |
|
|
DUMR2A |= m340_normal;
|
366 |
|
|
|
367 |
|
|
/*
|
368 |
|
|
* Enable Channel A: transmitter and receiver
|
369 |
|
|
*/
|
370 |
|
|
DUCRA = m340_Transmitter_Enable | m340_Receiver_Enable;
|
371 |
|
|
} /* channel A enabled */
|
372 |
|
|
|
373 |
|
|
/*****************************************************************************
|
374 |
|
|
** CHANNEL B **
|
375 |
|
|
*****************************************************************************/
|
376 |
|
|
if (CHANNEL_ENABLED_B) {
|
377 |
|
|
|
378 |
|
|
/* we mustn't set the console vector twice! */
|
379 |
|
|
if ((USE_INTERRUPTS_B && !(CHANNEL_ENABLED_A))
|
380 |
|
|
|| (USE_INTERRUPTS_B && CHANNEL_ENABLED_A && !USE_INTERRUPTS_A)) {
|
381 |
|
|
rtems_isr_entry old_handler;
|
382 |
|
|
rtems_status_code sc;
|
383 |
|
|
|
384 |
|
|
extern void _Debug_ISR_Handler_Console(void);
|
385 |
|
|
|
386 |
|
|
sc = rtems_interrupt_catch (InterruptHandler,
|
387 |
|
|
CONSOLE_VECTOR,
|
388 |
|
|
&old_handler);
|
389 |
|
|
|
390 |
|
|
/* uncomment this if you want to pass control to your own ISR handler
|
391 |
|
|
it may be usefull to do so to check for performances with an oscilloscope */
|
392 |
|
|
/*
|
393 |
|
|
{
|
394 |
|
|
proc_ptr ignored;
|
395 |
|
|
_CPU_ISR_install_raw_handler( CONSOLE_VECTOR, _Debug_ISR_Handler_Console, &ignored );
|
396 |
|
|
}
|
397 |
|
|
*/
|
398 |
|
|
|
399 |
|
|
/*
|
400 |
|
|
* Interrupt Enable Register
|
401 |
|
|
* Enable Interrupts on Channel A Receiver Ready
|
402 |
|
|
*/
|
403 |
|
|
set_DUIER(m340_RxRDYB);
|
404 |
|
|
}
|
405 |
|
|
else {
|
406 |
|
|
/*
|
407 |
|
|
* Disable Interrupts on channel B
|
408 |
|
|
*/
|
409 |
|
|
unset_DUIER(m340_RxRDYB&m340_TxRDYB);
|
410 |
|
|
}
|
411 |
|
|
|
412 |
|
|
/*
|
413 |
|
|
* Change set of baud speeds
|
414 |
|
|
* disable input control
|
415 |
|
|
*/
|
416 |
|
|
|
417 |
|
|
/* no good uart configuration ? */
|
418 |
|
|
if (uart_config.nb<2) rtems_fatal_error_occurred (-1);
|
419 |
|
|
|
420 |
|
|
/* don't set DUACR twice! */
|
421 |
|
|
if (!CHANNEL_ENABLED_A)
|
422 |
|
|
if (uart_config.baud_speed_table[UART_CHANNEL_B].set==1) DUACR = m340_BRG_Set1;
|
423 |
|
|
else DUACR = m340_BRG_Set2;
|
424 |
|
|
|
425 |
|
|
/*
|
426 |
|
|
* make OPCR an auxiliary function serving the communication channels
|
427 |
|
|
*/
|
428 |
|
|
if (!CHANNEL_ENABLED_A) DUOPCR = m340_OPCR_Aux;
|
429 |
|
|
|
430 |
|
|
/* poll the XTAL_RDY bit until it is cleared to ensure that an unstable crystal
|
431 |
|
|
input is not applied to the baud rate generator */
|
432 |
|
|
while (DUISR & m340_XTAL_RDY) continue;
|
433 |
|
|
|
434 |
|
|
/*
|
435 |
|
|
* Serial Channel Baud Speed
|
436 |
|
|
*/
|
437 |
|
|
DUCSRB = (uart_config.baud_speed_table[UART_CHANNEL_B].rcs << 4)
|
438 |
|
|
| (uart_config.baud_speed_table[UART_CHANNEL_B].tcs);
|
439 |
|
|
|
440 |
|
|
/*
|
441 |
|
|
* Serial Channel Configuration
|
442 |
|
|
*/
|
443 |
|
|
DUMR1B = m340_uart_config[UART_CHANNEL_B].parity_mode
|
444 |
|
|
| m340_uart_config[UART_CHANNEL_B].bits_per_char
|
445 |
|
|
| m340_RxRTS;
|
446 |
|
|
|
447 |
|
|
if (m340_uart_config[UART_CHANNEL_B].rx_mode==UART_FIFO_FULL) DUMR1B |= m340_R_F | m340_ERR;
|
448 |
|
|
|
449 |
|
|
/*
|
450 |
|
|
* Serial Channel Configuration 2
|
451 |
|
|
*/
|
452 |
|
|
DUMR2B |= m340_normal;
|
453 |
|
|
|
454 |
|
|
/*
|
455 |
|
|
* Enable Channel A: transmitter and receiver
|
456 |
|
|
*/
|
457 |
|
|
DUCRB = m340_Transmitter_Enable | m340_Receiver_Enable;
|
458 |
|
|
} /* channel B enabled */
|
459 |
|
|
}
|
460 |
|
|
|
461 |
|
|
/******************************************************
|
462 |
|
|
Name: SetAttributes
|
463 |
|
|
Input parameters: termios structure, channel
|
464 |
|
|
Output parameters: -
|
465 |
|
|
Description: return whether there's a character
|
466 |
|
|
in the receive buffer
|
467 |
|
|
TO DO: add the channel # to check for!!
|
468 |
|
|
*****************************************************/
|
469 |
|
|
static int
|
470 |
|
|
SetAttributes (int minor, const struct termios *t)
|
471 |
|
|
{
|
472 |
|
|
rtems_interrupt_level level;
|
473 |
|
|
float ispeed, ospeed;
|
474 |
|
|
int isp, osp;
|
475 |
|
|
|
476 |
|
|
/* output speed */
|
477 |
|
|
if (t->c_cflag & CBAUDEX)
|
478 |
|
|
osp = (t->c_cflag & CBAUD) + CBAUD + 1;
|
479 |
|
|
else
|
480 |
|
|
osp = t->c_cflag & CBAUD;
|
481 |
|
|
|
482 |
|
|
/* input speed */
|
483 |
|
|
isp = (t->c_cflag / (CIBAUD / CBAUD)) & CBAUD;
|
484 |
|
|
|
485 |
|
|
/* convert it */
|
486 |
|
|
ispeed = termios_baud_rates_equivalence(isp);
|
487 |
|
|
ospeed = termios_baud_rates_equivalence(osp);
|
488 |
|
|
|
489 |
|
|
if (ispeed || ospeed) {
|
490 |
|
|
/* update config table */
|
491 |
|
|
m340_uart_config[UART_CHANNEL_A].rx_baudrate = ((minor==UART_CHANNEL_A)&&(ispeed!=0)) ? ispeed : m340_uart_config[UART_CHANNEL_A].rx_baudrate;
|
492 |
|
|
m340_uart_config[UART_CHANNEL_A].tx_baudrate = ((minor==UART_CHANNEL_A)&&(ospeed!=0)) ? ospeed : m340_uart_config[UART_CHANNEL_A].tx_baudrate;
|
493 |
|
|
m340_uart_config[UART_CHANNEL_B].rx_baudrate = ((minor==UART_CHANNEL_B)&&(ispeed!=0)) ? ispeed : m340_uart_config[UART_CHANNEL_B].rx_baudrate;
|
494 |
|
|
m340_uart_config[UART_CHANNEL_B].tx_baudrate = ((minor==UART_CHANNEL_B)&&(ospeed!=0)) ? ospeed : m340_uart_config[UART_CHANNEL_B].tx_baudrate;
|
495 |
|
|
}
|
496 |
|
|
|
497 |
|
|
/* change parity */
|
498 |
|
|
if (t->c_cflag & PARENB) {
|
499 |
|
|
if (t->c_cflag & PARODD) m340_uart_config[minor].parity_mode = m340_Odd_Parity;
|
500 |
|
|
else m340_uart_config[minor].parity_mode = m340_Even_Parity;
|
501 |
|
|
}
|
502 |
|
|
|
503 |
|
|
/* change bits per character */
|
504 |
|
|
if (t->c_cflag & CSIZE) {
|
505 |
|
|
switch (t->c_cflag & CSIZE) {
|
506 |
|
|
default: break;
|
507 |
|
|
case CS5: m340_uart_config[minor].bits_per_char = m340_5bpc; break;
|
508 |
|
|
case CS6: m340_uart_config[minor].bits_per_char = m340_6bpc; break;
|
509 |
|
|
case CS7: m340_uart_config[minor].bits_per_char = m340_7bpc; break;
|
510 |
|
|
case CS8: m340_uart_config[minor].bits_per_char = m340_8bpc; break;
|
511 |
|
|
}
|
512 |
|
|
}
|
513 |
|
|
|
514 |
|
|
/* if serial module configuration has been changed */
|
515 |
|
|
if (t->c_cflag & (CBAUD | CIBAUD | CSIZE | PARENB)) {
|
516 |
|
|
rtems_interrupt_disable(level);
|
517 |
|
|
/* reinit the UART */
|
518 |
|
|
dbugInitialise();
|
519 |
|
|
rtems_interrupt_enable (level);
|
520 |
|
|
}
|
521 |
|
|
|
522 |
|
|
return 0;
|
523 |
|
|
}
|
524 |
|
|
|
525 |
|
|
/******************************************************
|
526 |
|
|
Name: console_initialize
|
527 |
|
|
Input parameters: MAJOR # of console_driver,
|
528 |
|
|
minor is always 0,
|
529 |
|
|
args are always NULL
|
530 |
|
|
Output parameters: -
|
531 |
|
|
Description: Reserve resources consumed by this driver
|
532 |
|
|
TODO: We should pass m340_uart_config table in arg
|
533 |
|
|
*****************************************************/
|
534 |
|
|
rtems_device_driver console_initialize(
|
535 |
|
|
rtems_device_major_number major,
|
536 |
|
|
rtems_device_minor_number minor,
|
537 |
|
|
void *arg
|
538 |
|
|
)
|
539 |
|
|
{
|
540 |
|
|
rtems_status_code status;
|
541 |
|
|
int i;
|
542 |
|
|
|
543 |
|
|
/*
|
544 |
|
|
* Set up TERMIOS
|
545 |
|
|
*/
|
546 |
|
|
rtems_termios_initialize ();
|
547 |
|
|
|
548 |
|
|
/*
|
549 |
|
|
* Do device-specific initialization
|
550 |
|
|
*/
|
551 |
|
|
Init_UART_Table();
|
552 |
|
|
dbugInitialise ();
|
553 |
|
|
Fifo_Full_Timer_initialize();
|
554 |
|
|
|
555 |
|
|
/*
|
556 |
|
|
* Register the devices
|
557 |
|
|
*/
|
558 |
|
|
for (i=0; i<UART_NUMBER_OF_CHANNELS; i++) {
|
559 |
|
|
if (m340_uart_config[i].enable) {
|
560 |
|
|
status = rtems_io_register_name (m340_uart_config[i].name, major, i);
|
561 |
|
|
if (status != RTEMS_SUCCESSFUL)
|
562 |
|
|
rtems_fatal_error_occurred (status);
|
563 |
|
|
}
|
564 |
|
|
}
|
565 |
|
|
|
566 |
|
|
return RTEMS_SUCCESSFUL;
|
567 |
|
|
}
|
568 |
|
|
|
569 |
|
|
/******************************************************
|
570 |
|
|
Name: console_open
|
571 |
|
|
Input parameters: channel #, arg
|
572 |
|
|
Output parameters: -
|
573 |
|
|
Description: open the device
|
574 |
|
|
*****************************************************/
|
575 |
|
|
rtems_device_driver console_open(
|
576 |
|
|
rtems_device_major_number major,
|
577 |
|
|
rtems_device_minor_number minor,
|
578 |
|
|
void * arg
|
579 |
|
|
)
|
580 |
|
|
{
|
581 |
|
|
rtems_status_code sc = 0;
|
582 |
|
|
|
583 |
|
|
static const rtems_termios_callbacks intrCallbacks = {
|
584 |
|
|
NULL, /* firstOpen */
|
585 |
|
|
NULL, /* lastClose */
|
586 |
|
|
NULL, /* pollRead */
|
587 |
|
|
InterruptWrite, /* write */
|
588 |
|
|
SetAttributes, /* setAttributes */
|
589 |
|
|
NULL, /* stopRemoteTx */
|
590 |
|
|
NULL, /* startRemoteTx */
|
591 |
|
|
1 /* outputUsesInterrupts */
|
592 |
|
|
};
|
593 |
|
|
|
594 |
|
|
static const rtems_termios_callbacks pollCallbacks = {
|
595 |
|
|
NULL, /* firstOpen */
|
596 |
|
|
NULL, /* lastClose */
|
597 |
|
|
dbugRead, /* pollRead */
|
598 |
|
|
dbugWrite, /* write */
|
599 |
|
|
SetAttributes, /* setAttributes */
|
600 |
|
|
NULL, /* stopRemoteTx */
|
601 |
|
|
NULL, /* startRemoteTx */
|
602 |
|
|
|
603 |
|
|
};
|
604 |
|
|
|
605 |
|
|
if (minor==UART_CHANNEL_A) {
|
606 |
|
|
if (USE_INTERRUPTS_A) {
|
607 |
|
|
rtems_libio_open_close_args_t *args = arg;
|
608 |
|
|
|
609 |
|
|
sc |= rtems_termios_open (major, minor, arg, &intrCallbacks);
|
610 |
|
|
ttypA = args->iop->data1;
|
611 |
|
|
}
|
612 |
|
|
else {
|
613 |
|
|
sc |= rtems_termios_open (major, minor, arg, &pollCallbacks);
|
614 |
|
|
}
|
615 |
|
|
}
|
616 |
|
|
|
617 |
|
|
else if (minor==UART_CHANNEL_B) {
|
618 |
|
|
if (USE_INTERRUPTS_B) {
|
619 |
|
|
rtems_libio_open_close_args_t *args = arg;
|
620 |
|
|
|
621 |
|
|
sc |= rtems_termios_open (major, minor, arg, &intrCallbacks);
|
622 |
|
|
ttypB = args->iop->data1;
|
623 |
|
|
}
|
624 |
|
|
else {
|
625 |
|
|
sc |= rtems_termios_open (major, minor, arg, &pollCallbacks);
|
626 |
|
|
}
|
627 |
|
|
}
|
628 |
|
|
|
629 |
|
|
else return RTEMS_INVALID_NUMBER;
|
630 |
|
|
|
631 |
|
|
return sc;
|
632 |
|
|
}
|
633 |
|
|
|
634 |
|
|
/******************************************************
|
635 |
|
|
Name: console_close
|
636 |
|
|
Input parameters: channel #, termios args
|
637 |
|
|
Output parameters: -
|
638 |
|
|
Description: close the device
|
639 |
|
|
*****************************************************/
|
640 |
|
|
rtems_device_driver console_close(
|
641 |
|
|
rtems_device_major_number major,
|
642 |
|
|
rtems_device_minor_number minor,
|
643 |
|
|
void * arg
|
644 |
|
|
)
|
645 |
|
|
{
|
646 |
|
|
return rtems_termios_close (arg);
|
647 |
|
|
}
|
648 |
|
|
|
649 |
|
|
/******************************************************
|
650 |
|
|
Name: console_read
|
651 |
|
|
Input parameters: channel #, termios args
|
652 |
|
|
Output parameters: -
|
653 |
|
|
Description: read the device
|
654 |
|
|
*****************************************************/
|
655 |
|
|
rtems_device_driver console_read(
|
656 |
|
|
rtems_device_major_number major,
|
657 |
|
|
rtems_device_minor_number minor,
|
658 |
|
|
void * arg
|
659 |
|
|
)
|
660 |
|
|
{
|
661 |
|
|
return rtems_termios_read (arg);
|
662 |
|
|
}
|
663 |
|
|
|
664 |
|
|
/******************************************************
|
665 |
|
|
Name: console_write
|
666 |
|
|
Input parameters: channel #, termios args
|
667 |
|
|
Output parameters: -
|
668 |
|
|
Description: write to the device
|
669 |
|
|
*****************************************************/
|
670 |
|
|
rtems_device_driver console_write(
|
671 |
|
|
rtems_device_major_number major,
|
672 |
|
|
rtems_device_minor_number minor,
|
673 |
|
|
void * arg
|
674 |
|
|
)
|
675 |
|
|
{
|
676 |
|
|
return rtems_termios_write (arg);
|
677 |
|
|
}
|
678 |
|
|
|
679 |
|
|
/******************************************************
|
680 |
|
|
Name: console_control
|
681 |
|
|
Input parameters: channel #, termios args
|
682 |
|
|
Output parameters: -
|
683 |
|
|
Description: Handle ioctl request
|
684 |
|
|
*****************************************************/
|
685 |
|
|
rtems_device_driver console_control(
|
686 |
|
|
rtems_device_major_number major,
|
687 |
|
|
rtems_device_minor_number minor,
|
688 |
|
|
void * arg
|
689 |
|
|
)
|
690 |
|
|
{
|
691 |
|
|
rtems_libio_ioctl_args_t *args = arg;
|
692 |
|
|
|
693 |
|
|
if (args->command == RTEMS_IO_SET_ATTRIBUTES)
|
694 |
|
|
SetAttributes (minor, (struct termios *)args->buffer);
|
695 |
|
|
|
696 |
|
|
return rtems_termios_ioctl (arg);
|
697 |
|
|
}
|