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

4.104.114.84.9
Last change on this file since cba119c9 was cba119c9, checked in by Ralf Corsepius <ralf.corsepius@…>, on Oct 17, 2005 at 10:34:02 AM

Remove CVS Log

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