source: rtems/c/src/lib/libbsp/m68k/efi332/console/console.c @ 8f35817

4.104.114.84.95
Last change on this file since 8f35817 was 8f35817, checked in by Joel Sherrill <joel.sherrill@…>, on Sep 15, 1997 at 6:52:26 PM

eliminated potential for overfilling buffer on read

  • Property mode set to 100644
File size: 9.2 KB
Line 
1/*
2 *  This file contains the efi332 console IO package.
3 *
4 *  COPYRIGHT (c) 1989-1997.
5 *  On-Line Applications Research Corporation (OAR).
6 *  Copyright assigned to U.S. Government, 1994.
7 *
8 *  The license and distribution terms for this file may in
9 *  the file LICENSE in this distribution or at
10 *  http://www.OARcorp.com/rtems/license.html.
11 *
12 *  $Id$
13 */
14
15#include <stdlib.h>
16#include <bsp.h>
17#include <rtems/libio.h>
18
19/* BUFFER_LENGTH must be 2^n for n=1, 2, 3, .... */
20#define BUFFER_LENGTH 256
21#define RTS_STOP_SIZE BUFFER_LENGTH-64
22#define RTS_START_SIZE 16
23
24char xmt_buf[BUFFER_LENGTH];
25char rcv_buf[BUFFER_LENGTH];
26/* in: last entry into the buffer; always on a valid character */
27/* out: points to the next character to be pull from the buffer */
28/*    in+1=out => buffer empty */
29/*    in+2=out => buffer full */
30struct UART_buf {
31  char *offset; 
32  char *in; 
33  char *out;
34};
35static volatile struct UART_buf  xmt = { xmt_buf, (char *)0, (char *)1};
36static volatile struct UART_buf  rcv = { rcv_buf, (char *)0, (char *)1};
37static volatile char _debug_flag = 0;
38
39#define SET_RTS(a) {*PORTF0 = (*PORTF0 & ~0x4) | ( (a)? 0 : 0x4); }
40#define GET_CTS (!(*PORTF0 & 0x2))
41
42/* _catchSCIint, _catchCTSint, and _catchSPURIOUSint are the
43   interrupt front-ends */
44extern void _catchSCIint();
45asm("   .text
46        .align 2
47        .globl _catchSCIint
48_catchSCIint:
49        moveml %d0-%d7/%a0-%a6,%sp@-       /* save registers */
50        jbsr    uart_interrupt
51        moveml  %sp@+,%d0-%d7/%a0-%a6                           
52        rte
53    ");
54
55extern void _catchCTSint();
56asm("   .text
57        .align 2
58        .globl _catchCTSint
59_catchCTSint:
60        moveml %d0-%d7/%a0-%a6,%sp@-       /* save registers */
61        jbsr    cts_interrupt
62        moveml  %sp@+,%d0-%d7/%a0-%a6                           
63        rte
64    ");
65
66extern void _catchSPURIOUSint();
67asm("   .text
68        .align 2
69        .globl _catchSPURIOUSint
70_catchSPURIOUSint:
71        moveml %d0-%d7/%a0-%a6,%sp@-       /* save registers */
72        jbsr    spurious_interrupt
73        moveml  %sp@+,%d0-%d7/%a0-%a6                           
74        rte
75    ");
76
77int _spurious_int_counter=0;
78
79/* note: cts uses int1. If it "bounces", a spurious interrupt is generated */
80void spurious_interrupt(void) {
81  _spurious_int_counter++;      /* there should never be alot of these */
82}
83
84/* _fake_trap_1 will continue the UART interrupt (%sr *still*
85   UART_ISR_LEVEL) as a trap #1 to enter the debugger */
86
87/* *****fix me; this is for 68000 w/jsr ram exception table ******* */
88asm("   .text
89        .align 2
90_fake_trap_1:
91        unlk %a6                /* clear interrupt frame */
92        lea %sp@(4),%sp         /* remove jbsr instruction */
93        moveml %sp@+,%d0-%d7/%a0-%a6 /* pop registers */
94        jmp (33*6-12)   /* jump exception 1 */
95        ");
96
97/* dispatch UART interrupt */
98void xmit_interrupt(void);
99void rcvr_interrupt(void);
100void _fake_trap_1(void);
101
102void uart_interrupt(void) {
103  /* receiver status bits are cleared by a SCSR read followed
104     by a SCDR read. transmitter status bits are cleared by
105     a SCSR read followed by a SCDR write. */
106  if ((*SCSR) & (TDRE | TC))
107    xmit_interrupt();
108
109  if ((*SCSR) & (RDRF))
110    rcvr_interrupt();
111
112  if (_debug_flag) {
113    _debug_flag = 0;            /* reset the flag */
114    _fake_trap_1();             /* fake a trap #1 */
115  }
116}
117
118/* transfer received character to the buffer */
119void rcvr_interrupt(void) {
120  register char *a, c;
121  register int length;
122
123  while((*SCSR) & (RDRF)) {
124    if ((c=*SCDR) == 0x1a)      /* use ctl-z to reboot */
125      reboot();
126/*     else if (c == 0x03) { */ /* use ctl-c to enter debugger */
127/*       _debug_flag = 1; */
128/*       continue; */
129/*     } */
130
131    *(char *)((int)rcv.offset +(int)
132              (a=(char *)(((int)rcv.in+1) & ((int)BUFFER_LENGTH-1)))) = c;
133    if ((char *)(((int)rcv.in+2) & ((int)BUFFER_LENGTH-1)) != rcv.out)
134      rcv.in=a;
135  };
136
137  length = (BUFFER_LENGTH -1) & ( 
138    ( ((int)rcv.out <= (int)rcv.in) ? 0 : BUFFER_LENGTH) - (int)rcv.out
139    + (int)rcv.in + 1);
140  if (length >= RTS_STOP_SIZE)
141    SET_RTS(0);
142}
143
144/* tranfer buffered characters to the UART */
145void xmit_interrupt(void) {
146  register short int oldsr;
147
148  _CPU_ISR_Disable( oldsr ); /* for when outbyte or flush calls */
149  while ((*SCSR) & (TDRE)) {
150    if ((char *)(((int)xmt.in+1) & ((int)BUFFER_LENGTH-1)) != xmt.out)
151      /* xmit buffer not empty */
152      if (GET_CTS) {
153        /* send next char */
154        *SCDR=*(char *)((int)xmt.offset+(int)xmt.out);
155        xmt.out= (char *)(((int)xmt.out+1) & ((int)BUFFER_LENGTH-1));
156        *SCCR1 = (*SCCR1 & ~(TIE | TCIE)) | (TIE);
157      } 
158      else {
159        /* configue CTS interrupt and shutdown xmit interrupts */
160        *SCCR1 &= ~(TIE | TCIE);
161        *PFPAR |= 0x2;
162        break;
163      }
164    else {
165      /* xmit buffer empty; shutdown interrupts */
166      *SCCR1 &= ~(TIE | TCIE);
167      break;
168    }
169  }
170  _CPU_ISR_Enable( oldsr );
171}
172
173void cts_interrupt(void) {
174  register short int oldsr;
175
176  _CPU_ISR_Disable( oldsr ); /* for when outbyte calls */
177
178  *PFPAR &= ~0x2;
179  *SCCR1 = (*SCCR1 & ~(TIE | TCIE)) | (TIE);
180
181  _CPU_ISR_Enable( oldsr );
182}
183 
184
185
186/* transfer character from the buffer */
187char inbyte(void) {
188  register char a;
189  register int length;
190
191  while ((char *)(((int)rcv.in+1) & ((int)BUFFER_LENGTH-1))== rcv.out);
192  a=*(char *)((int)rcv.offset+(int)rcv.out);
193  rcv.out= (char *)(((int)rcv.out+1) & ((int)BUFFER_LENGTH-1));
194  length = (BUFFER_LENGTH -1) & ( 
195    ( ((int)rcv.out <= (int)rcv.in) ? 0 : BUFFER_LENGTH) - (int)rcv.out
196    + (int)rcv.in + 1);
197  if (length < RTS_START_SIZE)
198    SET_RTS(1);
199  return (a);
200}
201
202/* once room is avaliable in the buffer, transfer
203   the character into the buffer and enable
204   the xmtr interrupt */
205void outbyte(char c) {
206  register char *a;
207 
208  while ((char *)(((int)xmt.in+2) & ((int)BUFFER_LENGTH-1)) == xmt.out);
209  *(char *)((int)xmt.offset+(int)
210            (a=(char *)(((int)xmt.in+1) & ((int)BUFFER_LENGTH-1))))=c;
211  xmt.in=a;
212
213  if (!(*SCCR1 & (TIE | TCIE)) && (!(*PFPAR & 0x2)) )
214                                /* if neither interrupts are running, */
215    xmit_interrupt();           /*    we need to restart the xmiter */
216}
217
218void _UART_flush(void) {
219  /* loop till xmt buffer empty. Works with interrupts disabled */
220  while ((char *)(((int)xmt.in+1) & ((int)BUFFER_LENGTH-1)) != xmt.out)
221    xmit_interrupt();
222  /* loop till UART buffer empty */
223  while ( (*SCSR & TC) == 0 );
224}
225
226/*  console_initialize
227 *
228 *  This routine initializes the console IO driver.
229 *
230 *  Input parameters: NONE
231 *
232 *  Output parameters:  NONE
233 *
234 *  Return values:
235 */
236 
237void console_init()
238{
239  *QSMCR = ( SAM(QSM_IARB,0,IARB) );
240  *QILR = ( SAM(ISRL_QSPI,4,ILQSPI) | SAM(ISRL_SCI,0,ILSCI) );
241  *QIVR = ( SAM(EFI_QIVR,0,INTV) );
242
243  *SCCR0 = ( (int)( SYS_CLOCK/SCI_BAUD/32.0+0.5 ) & 0x1fff );
244  *SCCR1 = ( RIE | TE | RE );
245
246  set_vector(_catchSPURIOUSint, EFI_SPINT, 0);
247  set_vector(_catchSCIint, EFI_QIVR, 0);
248  set_vector(_catchCTSint, EFI_INT1, 0);
249}
250
251rtems_device_driver console_initialize(
252  rtems_device_major_number  major,
253  rtems_device_minor_number  minor,
254  void                      *arg
255)
256{
257  rtems_status_code status;
258
259  status = rtems_io_register_name(
260    "/dev/console",
261    major,
262    (rtems_device_minor_number) 0
263  );
264 
265  if (status != RTEMS_SUCCESSFUL)
266    rtems_fatal_error_occurred(status);
267 
268  return RTEMS_SUCCESSFUL;
269}
270
271/*  is_character_ready
272 *
273 *  This routine returns TRUE if a character is available.
274 *
275 *  Input parameters: NONE
276 *
277 *  Output parameters:  NONE
278 *
279 *  Return values:
280 */
281
282rtems_boolean is_character_ready(
283  char *ch
284)
285{
286  if ((char *)(((int)rcv.in+1) & ((int)BUFFER_LENGTH-1))== rcv.out)
287    return(FALSE);
288  else
289    return(TRUE);
290}
291
292/*
293 *  Open entry point
294 */
295 
296rtems_device_driver console_open(
297  rtems_device_major_number major,
298  rtems_device_minor_number minor,
299  void                    * arg
300)
301{
302  return RTEMS_SUCCESSFUL;
303}
304 
305/*
306 *  Close entry point
307 */
308 
309rtems_device_driver console_close(
310  rtems_device_major_number major,
311  rtems_device_minor_number minor,
312  void                    * arg
313)
314{
315  return RTEMS_SUCCESSFUL;
316}
317 
318/*
319 * read bytes from the serial port. We only have stdin.
320 */
321 
322rtems_device_driver console_read(
323  rtems_device_major_number major,
324  rtems_device_minor_number minor,
325  void                    * arg
326)
327{
328  rtems_libio_rw_args_t *rw_args;
329  char *buffer;
330  int maximum;
331  int count = 0;
332 
333  rw_args = (rtems_libio_rw_args_t *) arg;
334 
335  buffer = rw_args->buffer;
336  maximum = rw_args->count;
337 
338  for (count = 0; count < maximum; count++) {
339    buffer[ count ] = inbyte();
340    if (buffer[ count ] == '\n' || buffer[ count ] == '\r') {
341      buffer[ count++ ]  = '\n';
342      break;
343    }
344  }
345 
346  rw_args->bytes_moved = count;
347  return (count >= 0) ? RTEMS_SUCCESSFUL : RTEMS_UNSATISFIED;
348}
349 
350/*
351 * write bytes to the serial port. Stdout and stderr are the same.
352 */
353 
354rtems_device_driver console_write(
355  rtems_device_major_number major,
356  rtems_device_minor_number minor,
357  void                    * arg
358)
359{
360  int count;
361  int maximum;
362  rtems_libio_rw_args_t *rw_args;
363  char *buffer;
364 
365  rw_args = (rtems_libio_rw_args_t *) arg;
366 
367  buffer = rw_args->buffer;
368  maximum = rw_args->count;
369 
370  for (count = 0; count < maximum; count++) {
371    if ( buffer[ count ] == '\n') {
372      outbyte('\r');
373    }
374    outbyte( buffer[ count ] );
375  }
376 
377  rw_args->bytes_moved = maximum;
378  return 0;
379}
380 
381/*
382 *  IO Control entry point
383 */
384 
385rtems_device_driver console_control(
386  rtems_device_major_number major,
387  rtems_device_minor_number minor,
388  void                    * arg
389)
390{
391  return RTEMS_SUCCESSFUL;
392}
393
Note: See TracBrowser for help on using the repository browser.