source: rtems/c/src/lib/libbsp/m68k/efi68k/console/console.c @ 4269a43

4.104.114.84.95
Last change on this file since 4269a43 was 4269a43, checked in by Joel Sherrill <joel.sherrill@…>, on Nov 1, 2002 at 11:10:45 PM

2002-11-01 Joel Sherrill <joel@…>

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