source: rtems/c/src/lib/libbsp/i386/shared/comm/tty_drv.c @ 1c77a36

Last change on this file since 1c77a36 was 1c77a36, checked in by Sebastian Huber <sebastian.huber@…>, on Jun 24, 2016 at 12:31:29 PM

bsps: Include missing <rtems/bspIo.h>

  • Property mode set to 100644
File size: 10.4 KB
Line 
1/***************************************************************************
2 *
3 * MODULE DESCRIPTION:
4 * This module implements the RTEMS drivers for the PC serial ports
5 * as /dev/ttyS1 for COM1 and /dev/ttyS2 as COM2. If one of the ports
6 * is used as the console, this driver would fail to initialize.
7 *
8 * This code was based on the console driver. It is based on the
9 * current termios framework. This is just a shell around the
10 * termios support.
11 *
12 * by: Rosimildo da Silva:
13 *     rdasilva@connecttel.com
14 *     http://www.connecttel.com
15 *
16 ****************************************************************************/
17
18
19#include <inttypes.h>
20#include <stdio.h>
21#include <stdlib.h>
22#include <assert.h>
23
24#include <bsp.h>
25#include <bsp/irq.h>
26#include <rtems/bspIo.h>
27#include <rtems/libio.h>
28#include <rtems/termiostypes.h>
29#include <termios.h>
30#include <uart.h>
31#include <libcpu/cpuModel.h>
32#include "tty_drv.h"
33
34int BSP_poll_read(int);
35
36/* Internal routines */
37static int tty1_conSetAttr( int minor, const struct termios *t);
38static int tty2_conSetAttr( int minor, const struct termios *t);
39
40extern BSP_polling_getchar_function_type BSP_poll_char;
41extern int BSPConsolePort;
42extern void rtems_set_waiting_id_comx( int port,  rtems_id id, rtems_event_set event );
43
44/*
45 *  TTYS1 - device driver INITIALIZE entry point.
46 */
47rtems_device_driver
48tty1_initialize(rtems_device_major_number major,
49                   rtems_device_minor_number minor,
50                   void                      *arg)
51{
52  rtems_status_code status;
53
54  /* Check if this port is not been used as console */
55  if( BSPConsolePort == BSP_UART_COM1 )
56  {
57    status = -1;
58    printk("TTYS1: port selected as console.\n");
59    rtems_fatal_error_occurred( status );
60  }
61
62  /*
63   * Set up TERMIOS
64   */
65  rtems_termios_initialize();
66
67  /*
68   * Do device-specific initialization
69   */
70  /* 9600-8-N-1, without hardware flow control */
71  BSP_uart_init( BSP_UART_COM1, 9600, CHR_8_BITS, 0, 0, 0 );
72  status = rtems_interrupt_handler_install(
73    BSP_UART_COM1_IRQ,
74    "tty_drv",
75    RTEMS_INTERRUPT_UNIQUE,
76    BSP_uart_termios_isr_com1,
77    NULL
78  );
79  assert(status == RTEMS_SUCCESSFUL);
80  /*
81   * Register the device
82   */
83  status = rtems_io_register_name ("/dev/ttyS1", major, 0);
84  if (status != RTEMS_SUCCESSFUL)
85  {
86      printk("Error registering ttyS1 device!\n");
87      rtems_fatal_error_occurred (status);
88  }
89  printk("Device: /dev/ttyS1 initialized.\n");
90  return RTEMS_SUCCESSFUL;
91} /* tty_initialize */
92
93static int tty1_last_close(int major, int minor, void *arg)
94{
95  rtems_status_code status;
96
97  status = rtems_interrupt_handler_remove(
98    BSP_UART_COM1_IRQ,
99    BSP_uart_termios_isr_com1,
100    NULL
101  );
102  assert(status == RTEMS_SUCCESSFUL);
103  return 0;
104}
105
106/*
107 * TTY1 - device driver OPEN entry point
108 */
109rtems_device_driver
110tty1_open(rtems_device_major_number major,
111                rtems_device_minor_number minor,
112                void                      *arg)
113{
114  rtems_status_code  status;
115#ifndef USE_TASK_DRIVEN
116  static rtems_termios_callbacks cb =
117  {
118    NULL,                        /* firstOpen */
119    tty1_last_close,             /* lastClose */
120    NULL,                        /* poll read */
121    BSP_uart_termios_write_com1, /* write */
122    tty1_conSetAttr,             /* setAttributes */
123    NULL,                        /* stopRemoteTx */
124    NULL,                        /* startRemoteTx */
125    TERMIOS_IRQ_DRIVEN           /* outputUsesInterrupts */
126  };
127#else
128  static rtems_termios_callbacks cb =
129  {
130    NULL,                        /* firstOpen */
131    NULL,                        /* lastClose */
132    BSP_uart_termios_read_com1,  /* poll read */
133    BSP_uart_termios_write_com1, /* write */
134    tty1_conSetAttr,             /* setAttributes */
135    NULL,                        /* stopRemoteTx */
136    NULL,                        /* startRemoteTx */
137    TERMIOS_TASK_DRIVEN          /* outputUsesInterrupts */
138  };
139#endif
140
141  status = rtems_termios_open( major, minor, arg, &cb );
142  if(status != RTEMS_SUCCESSFUL)
143  {
144     printk("Error openning tty1 device\n");
145     return status;
146  }
147
148  /*
149   * Pass data area info down to driver
150   */
151  BSP_uart_termios_set( BSP_UART_COM1,
152                       ((rtems_libio_open_close_args_t *)arg)->iop->data1 );
153  /* Enable interrupts  on channel */
154  BSP_uart_intr_ctrl( BSP_UART_COM1, BSP_UART_INTR_CTRL_TERMIOS);
155  return RTEMS_SUCCESSFUL;
156}
157
158/*
159 * TTY - device driver CLOSE entry point
160 */
161rtems_device_driver
162tty_close(rtems_device_major_number major,
163              rtems_device_minor_number minor,
164              void                      *arg)
165{
166
167  return (rtems_termios_close (arg));
168
169} /* tty_close */
170
171/*
172 * TTY device driver READ entry point.
173 * Read characters from the tty device.
174 */
175rtems_device_driver
176tty_read(rtems_device_major_number major,
177             rtems_device_minor_number minor,
178             void                      *arg)
179{
180  return rtems_termios_read (arg);
181} /* tty_read */
182
183/*
184 * TTY device driver WRITE entry point.
185 * Write characters to the tty device.
186 */
187rtems_device_driver
188tty_write(rtems_device_major_number major,
189              rtems_device_minor_number minor,
190              void                    * arg)
191{
192    return rtems_termios_write (arg);
193
194} /* tty_write */
195
196/*
197 * Handle ioctl request. This is a generic internal
198 * routine to handle both devices.
199 */
200static rtems_device_driver tty_control( int port, void  *arg )
201{
202        rtems_libio_ioctl_args_t *args = arg;
203        switch( args->command )
204        {
205           default:
206      return rtems_termios_ioctl (arg);
207                break;
208   }
209        args->ioctl_return = 0;
210   return RTEMS_SUCCESSFUL;
211}
212
213/*
214 * Handle ioctl request for ttyS1.
215 */
216rtems_device_driver
217tty1_control(rtems_device_major_number major,
218                rtems_device_minor_number minor,
219                void                      * arg
220)
221{
222  return tty_control( BSP_UART_COM1, arg );
223}
224
225static int
226conSetAttr(int port, int minor, const struct termios *t)
227{
228  unsigned long baud, databits, parity, stopbits;
229
230  baud = rtems_termios_baud_to_number(t->c_cflag & CBAUD);
231  if ( baud > 115200 )
232    rtems_fatal_error_occurred (RTEMS_INTERNAL_ERROR);
233
234  if (t->c_cflag & PARENB) {
235    /* Parity is enabled */
236    if (t->c_cflag & PARODD) {
237      /* Parity is odd */
238      parity = PEN;
239    }
240    else {
241      /* Parity is even */
242      parity = PEN | EPS;
243    }
244  }
245  else {
246    /* No parity */
247    parity = 0;
248  }
249
250  switch (t->c_cflag & CSIZE) {
251    case CS5: databits = CHR_5_BITS; break;
252    case CS6: databits = CHR_6_BITS; break;
253    case CS7: databits = CHR_7_BITS; break;
254    default:  /* just to avoid warnings -- all cases are covered */
255    case CS8: databits = CHR_8_BITS; break;
256  }
257
258  if (t->c_cflag & CSTOPB) {
259    /* 2 stop bits */
260    stopbits = STB;
261  }
262  else {
263    /* 1 stop bit */
264    stopbits = 0;
265  }
266
267  printk("Setting attributes, port=%X, baud=%" PRId32 ", linemode = 0x%02" PRIx32 "\n",
268         port, baud, databits | parity | stopbits );
269  BSP_uart_set_attributes(port, baud, databits, parity, stopbits);
270  return 0;
271}
272
273/*
274 * Handle ioctl request for ttyS2.
275 */
276static int
277tty1_conSetAttr( int minor, const struct termios *t)
278{
279  return conSetAttr( BSP_UART_COM1, minor, t );
280}
281
282/*
283 * TTY2 device driver INITIALIZE entry point.
284 */
285rtems_device_driver
286tty2_initialize(rtems_device_major_number major,
287                   rtems_device_minor_number minor,
288                   void                      *arg)
289{
290  rtems_status_code status;
291
292  /* Check if this port is not been used as console */
293  if( BSPConsolePort == BSP_UART_COM2 )
294  {
295    status = -1;
296    printk("TTY2: port selected as console.\n");
297    rtems_fatal_error_occurred( status );
298  }
299
300  /*
301   * Set up TERMIOS
302   */
303  rtems_termios_initialize();
304
305  /*
306   * Do device-specific initialization
307   */
308  /* 9600-8-N-1, without hardware flow control */
309  BSP_uart_init( BSP_UART_COM2, 9600, CHR_8_BITS, 0, 0, 0);
310  status = rtems_interrupt_handler_install(
311    BSP_UART_COM2_IRQ,
312    "tty_drv",
313    RTEMS_INTERRUPT_UNIQUE,
314    BSP_uart_termios_isr_com2,
315    NULL
316  );
317  assert(status == RTEMS_SUCCESSFUL);
318
319  /*
320   * Register the device
321   */
322  status = rtems_io_register_name ("/dev/ttyS2", major, 0);
323  if (status != RTEMS_SUCCESSFUL)
324  {
325      printk("Error registering tty2 device!\n");
326      rtems_fatal_error_occurred (status);
327  }
328  printk("Device: /dev/ttyS2 initialized.\n");
329  return RTEMS_SUCCESSFUL;
330} /* tty_initialize */
331
332static int tty2_last_close(int major, int minor, void *arg)
333{
334  rtems_status_code status;
335
336  status = rtems_interrupt_handler_remove(
337    BSP_UART_COM2_IRQ,
338    BSP_uart_termios_isr_com2,
339    NULL
340  );
341  assert(status == RTEMS_SUCCESSFUL);
342  return 0;
343}
344
345/*
346 * TTY2 device driver OPEN entry point
347 */
348rtems_device_driver
349tty2_open(rtems_device_major_number major,
350                rtems_device_minor_number minor,
351                void                      *arg)
352{
353  rtems_status_code              status;
354#ifndef USE_TASK_DRIVEN
355  static rtems_termios_callbacks cb =
356  {
357    NULL,                        /* firstOpen */
358    tty2_last_close,             /* lastClose */
359    NULL,                        /* poll read */
360    BSP_uart_termios_write_com2, /* write */
361    tty2_conSetAttr,             /* setAttributes */
362    NULL,                        /* stopRemoteTx */
363    NULL,                        /* startRemoteTx */
364    TERMIOS_IRQ_DRIVEN           /* outputUsesInterrupts */
365  };
366#else
367  static rtems_termios_callbacks cb =
368  {
369    NULL,                        /* firstOpen */
370    NULL,                        /* lastClose */
371    BSP_uart_termios_read_com2,  /* poll read */
372    BSP_uart_termios_write_com2, /* write */
373    tty2_conSetAttr,             /* setAttributes */
374    NULL,                        /* stopRemoteTx */
375    NULL,                        /* startRemoteTx */
376    TERMIOS_TASK_DRIVEN          /* outputUsesInterrupts */
377  };
378#endif
379
380  status = rtems_termios_open (major, minor, arg, &cb);
381  if(status != RTEMS_SUCCESSFUL)
382  {
383     printk("Error openning tty1 device\n");
384     return status;
385  }
386
387  /*
388   * Pass data area info down to driver
389   */
390  BSP_uart_termios_set( BSP_UART_COM2,
391                         ((rtems_libio_open_close_args_t *)arg)->iop->data1 );
392   /* Enable interrupts  on channel */
393  BSP_uart_intr_ctrl( BSP_UART_COM2, BSP_UART_INTR_CTRL_TERMIOS);
394  return RTEMS_SUCCESSFUL;
395}
396
397/*
398 * Handle ioctl request for TTY2
399 */
400rtems_device_driver
401tty2_control(rtems_device_major_number major,
402                rtems_device_minor_number minor,
403                void                      * arg
404)
405{
406   return tty_control( BSP_UART_COM2, arg );
407}
408
409static int
410tty2_conSetAttr( int minor, const struct termios *t)
411{
412  return conSetAttr( BSP_UART_COM2, minor, t );
413}
Note: See TracBrowser for help on using the repository browser.