source: rtems/c/src/lib/libbsp/i386/pc386/console/console.c @ de9edc4

4.104.114.84.95
Last change on this file since de9edc4 was de9edc4, checked in by Joel Sherrill <joel.sherrill@…>, on 08/31/98 at 22:56:20

Patch from Eric Valette <valette@…>:

Here is a brief description of the attached patch :

1) There was a bug in the code for the COM2 serial line driver. Aleksey
gave me a fix that fixes the driver code itself. I would like to thank
him again publicly,

2) I introduced constants in the serial driver code because I had a hard
time reading the meanning of hexadecimal values in the NS data book :)

3)You can now mix printk and printf on serial line (tested on COM2).
There is a #ifdef PRINTK_ON_SERIAL in console.c that enables to have
printk on console while printf on serial line,
4) Removed call to displayCpuInfo because anyway if was at the wrong
place for serial line console (too early). It can anyway be called at
application level,

5) The original printk was unable to display negative integer values
and was also recursive. It now works corectly,

All the modifications have been tested here on the COM2 port from
a PC running RTEMS to a PC running linux,

NB : there is still a bug on PC386 serial line : exit does not flush the
remaining output queue. As this is not a bug in the driver itself but
somewhere in PC386 initialization/termios relationship it will be part
of another patch.

NB2 : As Emmanuel excerced the exception hanlder code, while porting the
SMC driver to the new BSD stack, we found a bug in the exception
handler : it shall not delete the current thread in case we are running
at interrupt level. This will be part of another patch...

  • Property mode set to 100644
