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

4.104.114.84.95
Last change on this file since 6128a4a was 6128a4a, checked in by Ralf Corsepius <ralf.corsepius@…>, on 04/21/04 at 10:43:04

Remove stray white spaces.

  • Property mode set to 100644
File size: 13.5 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 * MODIFICATION/HISTORY:
19 *
20 * $Log$
21 * Revision 1.5  2001/08/16 20:52:05  joel
22 * 2001-08-16   Mike Siers <mikes@poliac.com>
23 *
24 *      * comm/tty_drv.c, comm/uart.c: Correct some minor cut and paste bugs.
25 *
26 * Revision 1.4  2001/07/03 17:56:32  joel
27 * 2001-07-03   Mike Seirs <mike@poliac.com>
28 *
29 *      * comm/tty_drv.c, comm/uart.c, comm/uart.h:  Adds the capability
30 *      to use task driven serial I/O to ti386 BSPs. This patch leaves thex
31 *      default I/O mode to be IRQ.  If you want to use task I/O mode,
32 *      then the tty_drv.c file needs to be modified.  Basically, all
33 *      you need to change is the data values of the termios callbacks
34 *      structure.  This callback structure is used in the tty1_open
35 *      and tty2_open functions.  The values you need to set are commented
36 *      out in the source code.
37 *
38 * Revision 1.3  2000/12/05 16:37:38  joel
39 * 2000-12-01   Joel Sherrill <joel@OARcorp.com>
40 *
41 *      * pc386/console/console.c, pc386/console/serial_mouse.c,
42 *      pc386/console/vgainit.c, shared/comm/tty_drv.c: Remove warnings.
43 *
44 * Revision 1.2  2000/10/18 16:10:50  joel
45 * 2000-10-18    Charles-Antoine Gauthier <charles.gauthier@nrc.ca>
46 *
47 *      * comm/i386-stub-glue.c, comm/tty_drv.c, comm/uart.c, comm/uart.h:
48 *      Add the ability to set parity, number of data bits and
49 *      number of stop bits to the existing i386 serial drivers.
50 *
51 * Revision 1.1  2000/08/30 08:18:56  joel
52 * 2000-08-26  Rosimildo da Silva  <rdasilva@connecttel.com>
53 *
54 *      * shared/comm: Added "/dev/ttyS1" & "/dev/ttyS2" support for
55 *      the i386 BSPs.
56 *      * shared/comm/gdb_glue.c: New file.
57 *      * shared/comm/i386_io.c: New file.
58 *      * shared/comm/tty_drv.c: New file.
59 *      * shared/comm/tty_drv.h: New file.
60 *      * shared/comm/Makefile.am: Account for new files.
61 *      * shared/comm/uart.c: Adds support for sending characters to
62 *      another "line discipline."
63 *
64 ****************************************************************************/
65
66#include <stdio.h>
67#include <stdlib.h>
68#include <assert.h>
69
70#include <bsp.h>
71#include <irq.h>
72#include <rtems/libio.h>
73#include <rtems/termiostypes.h>
74#include <termios.h>
75#include <uart.h>
76#include <libcpu/cpuModel.h>
77
78int BSP_poll_read(int);
79
80/* Internal routines */
81static int tty1_conSetAttr( int minor, const struct termios *t);
82static int tty2_conSetAttr( int minor, const struct termios *t);
83static void isr_on(const rtems_irq_connect_data *);
84static void isr_off(const rtems_irq_connect_data *);
85static int  isr_is_on(const rtems_irq_connect_data *);
86
87
88extern BSP_polling_getchar_function_type BSP_poll_char;
89extern int BSPConsolePort;
90extern void rtems_set_waiting_id_comx( int port,  rtems_id id, rtems_event_set event );
91
92
93/*
94 * Interrupt structure for tty1
95 */
96static rtems_irq_connect_data tty1_isr_data =
97{
98  BSP_UART_COM1_IRQ,
99  BSP_uart_termios_isr_com1,
100  isr_on,
101  isr_off,
102  isr_is_on};
103
104/*
105 * Interrupt structure for tty2
106 */
107static rtems_irq_connect_data tty2_isr_data =
108{
109  BSP_UART_COM2_IRQ,
110  BSP_uart_termios_isr_com2,
111  isr_on,
112  isr_off,
113  isr_is_on};
114
115static void
116isr_on(const rtems_irq_connect_data *unused)
117{
118  return;
119}
120
121static void
122isr_off(const rtems_irq_connect_data *unused)
123{
124  return;
125}
126
127static int
128isr_is_on(const rtems_irq_connect_data *irq)
129{
130  return BSP_irq_enabled_at_i8259s(irq->name);
131}
132
133void tty_reserve_resources(rtems_configuration_table *conf)
134{
135  rtems_termios_reserve_resources(conf, 1);
136  return;
137}
138
139/*
140 *  TTYS1 - device driver INITIALIZE entry point.
141 */
142rtems_device_driver
143tty1_initialize(rtems_device_major_number major,
144                   rtems_device_minor_number minor,
145                   void                      *arg)
146{
147  rtems_status_code status;
148
149  /* Check if this port is not been used as console */
150  if( BSPConsolePort == BSP_UART_COM1 )
151  {
152    status = -1;
153    printk("TTYS1: port selected as console.\n");
154    rtems_fatal_error_occurred( status );
155  }
156
157  /*
158   * Set up TERMIOS
159   */
160  rtems_termios_initialize();
161
162  /*
163   * Do device-specific initialization
164   */
165  /* 9600-8-N-1, without hardware flow control */
166  BSP_uart_init( BSP_UART_COM1, 9600, CHR_8_BITS, 0, 0, 0 );
167  status = BSP_install_rtems_irq_handler( &tty1_isr_data );
168  if( !status )
169  {
170    printk("Error installing ttyS1 interrupt handler!\n");
171    rtems_fatal_error_occurred(status);
172  }
173  /*
174   * Register the device
175   */
176  status = rtems_io_register_name ("/dev/ttyS1", major, 0);
177  if (status != RTEMS_SUCCESSFUL)
178  {
179      printk("Error registering ttyS1 device!\n");
180      rtems_fatal_error_occurred (status);
181  }
182  printk("Device: /dev/ttyS1 initialized.\n");
183  return RTEMS_SUCCESSFUL;
184} /* tty_initialize */
185
186
187static int tty1_last_close(int major, int minor, void *arg)
188{
189  BSP_remove_rtems_irq_handler( &tty1_isr_data );
190  return 0;
191}
192
193/*
194 * TTY1 - device driver OPEN entry point
195 */
196rtems_device_driver
197tty1_open(rtems_device_major_number major,
198                rtems_device_minor_number minor,
199                void                      *arg)
200{
201  rtems_status_code  status;
202#ifndef USE_TASK_DRIVEN
203  static rtems_termios_callbacks cb =
204  {
205    NULL,                        /* firstOpen */
206    tty1_last_close,             /* lastClose */
207    NULL,                        /* poll read */
208    BSP_uart_termios_write_com1, /* write */
209    tty1_conSetAttr,             /* setAttributes */
210    NULL,                        /* stopRemoteTx */
211    NULL,                        /* startRemoteTx */
212    TERMIOS_IRQ_DRIVEN           /* outputUsesInterrupts */
213  };
214#else
215  static rtems_termios_callbacks cb =
216  {
217    NULL,                        /* firstOpen */
218    NULL,                        /* lastClose */
219    BSP_uart_termios_read_com1,  /* poll read */
220    BSP_uart_termios_write_com1, /* write */
221    tty1_conSetAttr,             /* setAttributes */
222    NULL,                        /* stopRemoteTx */
223    NULL,                        /* startRemoteTx */
224    TERMIOS_TASK_DRIVEN          /* outputUsesInterrupts */
225  };
226#endif
227
228  status = rtems_termios_open( major, minor, arg, &cb );
229  if(status != RTEMS_SUCCESSFUL)
230  {
231     printk("Error openning tty1 device\n");
232     return status;
233  }
234
235  /*
236   * Pass data area info down to driver
237   */
238  BSP_uart_termios_set( BSP_UART_COM1,
239                       ((rtems_libio_open_close_args_t *)arg)->iop->data1 );
240  /* Enable interrupts  on channel */
241  BSP_uart_intr_ctrl( BSP_UART_COM1, BSP_UART_INTR_CTRL_TERMIOS);
242  return RTEMS_SUCCESSFUL;
243}
244
245/*
246 * TTY - device driver CLOSE entry point
247 */
248rtems_device_driver
249tty_close(rtems_device_major_number major,
250              rtems_device_minor_number minor,
251              void                      *arg)
252{
253
254  return (rtems_termios_close (arg));
255
256} /* tty_close */
257
258
259/*
260 * TTY device driver READ entry point.
261 * Read characters from the tty device.
262 */
263rtems_device_driver
264tty_read(rtems_device_major_number major,
265             rtems_device_minor_number minor,
266             void                      *arg)
267{
268  return rtems_termios_read (arg);
269} /* tty_read */
270
271
272/*
273 * TTY device driver WRITE entry point.
274 * Write characters to the tty device.
275 */
276rtems_device_driver
277tty_write(rtems_device_major_number major,
278              rtems_device_minor_number minor,
279              void                    * arg)
280{
281    return rtems_termios_write (arg);
282
283} /* tty_write */
284
285/*
286 * Handle ioctl request. This is a generic internal
287 * routine to handle both devices.
288 */
289static rtems_device_driver tty_control( int port, void  *arg )
290{
291        rtems_libio_ioctl_args_t *args = arg;
292        switch( args->command )
293        {
294           default:
295      return rtems_termios_ioctl (arg);
296                break;
297   }
298        args->ioctl_return = 0;
299   return RTEMS_SUCCESSFUL;
300}
301
302
303
304/*
305 * Handle ioctl request for ttyS1.
306 */
307rtems_device_driver
308tty1_control(rtems_device_major_number major,
309                rtems_device_minor_number minor,
310                void                      * arg
311)
312{
313  return tty_control( BSP_UART_COM1, arg );
314}
315
316
317static int
318conSetAttr(int port, int minor, const struct termios *t)
319{
320  unsigned long baud, databits, parity, stopbits;
321
322  switch (t->c_cflag & CBAUD)
323    {
324    case B50:
325      baud = 50;
326      break;
327    case B75:
328      baud = 75;
329      break;
330    case B110:
331      baud = 110;
332      break;
333    case B134:
334      baud = 134;
335      break;
336    case B150:
337      baud = 150;
338      break;
339    case B200:
340      baud = 200;
341      break;
342    case B300:
343      baud = 300;
344      break;
345    case B600:
346      baud = 600;
347      break;
348    case B1200:
349      baud = 1200;
350      break;
351    case B1800:
352      baud = 1800;
353      break;
354    case B2400:
355      baud = 2400;
356      break;
357    case B4800:
358      baud = 4800;
359      break;
360    case B9600:
361      baud = 9600;
362      break;
363    case B19200:
364      baud = 19200;
365      break;
366    case B38400:
367      baud = 38400;
368      break;
369    case B57600:
370      baud = 57600;
371      break;
372    case B115200:
373      baud = 115200;
374      break;
375    default:
376      baud = 0;
377      rtems_fatal_error_occurred (RTEMS_INTERNAL_ERROR);
378      return 0;
379    }
380  if (t->c_cflag & PARENB) {
381    /* Parity is enabled */
382    if (t->c_cflag & PARODD) {
383      /* Parity is odd */
384      parity = PEN;
385    }
386    else {
387      /* Parity is even */
388      parity = PEN | EPS;
389    }
390  }
391  else {
392    /* No parity */
393    parity = 0;
394  }
395
396  switch (t->c_cflag & CSIZE) {
397    case CS5: databits = CHR_5_BITS; break;
398    case CS6: databits = CHR_6_BITS; break;
399    case CS7: databits = CHR_7_BITS; break;
400    default:  /* just to avoid warnings -- all cases are covered */
401    case CS8: databits = CHR_8_BITS; break;
402  }
403
404  if (t->c_cflag & CSTOPB) {
405    /* 2 stop bits */
406    stopbits = STB;
407  }
408  else {
409    /* 1 stop bit */
410    stopbits = 0;
411  }
412
413  printk("Setting attributes, port=%X, baud=%d, linemode = 0x%02x\n", port, baud, databits | parity | stopbits );
414  BSP_uart_set_attributes(port, baud, databits, parity, stopbits);
415  return 0;
416}
417
418/*
419 * Handle ioctl request for ttyS2.
420 */
421static int
422tty1_conSetAttr( int minor, const struct termios *t)
423{
424  return conSetAttr( BSP_UART_COM1, minor, t );
425}
426
427
428
429/*
430 * TTY2 device driver INITIALIZE entry point.
431 */
432rtems_device_driver
433tty2_initialize(rtems_device_major_number major,
434                   rtems_device_minor_number minor,
435                   void                      *arg)
436{
437  rtems_status_code status;
438
439  /* Check if this port is not been used as console */
440  if( BSPConsolePort == BSP_UART_COM2 )
441  {
442    status = -1;
443    printk("TTY2: port selected as console.\n");
444    rtems_fatal_error_occurred( status );
445  }
446
447  /*
448   * Set up TERMIOS
449   */
450  rtems_termios_initialize();
451
452  /*
453   * Do device-specific initialization
454   */
455  /* 9600-8-N-1, without hardware flow control */
456  BSP_uart_init( BSP_UART_COM2, 9600, CHR_8_BITS, 0, 0, 0);
457  status = BSP_install_rtems_irq_handler( &tty2_isr_data );
458  if( !status )
459  {
460    printk("Error installing serial console interrupt handler!\n");
461    rtems_fatal_error_occurred(status);
462  }
463  /*
464   * Register the device
465   */
466  status = rtems_io_register_name ("/dev/ttyS2", major, 0);
467  if (status != RTEMS_SUCCESSFUL)
468  {
469      printk("Error registering tty2 device!\n");
470      rtems_fatal_error_occurred (status);
471  }
472  printk("Device: /dev/ttyS2 initialized.\n");
473  return RTEMS_SUCCESSFUL;
474} /* tty_initialize */
475
476
477static int tty2_last_close(int major, int minor, void *arg)
478{
479  BSP_remove_rtems_irq_handler( &tty2_isr_data );
480  return 0;
481}
482
483/*
484 * TTY2 device driver OPEN entry point
485 */
486rtems_device_driver
487tty2_open(rtems_device_major_number major,
488                rtems_device_minor_number minor,
489                void                      *arg)
490{
491  rtems_status_code              status;
492#ifndef USE_TASK_DRIVEN
493  static rtems_termios_callbacks cb =
494  {
495    NULL,                        /* firstOpen */
496    tty2_last_close,             /* lastClose */
497    NULL,                        /* poll read */
498    BSP_uart_termios_write_com2, /* write */
499    tty2_conSetAttr,             /* setAttributes */
500    NULL,                        /* stopRemoteTx */
501    NULL,                        /* startRemoteTx */
502    TERMIOS_IRQ_DRIVEN           /* outputUsesInterrupts */
503  };
504#else
505  static rtems_termios_callbacks cb =
506  {
507    NULL,                        /* firstOpen */
508    NULL,                        /* lastClose */
509    BSP_uart_termios_read_com2,  /* poll read */
510    BSP_uart_termios_write_com2, /* write */
511    tty2_conSetAttr,             /* setAttributes */
512    NULL,                        /* stopRemoteTx */
513    NULL,                        /* startRemoteTx */
514    TERMIOS_TASK_DRIVEN          /* outputUsesInterrupts */
515  };
516#endif
517
518  status = rtems_termios_open (major, minor, arg, &cb);
519  if(status != RTEMS_SUCCESSFUL)
520  {
521     printk("Error openning tty1 device\n");
522     return status;
523  }
524
525  /*
526   * Pass data area info down to driver
527   */
528  BSP_uart_termios_set( BSP_UART_COM2,
529                         ((rtems_libio_open_close_args_t *)arg)->iop->data1 );
530   /* Enable interrupts  on channel */
531  BSP_uart_intr_ctrl( BSP_UART_COM2, BSP_UART_INTR_CTRL_TERMIOS);
532  return RTEMS_SUCCESSFUL;
533}
534
535/*
536 * Handle ioctl request for TTY2
537 */
538rtems_device_driver
539tty2_control(rtems_device_major_number major,
540                rtems_device_minor_number minor,
541                void                      * arg
542)
543{
544   return tty_control( BSP_UART_COM2, arg );
545}
546
547static int
548tty2_conSetAttr( int minor, const struct termios *t)
549{
550  return conSetAttr( BSP_UART_COM2, minor, t );
551}
Note: See TracBrowser for help on using the repository browser.