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

5
Last change on this file since c16e54a was 1503c1c3, checked in by Chris Johns <chrisj@…>, on 05/23/16 at 05:24:34

i386/pc386: Fix printk formatting warnings.

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