File size: 12.3 KB
Line 
1/*-------------------------------------------------------------------------+
2| console.c v1.1 - PC386 BSP - 1997/08/07
3+--------------------------------------------------------------------------+
4| This file contains the PC386 console I/O package.
5+--------------------------------------------------------------------------+
6| (C) Copyright 1997 -
7| - NavIST Group - Real-Time Distributed Systems and Industrial Automation
8|
9| http://pandora.ist.utl.pt
10|
11| Instituto Superior Tecnico * Lisboa * PORTUGAL
12+--------------------------------------------------------------------------+
13| Disclaimer:
14|
15| This file is provided "AS IS" without warranty of any kind, either
16| expressed or implied.
17+--------------------------------------------------------------------------+
18| This code is based on:
19|   console.c,v 1.4 1995/12/19 20:07:23 joel Exp - go32 BSP
20| With the following copyright notice:
21| **************************************************************************
22| *  COPYRIGHT (c) 1989-1998.
23| *  On-Line Applications Research Corporation (OAR).
24| *  Copyright assigned to U.S. Government, 1994.
25| *
26| *  The license and distribution terms for this file may be
27| *  found in found in the file LICENSE in this distribution or at
28| *  http://www.OARcorp.com/rtems/license.html.
29| **************************************************************************
30|
31|  $Id$
32+--------------------------------------------------------------------------*/
33
34#include <stdio.h>
35#include <stdlib.h>
36#include <assert.h>
37
38#include <bsp.h>
39#include <irq.h>
40#include <rtems/libio.h>
41#include <termios.h>
42#include <pc386uart.h>
43#include <libcpu/cpuModel.h>
44
45/*
46 * Possible value for console input/output :
47 *      PC386_CONSOLE_PORT_CONSOLE
48 *      PC386_UART_COM1
49 *      PC386_UART_COM2
50 */
51
52int PC386ConsolePort = PC386_UART_COM2;
53
54static int conSetAttr(int minor, const struct termios *);
55extern BSP_polling_getchar_function_type BSP_poll_char;
56
57/*-------------------------------------------------------------------------+
58| External Prototypes
59+--------------------------------------------------------------------------*/
60extern void     _IBMPC_keyboard_isr(void);
61extern void     _IBMPC_keyboard_isr_on(const rtems_irq_connect_data*);
62extern void     _IBMPC_keyboard_isr_off(const rtems_irq_connect_data*);
63extern int      _IBMPC_keyboard_isr_is_on(const rtems_irq_connect_data*);
64
65static rtems_irq_connect_data console_isr_data = {PC_386_KEYBOARD,
66                                                   _IBMPC_keyboard_isr,
67                                                   _IBMPC_keyboard_isr_on,
68                                                   _IBMPC_keyboard_isr_off,
69                                                   _IBMPC_keyboard_isr_is_on};
70                                                   
71
72extern rtems_boolean _IBMPC_scankey(char *);  /* defined in 'inch.c' */
73extern char BSP_wait_polled_input(void);
74extern void _IBMPC_initVideo(void);
75
76void console_reserve_resources(rtems_configuration_table *conf)
77{
78  if(PC386ConsolePort != PC386_CONSOLE_PORT_CONSOLE)
79    {
80      rtems_termios_reserve_resources(conf, 1);
81    }
82  return;
83}
84
85void __assert(const char *file, int line, const char *msg)
86{
87  static   char exit_msg[] = "EXECUTIVE SHUTDOWN! Any key to reboot...";
88  unsigned char  ch;
89 
90  /*
91   * Note we cannot call exit or printf from here,
92   * assert can fail inside ISR too
93   */
94  printk("\nassert failed: %s: ", file);
95  printk("%d: ", line);
96  printk("%s\n\n", msg);
97  printk(exit_msg);
98  ch = BSP_poll_char();
99  printk("\n\n");
100  rtemsReboot();
101}
102
103
104/*-------------------------------------------------------------------------+
105| Console device driver INITIALIZE entry point.
106+--------------------------------------------------------------------------+
107| Initilizes the I/O console (keyboard + VGA display) driver.
108+--------------------------------------------------------------------------*/
109rtems_device_driver
110console_initialize(rtems_device_major_number major,
111                   rtems_device_minor_number minor,
112                   void                      *arg)
113{
114  rtems_status_code status;
115
116  /* Initialize video */
117  _IBMPC_initVideo();
118
119  if(PC386ConsolePort == PC386_CONSOLE_PORT_CONSOLE)
120    {
121
122      /* Install keyboard interrupt handler */
123      status = pc386_install_rtems_irq_handler(&console_isr_data);
124 
125      if (!status)
126        {
127          printk("Error installing keyboard interrupt handler!\n");
128          rtems_fatal_error_occurred(status);
129        }
130     
131      status = rtems_io_register_name("/dev/console", major, 0);
132      if (status != RTEMS_SUCCESSFUL)
133        {
134          printk("Error registering console device!\n");
135          rtems_fatal_error_occurred(status);
136        }
137      printk("Initialized console on port CONSOLE\n\n");
138    }
139  else
140    {
141      /*
142       * Set up TERMIOS
143       */
144      rtems_termios_initialize ();
145     
146      /*
147       * Do device-specific initialization
148       */
149     
150      /* 9600-8-N-1 */
151      PC386_uart_init(PC386ConsolePort, 9600, 0);
152     
153     
154      /* Set interrupt handler */
155      if(PC386ConsolePort == PC386_UART_COM1)
156        {
157          console_isr_data.name = PC386_UART_COM1_IRQ;
158          console_isr_data.hdl  = PC386_uart_termios_isr_com1;
159         
160        }
161      else
162        {
163          assert(PC386ConsolePort == PC386_UART_COM2);
164          console_isr_data.name = PC386_UART_COM2_IRQ;
165          console_isr_data.hdl  = PC386_uart_termios_isr_com2;
166        }
167
168      status = pc386_install_rtems_irq_handler(&console_isr_data);
169
170      if (!status){
171          printk("Error installing serial console interrupt handler!\n");
172          rtems_fatal_error_occurred(status);
173      }
174      /*
175       * Register the device
176       */
177      status = rtems_io_register_name ("/dev/console", major, 0);
178      if (status != RTEMS_SUCCESSFUL)
179        {
180          printk("Error registering console device!\n");
181          rtems_fatal_error_occurred (status);
182        }
183
184      if(PC386ConsolePort == PC386_UART_COM1)
185        {
186          printk("Initialized console on port COM1 9600-8-N-1\n\n");
187        }
188      else
189        {
190          printk("Initialized console on port COM2 9600-8-N-1\n\n");
191        }
192#define  PRINTK_ON_SERIAL     
193#ifdef PRINTK_ON_SERIAL
194      /*
195       * You can remove the follwoing tree lines if you want to have printk
196       * using the video console for output while printf use serial line.
197       * This may be convenient to debug the serial line driver itself...
198       */
199      printk("Warning : This will be the last message displayed on console\n");
200      BSP_output_char = (BSP_output_char_function_type) BSP_output_char_via_serial;
201      BSP_poll_char   = (BSP_polling_getchar_function_type) BSP_poll_char_via_serial;
202#endif 
203    }
204  return RTEMS_SUCCESSFUL;
205} /* console_initialize */
206
207
208/*-------------------------------------------------------------------------+
209| Console device driver OPEN entry point
210+--------------------------------------------------------------------------*/
211rtems_device_driver
212console_open(rtems_device_major_number major,
213                rtems_device_minor_number minor,
214                void                      *arg)
215{
216  rtems_status_code              status;
217  static rtems_termios_callbacks cb =
218  {
219    NULL,                     /* firstOpen */
220    NULL,                     /* lastClose */
221    NULL,                     /* pollRead */
222    PC386_uart_termios_write_com1, /* write */
223    conSetAttr,               /* setAttributes */
224    NULL,                     /* stopRemoteTx */
225    NULL,                     /* startRemoteTx */
226    1                         /* outputUsesInterrupts */
227  };
228
229  if(PC386ConsolePort == PC386_CONSOLE_PORT_CONSOLE)
230    {
231      return RTEMS_SUCCESSFUL;
232    }
233
234  if(PC386ConsolePort == PC386_UART_COM2)
235    {
236      cb.write = PC386_uart_termios_write_com2;
237    }
238
239  status = rtems_termios_open (major, minor, arg, &cb);
240
241  if(status != RTEMS_SUCCESSFUL)
242    {
243      printk("Error openning console device\n");
244      return status;
245    }
246
247  /*
248   * Pass data area info down to driver
249   */
250  PC386_uart_termios_set(PC386ConsolePort,
251                         ((rtems_libio_open_close_args_t *)arg)->iop->data1);
252 
253  /* Enable interrupts  on channel */
254  PC386_uart_intr_ctrl(PC386ConsolePort, PC386_UART_INTR_CTRL_TERMIOS);
255
256  return RTEMS_SUCCESSFUL;
257}
258
259/*-------------------------------------------------------------------------+
260| Console device driver CLOSE entry point
261+--------------------------------------------------------------------------*/
262rtems_device_driver
263console_close(rtems_device_major_number major,
264              rtems_device_minor_number minor,
265              void                      *arg)
266{
267  rtems_device_driver res = RTEMS_SUCCESSFUL;
268 
269  if(PC386ConsolePort != PC386_CONSOLE_PORT_CONSOLE)
270    {
271      res =  rtems_termios_close (arg);
272    }
273  pc386_remove_rtems_irq_handler (&console_isr_data);
274 
275  return res;
276} /* console_close */
277
278 
279/*-------------------------------------------------------------------------+
280| Console device driver READ entry point.
281+--------------------------------------------------------------------------+
282| Read characters from the I/O console. We only have stdin.
283+--------------------------------------------------------------------------*/
284rtems_device_driver
285console_read(rtems_device_major_number major,
286             rtems_device_minor_number minor,
287             void                      *arg)
288{
289  rtems_libio_rw_args_t *rw_args = (rtems_libio_rw_args_t *)arg;
290  char                  *buffer  = rw_args->buffer;
291  int            count, maximum  = rw_args->count;
292
293  if(PC386ConsolePort != PC386_CONSOLE_PORT_CONSOLE)
294    {
295      return rtems_termios_read (arg);
296    }
297 
298  for (count = 0; count < maximum; count++)
299  {
300    /* Get character */
301    buffer[count] = _IBMPC_inch_sleep();
302
303    /* Echo character to screen */
304    _IBMPC_outch(buffer[count]);
305    if (buffer[count] == '\r')
306      {
307        _IBMPC_outch('\n');  /* CR = CR + LF */
308      }
309
310    if (buffer[count] == '\n' || buffer[count] == '\r')
311    {
312      /* What if this goes past the end of the buffer?  We're hosed. [bhc] */
313      buffer[count++]  = '\n';
314      buffer[count]    = '\0';
315      break;
316    }
317  }
318 
319  rw_args->bytes_moved = count;
320  return ((count >= 0) ? RTEMS_SUCCESSFUL : RTEMS_UNSATISFIED);
321} /* console_read */
322 
323
324/*-------------------------------------------------------------------------+
325| Console device driver WRITE entry point.
326+--------------------------------------------------------------------------+
327| Write characters to the I/O console. Stderr and stdout are the same.
328+--------------------------------------------------------------------------*/
329rtems_device_driver
330console_write(rtems_device_major_number major,
331              rtems_device_minor_number minor,
332              void                    * arg)
333{
334  rtems_libio_rw_args_t *rw_args = (rtems_libio_rw_args_t *)arg;
335  char                  *buffer  = rw_args->buffer;
336  int            count, maximum  = rw_args->count;
337
338  if(PC386ConsolePort != PC386_CONSOLE_PORT_CONSOLE)
339    {
340      return rtems_termios_write (arg);
341    }
342 
343  for (count = 0; count < maximum; count++)
344  {
345    _IBMPC_outch(buffer[count]);
346    if (buffer[count] == '\n')
347      _IBMPC_outch('\r');            /* LF = LF + CR */
348  }
349
350  rw_args->bytes_moved = maximum;
351  return RTEMS_SUCCESSFUL;
352} /* console_write */
353
354
355 
356/*
357 * Handle ioctl request.
358 */
359rtems_device_driver
360console_control(rtems_device_major_number major,
361                rtems_device_minor_number minor,
362                void                      * arg
363)
364{
365  if(PC386ConsolePort != PC386_CONSOLE_PORT_CONSOLE)
366    {
367      return rtems_termios_ioctl (arg);
368    }
369
370  return RTEMS_SUCCESSFUL;
371}
372
373static int
374conSetAttr(int minor, const struct termios *t)
375{
376  int baud;
377
378  switch (t->c_cflag & CBAUD)
379    {
380    case B50:   
381      baud = 50;
382      break;
383    case B75:   
384      baud = 75;       
385      break;
386    case B110: 
387      baud = 110;       
388      break;
389    case B134: 
390      baud = 134;       
391      break;
392    case B150: 
393      baud = 150;       
394      break;
395    case B200:
396      baud = 200;       
397      break;
398    case B300: 
399      baud = 300;
400      break;
401    case B600: 
402      baud = 600;       
403      break;
404    case B1200:
405      baud = 1200;
406      break;
407    case B1800:
408      baud = 1800;     
409      break;
410    case B2400:
411      baud = 2400;
412      break;
413    case B4800:
414      baud = 4800;
415      break;
416    case B9600:
417      baud = 9600;
418      break;
419    case B19200:
420      baud = 19200;
421      break;
422    case B38400:
423      baud = 38400;
424      break;
425    case B57600:       
426      baud = 57600;
427      break;
428    case B115200:
429      baud = 115200;
430      break;
431    default:
432      baud = 0;
433      rtems_fatal_error_occurred (RTEMS_INTERNAL_ERROR);
434      return 0;
435    }
436
437  PC386_uart_set_baud(PC386ConsolePort, baud);
438
439  return 0;
440}
441
442/*
443 * BSP initialization
444 */
445
446BSP_output_char_function_type BSP_output_char =
447                       (BSP_output_char_function_type) _IBMPC_outch;
448
449BSP_polling_getchar_function_type BSP_poll_char = BSP_wait_polled_input;
450
451void BSP_emergency_output_init()
452{
453  _IBMPC_initVideo();
454}
455
456
Note: See TracBrowser for help on using the repository browser.