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

4.104.114.84.95
Last change on this file since d366f2aa was d366f2aa, checked in by Joel Sherrill <joel.sherrill@…>, on 09/04/03 at 18:51:46

2003-09-04 Joel Sherrill <joel@…>

  • clock/ckinit.c, console/console.c, include/16550.h, include/DP8570A.h, include/bsp.h, spurious/spinit.c, startup/bspclean.c, startup/bspstart.c, startup/efi68k_tcp.c, startup/efi68k_wd.c, startup/setvec.c, timer/timer.c: URL for license changed.
  • 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.rtems.com/license/LICENSE.
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
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 
197void console_init()
198{
199  /* set clock divisor */
200  *LCR = (char)(DLAB);
201  *DLL = (char)((int)(CLK_FREQ/BAUD/16.0+0.5) & 0xFF);
202  *DLM = (char)(((int)(CLK_FREQ/BAUD/16.0+0.5) & 0xFF00) >> 8);
203
204  /* Line control setup */
205  *LCR = (char)(WL_8 | NSB);
206
207  /* Interrupt setup */
208  *IER = (char) 0x0b;           /* enable transmit, receive, modem stat int */
209 
210  /* FIFO setup */
211  *FCR = (char)(FIFO_E | 0xc0);
212
213  /* Modem control setup */
214  *MCR = (char) RTS;
215
216  /* init tx_stop with CTS */
217  _tx_stop = ( (*MDSR & CTS) ? 0 : 1);
218
219  set_vector(_catchUARTint, UART_ISR_LEVEL+24, 0);
220}
221
222rtems_device_driver console_initialize(
223  rtems_device_major_number  major,
224  rtems_device_minor_number  minor,
225  void                      *arg
226)
227{
228  rtems_status_code status;
229
230  status = rtems_io_register_name(
231    "/dev/console",
232    major,
233    (rtems_device_minor_number) 0
234  );
235 
236  if (status != RTEMS_SUCCESSFUL)
237    rtems_fatal_error_occurred(status);
238 
239  return RTEMS_SUCCESSFUL;
240
241}
242
243
244/*  is_character_ready
245 *
246 *  This routine returns TRUE if a character is available.
247 *
248 *  Input parameters: NONE
249 *
250 *  Output parameters:  NONE
251 *
252 *  Return values:
253 */
254
255rtems_boolean is_character_ready(
256  char *ch
257)
258{
259  if ((char *)(((int)rcv.in+1) & ((int)BUFFER_LENGTH-1))== rcv.out)
260    return(FALSE);
261  else
262    return(TRUE);
263}
264
265/*
266 *  Open entry point
267 */
268 
269rtems_device_driver console_open(
270  rtems_device_major_number major,
271  rtems_device_minor_number minor,
272  void                    * arg
273)
274{
275  return RTEMS_SUCCESSFUL;
276}
277 
278/*
279 *  Close entry point
280 */
281 
282rtems_device_driver console_close(
283  rtems_device_major_number major,
284  rtems_device_minor_number minor,
285  void                    * arg
286)
287{
288  return RTEMS_SUCCESSFUL;
289}
290 
291/*
292 * read bytes from the serial port. We only have stdin.
293 */
294 
295rtems_device_driver console_read(
296  rtems_device_major_number major,
297  rtems_device_minor_number minor,
298  void                    * arg
299)
300{
301  rtems_libio_rw_args_t *rw_args;
302  char *buffer;
303  int maximum;
304  int count = 0;
305 
306  rw_args = (rtems_libio_rw_args_t *) arg;
307 
308  buffer = rw_args->buffer;
309  maximum = rw_args->count;
310 
311  for (count = 0; count < maximum; count++) {
312    buffer[ count ] = inbyte();
313    if (buffer[ count ] == '\n' || buffer[ count ] == '\r') {
314      buffer[ count++ ]  = '\n';
315      break;
316    }
317  }
318 
319  rw_args->bytes_moved = count;
320  return (count >= 0) ? RTEMS_SUCCESSFUL : RTEMS_UNSATISFIED;
321}
322 
323/*
324 * write bytes to the serial port. Stdout and stderr are the same.
325 */
326 
327rtems_device_driver console_write(
328  rtems_device_major_number major,
329  rtems_device_minor_number minor,
330  void                    * arg
331)
332{
333  int count;
334  int maximum;
335  rtems_libio_rw_args_t *rw_args;
336  char *buffer;
337 
338  rw_args = (rtems_libio_rw_args_t *) arg;
339 
340  buffer = rw_args->buffer;
341  maximum = rw_args->count;
342 
343  for (count = 0; count < maximum; count++) {
344    if ( buffer[ count ] == '\n') {
345      outbyte('\r');
346    }
347    outbyte( buffer[ count ] );
348  }
349 
350  rw_args->bytes_moved = maximum;
351  return 0;
352}
353 
354/*
355 *  IO Control entry point
356 */
357 
358rtems_device_driver console_control(
359  rtems_device_major_number major,
360  rtems_device_minor_number minor,
361  void                    * arg
362)
363{
364  return RTEMS_SUCCESSFUL;
365}
Note: See TracBrowser for help on using the repository browser.