source: rtems/c/src/lib/libbsp/m68k/efi68k/console/console.c @ 486c329

4.104.114.84.95
Last change on this file since 486c329 was 486c329, checked in by Joel Sherrill <joel.sherrill@…>, on Sep 20, 1995 at 3:05:19 PM

Actually adding efi bsp's from John Gwynne after forgetting to
commit them.

  • Property mode set to 100644
File size: 8.4 KB
Line 
1/*
2 *  This file contains the efi68k console IO package.
3 *
4 *  COPYRIGHT (c) 1989, 1990, 1991, 1992, 1993, 1994.
5 *  On-Line Applications Research Corporation (OAR).
6 *  All rights assigned to U.S. Government, 1994.
7 *
8 *  This material may be reproduced by or for the U.S. Government pursuant
9 *  to the copyright license under the clause at DFARS 252.227-7013.  This
10 *  notice must appear in all copies of this file and its derivatives.
11 *
12 *  $Id$
13 */
14
15#include <stdlib.h>
16#include <bsp.h>
17#include <rtems/libio.h>
18
19
20#define BAUD 38400
21#define CLK_FREQ 8000000.0
22
23/* BUFFER_LENGTH must be 2^n for n=1, 2, 3, .... */
24#define BUFFER_LENGTH 256
25#define RTS_STOP_SIZE BUFFER_LENGTH-64
26#define RTS_START_SIZE 16
27
28char xmt_buf[BUFFER_LENGTH];
29char rcv_buf[BUFFER_LENGTH];
30/* in: last entry into the buffer; always on a valid character */
31/* out: points to the next character to be pull from the buffer */
32/*    in+1=out => buffer empty */
33/*    in+2=out => buffer full */
34struct UART_buf {
35  char *offset; 
36  char *in; 
37  char *out;
38};
39static volatile struct UART_buf  xmt = { xmt_buf, (char *)0, (char *)1};
40static volatile struct UART_buf  rcv = { rcv_buf, (char *)0, (char *)1};
41static volatile char _debug_flag = 0;
42static volatile char _tx_stop = 0;
43
44/* _catchUARTint is the interrupt front-end */
45extern void _catchUARTint();
46asm("   .text
47        .align 2
48        .globl _catchUARTint
49_catchUARTint:
50        lea    %sp@(4),%sp                /* pop return address */
51        moveml %d0-%d7/%a0-%a6,%sp@-       /* save registers */
52        jbsr    uart_interrupt
53        moveml  %sp@+,%d0-%d7/%a0-%a6                           
54        rte
55    ");
56
57/* _fake_trap_1 will continue the UART interrupt (%sr *still*
58   UART_ISR_LEVEL) as a trap #1 to enter the debugger */
59asm("   .text
60        .align 2
61_fake_trap_1:
62        unlk %a6                /* clear interrupt frame */
63        lea %sp@(4),%sp         /* remove jbsr instruction */
64        moveml %sp@+,%d0-%d7/%a0-%a6 /* pop registers */
65        jmp (33*6-12+_VBR)      /* jump exception 1 */
66        ");
67
68/* dispatch UART interrupt */
69void xmit_interrupt(void);
70void rcvr_interrupt(void);
71void modem_status(void);
72void _fake_trap_1(void);
73void uart_interrupt(void) {
74  register char a;
75
76  a=*IIR & (NIP | IID_MASK); /* read interrupt id register */
77  switch (a) {
78  case 0x04: case 0x0c:
79    rcvr_interrupt();
80    break;
81  case 0x02:
82    xmit_interrupt();
83    break;
84  case 0x00:
85    modem_status();
86    break;
87  default:
88    break;
89  }
90  if (_debug_flag) {
91    _debug_flag = 0;            /* reset the flag */
92    _fake_trap_1();             /* fake a trap #1 */
93  }
94}
95
96/* transfer received character to the buffer */
97void rcvr_interrupt(void) {
98  register char *a, c;
99  register int length;
100
101  while ( (*LSR & DR) != 0) {
102    if ((c=*RBR) == 0x1a)       /* use ctl-z to reboot */
103      reboot();
104    else if (c == 0x03) {       /* use ctl-c to enter debugger */
105      _debug_flag = 1;
106      continue;
107    }
108    *(char *)((int)rcv.offset +(int)
109              (a=(char *)(((int)rcv.in+1) & ((int)BUFFER_LENGTH-1)))) = c;
110    if ((char *)(((int)rcv.in+2) & ((int)BUFFER_LENGTH-1)) != rcv.out)
111      rcv.in=a;
112  }
113  length = (BUFFER_LENGTH -1) & ( 
114    ( ((int)rcv.out <= (int)rcv.in) ? 0 : BUFFER_LENGTH) - (int)rcv.out
115    + (int)rcv.in + 1);
116  if (length >= RTS_STOP_SIZE)
117    *MCR &= (char) (~RTS);
118}
119
120/* tranfer buffered characters to the UART */
121void xmit_interrupt(void) {
122  register short int i, oldsr;
123
124  _CPU_ISR_Disable( oldsr ); /* for when outbyte calls */
125  if ( (*LSR & THRE) != 0 && _tx_stop == 0 )
126    for (i=0;i<16;i++) {
127      if ((char *)(((int)xmt.in+1) & ((int)BUFFER_LENGTH-1))== xmt.out)
128        break;
129      *THR=*(char *)((int)xmt.offset+(int)xmt.out);
130      xmt.out= (char *)(((int)xmt.out+1) & ((int)BUFFER_LENGTH-1));
131    }
132  _CPU_ISR_Enable( oldsr );
133}
134
135void modem_status(void) {
136  register char a;
137 
138  if ( ((a=*MDSR) & DCTS) != 0 )
139    if ( (a & CTS) == 0)
140      _tx_stop = 1;
141    else {
142      _tx_stop = 0;
143      xmit_interrupt();
144    }
145}
146
147/* transfer character from the buffer */
148char inbyte(void) {
149  register char a;
150  register int length;
151
152  while ((char *)(((int)rcv.in+1) & ((int)BUFFER_LENGTH-1))== rcv.out);
153  a=*(char *)((int)rcv.offset+(int)rcv.out);
154  rcv.out= (char *)(((int)rcv.out+1) & ((int)BUFFER_LENGTH-1));
155  length = (BUFFER_LENGTH -1) & ( 
156    ( ((int)rcv.out <= (int)rcv.in) ? 0 : BUFFER_LENGTH) - (int)rcv.out
157    + (int)rcv.in + 1);
158  if (length < RTS_START_SIZE)
159    *MCR |= (char) RTS;
160  return (a);
161}
162
163/* once room is avaliable in the buffer, transfer
164   the character into the buffer and enable
165   the xmtr interrupt */
166void outbyte(char c) {
167  register char *a;
168 
169  while ((char *)(((int)xmt.in+2) & ((int)BUFFER_LENGTH-1)) == xmt.out);
170  *(char *)((int)xmt.offset+(int)
171            (a=(char *)(((int)xmt.in+1) & ((int)BUFFER_LENGTH-1))))=c;
172  xmt.in=a;
173
174  if ( (*LSR & THRE) != 0 )     /* if THRE, uart has already interrupted */
175    xmit_interrupt();           /*   and was ignored. Need to restart. */
176}
177
178void _UART_flush(void) {
179  /* loop till xmt buffer empty. Works with interrupts disabled */
180  while ((char *)(((int)xmt.in+1) & ((int)BUFFER_LENGTH-1)) != xmt.out)
181    xmit_interrupt();
182  /* loop till UART buffer empty */
183  while ( (*LSR & TEMT) == 0 );
184}
185
186/*  console_initialize
187 *
188 *  This routine initializes the console IO driver.
189 *
190 *  Input parameters: NONE
191 *
192 *  Output parameters:  NONE
193 *
194 *  Return values:
195 */
196 
197rtems_device_driver console_initialize(
198  rtems_device_major_number  major,
199  rtems_device_minor_number  minor,
200  void                      *arg
201)
202{
203  rtems_status_code status;
204
205  /* set clock divisor */
206  *LCR = (char)(DLAB);
207  *DLL = (char)((int)(CLK_FREQ/BAUD/16.0+0.5) & 0xFF);
208  *DLM = (char)(((int)(CLK_FREQ/BAUD/16.0+0.5) & 0xFF00) >> 8);
209
210  /* Line control setup */
211  *LCR = (char)(WL_8 | NSB);
212
213  /* Interrupt setup */
214  *IER = (char) 0x0b;           /* enable transmit, receive, modem stat int */
215 
216  /* FIFO setup */
217  *FCR = (char)(FIFO_E | 0xc0);
218
219  /* Modem control setup */
220  *MCR = (char) RTS;
221
222  /* init tx_stop with CTS */
223  _tx_stop = ( (*MDSR & CTS) ? 0 : 1);
224
225  set_vector(_catchUARTint, UART_ISR_LEVEL+24, 0);
226
227  status = rtems_io_register_name(
228    "/dev/console",
229    major,
230    (rtems_device_minor_number) 0
231  );
232 
233  if (status != RTEMS_SUCCESSFUL)
234    rtems_fatal_error_occurred(status);
235 
236  return RTEMS_SUCCESSFUL;
237
238}
239
240
241/*  is_character_ready
242 *
243 *  This routine returns TRUE if a character is available.
244 *
245 *  Input parameters: NONE
246 *
247 *  Output parameters:  NONE
248 *
249 *  Return values:
250 */
251
252rtems_boolean is_character_ready(
253  char *ch
254)
255{
256  if ((char *)(((int)rcv.in+1) & ((int)BUFFER_LENGTH-1))== rcv.out)
257    return(FALSE);
258  else
259    return(TRUE);
260}
261
262/*
263 *  Open entry point
264 */
265 
266rtems_device_driver console_open(
267  rtems_device_major_number major,
268  rtems_device_minor_number minor,
269  void                    * arg
270)
271{
272  return RTEMS_SUCCESSFUL;
273}
274 
275/*
276 *  Close entry point
277 */
278 
279rtems_device_driver console_close(
280  rtems_device_major_number major,
281  rtems_device_minor_number minor,
282  void                    * arg
283)
284{
285  return RTEMS_SUCCESSFUL;
286}
287 
288/*
289 * read bytes from the serial port. We only have stdin.
290 */
291 
292rtems_device_driver console_read(
293  rtems_device_major_number major,
294  rtems_device_minor_number minor,
295  void                    * arg
296)
297{
298  rtems_libio_rw_args_t *rw_args;
299  char *buffer;
300  int maximum;
301  int count = 0;
302 
303  rw_args = (rtems_libio_rw_args_t *) arg;
304 
305  buffer = rw_args->buffer;
306  maximum = rw_args->count;
307 
308  for (count = 0; count < maximum; count++) {
309    buffer[ count ] = inbyte();
310    if (buffer[ count ] == '\n' || buffer[ count ] == '\r') {
311      buffer[ count++ ]  = '\n';
312      buffer[ count ]  = 0;
313      break;
314    }
315  }
316 
317  rw_args->bytes_moved = count;
318  return (count >= 0) ? RTEMS_SUCCESSFUL : RTEMS_UNSATISFIED;
319}
320 
321/*
322 * write bytes to the serial port. Stdout and stderr are the same.
323 */
324 
325rtems_device_driver console_write(
326  rtems_device_major_number major,
327  rtems_device_minor_number minor,
328  void                    * arg
329)
330{
331  int count;
332  int maximum;
333  rtems_libio_rw_args_t *rw_args;
334  char *buffer;
335 
336  rw_args = (rtems_libio_rw_args_t *) arg;
337 
338  buffer = rw_args->buffer;
339  maximum = rw_args->count;
340 
341  for (count = 0; count < maximum; count++) {
342    if ( buffer[ count ] == '\n') {
343      outbyte('\r');
344    }
345    outbyte( buffer[ count ] );
346  }
347 
348  rw_args->bytes_moved = maximum;
349  return 0;
350}
351 
352/*
353 *  IO Control entry point
354 */
355 
356rtems_device_driver console_control(
357  rtems_device_major_number major,
358  rtems_device_minor_number minor,
359  void                    * arg
360)
361{
362  return RTEMS_SUCCESSFUL;
363}
Note: See TracBrowser for help on using the repository browser.