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

4.104.114.84.95
Last change on this file since e54db8b was e54db8b, checked in by Jennifer Averett <Jennifer.Averett@…>, on 05/03/05 at 14:45:12

2005-05-03 Jennifer Averett <jennifer.averett@…>

  • comm/tty_drv.c: Modified to support addition of parameter to ISRs.
  • Property mode set to 100644
File size: 13.6 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.7  2004/04/21 16:01:33  ralf
22 * Remove duplicate white lines.
23 *
24 * Revision 1.6  2004/04/21 10:42:44  ralf
25 * Remove stray white spaces.
26 *
27 * Revision 1.5  2001/08/16 20:52:05  joel
28 * 2001-08-16   Mike Siers <mikes@poliac.com>
29 *
30 *      * comm/tty_drv.c, comm/uart.c: Correct some minor cut and paste bugs.
31 *
32 * Revision 1.4  2001/07/03 17:56:32  joel
33 * 2001-07-03   Mike Seirs <mike@poliac.com>
34 *
35 *      * comm/tty_drv.c, comm/uart.c, comm/uart.h:  Adds the capability
36 *      to use task driven serial I/O to ti386 BSPs. This patch leaves thex
37 *      default I/O mode to be IRQ.  If you want to use task I/O mode,
38 *      then the tty_drv.c file needs to be modified.  Basically, all
39 *      you need to change is the data values of the termios callbacks
40 *      structure.  This callback structure is used in the tty1_open
41 *      and tty2_open functions.  The values you need to set are commented
42 *      out in the source code.
43 *
44 * Revision 1.3  2000/12/05 16:37:38  joel
45 * 2000-12-01   Joel Sherrill <joel@OARcorp.com>
46 *
47 *      * pc386/console/console.c, pc386/console/serial_mouse.c,
48 *      pc386/console/vgainit.c, shared/comm/tty_drv.c: Remove warnings.
49 *
50 * Revision 1.2  2000/10/18 16:10:50  joel
51 * 2000-10-18    Charles-Antoine Gauthier <charles.gauthier@nrc.ca>
52 *
53 *      * comm/i386-stub-glue.c, comm/tty_drv.c, comm/uart.c, comm/uart.h:
54 *      Add the ability to set parity, number of data bits and
55 *      number of stop bits to the existing i386 serial drivers.
56 *
57 * Revision 1.1  2000/08/30 08:18:56  joel
58 * 2000-08-26  Rosimildo da Silva  <rdasilva@connecttel.com>
59 *
60 *      * shared/comm: Added "/dev/ttyS1" & "/dev/ttyS2" support for
61 *      the i386 BSPs.
62 *      * shared/comm/gdb_glue.c: New file.
63 *      * shared/comm/i386_io.c: New file.
64 *      * shared/comm/tty_drv.c: New file.
65 *      * shared/comm/tty_drv.h: New file.
66 *      * shared/comm/Makefile.am: Account for new files.
67 *      * shared/comm/uart.c: Adds support for sending characters to
68 *      another "line discipline."
69 *
70 ****************************************************************************/
71
72#include <stdio.h>
73#include <stdlib.h>
74#include <assert.h>
75
76#include <bsp.h>
77#include <irq.h>
78#include <rtems/libio.h>
79#include <rtems/termiostypes.h>
80#include <termios.h>
81#include <uart.h>
82#include <libcpu/cpuModel.h>
83
84int BSP_poll_read(int);
85
86/* Internal routines */
87static int tty1_conSetAttr( int minor, const struct termios *t);
88static int tty2_conSetAttr( int minor, const struct termios *t);
89static void isr_on(const rtems_irq_connect_data *);
90static void isr_off(const rtems_irq_connect_data *);
91static int  isr_is_on(const rtems_irq_connect_data *);
92
93extern BSP_polling_getchar_function_type BSP_poll_char;
94extern int BSPConsolePort;
95extern void rtems_set_waiting_id_comx( int port,  rtems_id id, rtems_event_set event );
96
97/*
98 * Interrupt structure for tty1
99 */
100static rtems_irq_connect_data tty1_isr_data =
101{
102  BSP_UART_COM1_IRQ,
103  BSP_uart_termios_isr_com1,
104  0,
105  isr_on,
106  isr_off,
107  isr_is_on};
108
109/*
110 * Interrupt structure for tty2
111 */
112static rtems_irq_connect_data tty2_isr_data =
113{
114  BSP_UART_COM2_IRQ,
115  BSP_uart_termios_isr_com2,
116  0,
117  isr_on,
118  isr_off,
119  isr_is_on};
120
121static void
122isr_on(const rtems_irq_connect_data *unused)
123{
124  return;
125}
126
127static void
128isr_off(const rtems_irq_connect_data *unused)
129{
130  return;
131}
132
133static int
134isr_is_on(const rtems_irq_connect_data *irq)
135{
136  return BSP_irq_enabled_at_i8259s(irq->name);
137}
138
139void tty_reserve_resources(rtems_configuration_table *conf)
140{
141  rtems_termios_reserve_resources(conf, 1);
142  return;
143}
144
145/*
146 *  TTYS1 - device driver INITIALIZE entry point.
147 */
148rtems_device_driver
149tty1_initialize(rtems_device_major_number major,
150                   rtems_device_minor_number minor,
151                   void                      *arg)
152{
153  rtems_status_code status;
154
155  /* Check if this port is not been used as console */
156  if( BSPConsolePort == BSP_UART_COM1 )
157  {
158    status = -1;
159    printk("TTYS1: port selected as console.\n");
160    rtems_fatal_error_occurred( status );
161  }
162
163  /*
164   * Set up TERMIOS
165   */
166  rtems_termios_initialize();
167
168  /*
169   * Do device-specific initialization
170   */
171  /* 9600-8-N-1, without hardware flow control */
172  BSP_uart_init( BSP_UART_COM1, 9600, CHR_8_BITS, 0, 0, 0 );
173  status = BSP_install_rtems_irq_handler( &tty1_isr_data );
174  if( !status )
175  {
176    printk("Error installing ttyS1 interrupt handler!\n");
177    rtems_fatal_error_occurred(status);
178  }
179  /*
180   * Register the device
181   */
182  status = rtems_io_register_name ("/dev/ttyS1", major, 0);
183  if (status != RTEMS_SUCCESSFUL)
184  {
185      printk("Error registering ttyS1 device!\n");
186      rtems_fatal_error_occurred (status);
187  }
188  printk("Device: /dev/ttyS1 initialized.\n");
189  return RTEMS_SUCCESSFUL;
190} /* tty_initialize */
191
192static int tty1_last_close(int major, int minor, void *arg)
193{
194  BSP_remove_rtems_irq_handler( &tty1_isr_data );
195  return 0;
196}
197
198/*
199 * TTY1 - device driver OPEN entry point
200 */
201rtems_device_driver
202tty1_open(rtems_device_major_number major,
203                rtems_device_minor_number minor,
204                void                      *arg)
205{
206  rtems_status_code  status;
207#ifndef USE_TASK_DRIVEN
208  static rtems_termios_callbacks cb =
209  {
210    NULL,                        /* firstOpen */
211    tty1_last_close,             /* lastClose */
212    NULL,                        /* poll read */
213    BSP_uart_termios_write_com1, /* write */
214    tty1_conSetAttr,             /* setAttributes */
215    NULL,                        /* stopRemoteTx */
216    NULL,                        /* startRemoteTx */
217    TERMIOS_IRQ_DRIVEN           /* outputUsesInterrupts */
218  };
219#else
220  static rtems_termios_callbacks cb =
221  {
222    NULL,                        /* firstOpen */
223    NULL,                        /* lastClose */
224    BSP_uart_termios_read_com1,  /* poll read */
225    BSP_uart_termios_write_com1, /* write */
226    tty1_conSetAttr,             /* setAttributes */
227    NULL,                        /* stopRemoteTx */
228    NULL,                        /* startRemoteTx */
229    TERMIOS_TASK_DRIVEN          /* outputUsesInterrupts */
230  };
231#endif
232
233  status = rtems_termios_open( major, minor, arg, &cb );
234  if(status != RTEMS_SUCCESSFUL)
235  {
236     printk("Error openning tty1 device\n");
237     return status;
238  }
239
240  /*
241   * Pass data area info down to driver
242   */
243  BSP_uart_termios_set( BSP_UART_COM1,
244                       ((rtems_libio_open_close_args_t *)arg)->iop->data1 );
245  /* Enable interrupts  on channel */
246  BSP_uart_intr_ctrl( BSP_UART_COM1, BSP_UART_INTR_CTRL_TERMIOS);
247  return RTEMS_SUCCESSFUL;
248}
249
250/*
251 * TTY - device driver CLOSE entry point
252 */
253rtems_device_driver
254tty_close(rtems_device_major_number major,
255              rtems_device_minor_number minor,
256              void                      *arg)
257{
258
259  return (rtems_termios_close (arg));
260
261} /* tty_close */
262
263/*
264 * TTY device driver READ entry point.
265 * Read characters from the tty device.
266 */
267rtems_device_driver
268tty_read(rtems_device_major_number major,
269             rtems_device_minor_number minor,
270             void                      *arg)
271{
272  return rtems_termios_read (arg);
273} /* tty_read */
274
275/*
276 * TTY device driver WRITE entry point.
277 * Write characters to the tty device.
278 */
279rtems_device_driver
280tty_write(rtems_device_major_number major,
281              rtems_device_minor_number minor,
282              void                    * arg)
283{
284    return rtems_termios_write (arg);
285
286} /* tty_write */
287
288/*
289 * Handle ioctl request. This is a generic internal
290 * routine to handle both devices.
291 */
292static rtems_device_driver tty_control( int port, void  *arg )
293{
294        rtems_libio_ioctl_args_t *args = arg;
295        switch( args->command )
296        {
297           default:
298      return rtems_termios_ioctl (arg);
299                break;
300   }
301        args->ioctl_return = 0;
302   return RTEMS_SUCCESSFUL;
303}
304
305/*
306 * Handle ioctl request for ttyS1.
307 */
308rtems_device_driver
309tty1_control(rtems_device_major_number major,
310                rtems_device_minor_number minor,
311                void                      * arg
312)
313{
314  return tty_control( BSP_UART_COM1, arg );
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 * TTY2 device driver INITIALIZE entry point.
429 */
430rtems_device_driver
431tty2_initialize(rtems_device_major_number major,
432                   rtems_device_minor_number minor,
433                   void                      *arg)
434{
435  rtems_status_code status;
436
437  /* Check if this port is not been used as console */
438  if( BSPConsolePort == BSP_UART_COM2 )
439  {
440    status = -1;
441    printk("TTY2: port selected as console.\n");
442    rtems_fatal_error_occurred( status );
443  }
444
445  /*
446   * Set up TERMIOS
447   */
448  rtems_termios_initialize();
449
450  /*
451   * Do device-specific initialization
452   */
453  /* 9600-8-N-1, without hardware flow control */
454  BSP_uart_init( BSP_UART_COM2, 9600, CHR_8_BITS, 0, 0, 0);
455  status = BSP_install_rtems_irq_handler( &tty2_isr_data );
456  if( !status )
457  {
458    printk("Error installing serial console interrupt handler!\n");
459    rtems_fatal_error_occurred(status);
460  }
461  /*
462   * Register the device
463   */
464  status = rtems_io_register_name ("/dev/ttyS2", major, 0);
465  if (status != RTEMS_SUCCESSFUL)
466  {
467      printk("Error registering tty2 device!\n");
468      rtems_fatal_error_occurred (status);
469  }
470  printk("Device: /dev/ttyS2 initialized.\n");
471  return RTEMS_SUCCESSFUL;
472} /* tty_initialize */
473
474static int tty2_last_close(int major, int minor, void *arg)
475{
476  BSP_remove_rtems_irq_handler( &tty2_isr_data );
477  return 0;
478}
479
480/*
481 * TTY2 device driver OPEN entry point
482 */
483rtems_device_driver
484tty2_open(rtems_device_major_number major,
485                rtems_device_minor_number minor,
486                void                      *arg)
487{
488  rtems_status_code              status;
489#ifndef USE_TASK_DRIVEN
490  static rtems_termios_callbacks cb =
491  {
492    NULL,                        /* firstOpen */
493    tty2_last_close,             /* lastClose */
494    NULL,                        /* poll read */
495    BSP_uart_termios_write_com2, /* write */
496    tty2_conSetAttr,             /* setAttributes */
497    NULL,                        /* stopRemoteTx */
498    NULL,                        /* startRemoteTx */
499    TERMIOS_IRQ_DRIVEN           /* outputUsesInterrupts */
500  };
501#else
502  static rtems_termios_callbacks cb =
503  {
504    NULL,                        /* firstOpen */
505    NULL,                        /* lastClose */
506    BSP_uart_termios_read_com2,  /* poll read */
507    BSP_uart_termios_write_com2, /* write */
508    tty2_conSetAttr,             /* setAttributes */
509    NULL,                        /* stopRemoteTx */
510    NULL,                        /* startRemoteTx */
511    TERMIOS_TASK_DRIVEN          /* outputUsesInterrupts */
512  };
513#endif
514
515  status = rtems_termios_open (major, minor, arg, &cb);
516  if(status != RTEMS_SUCCESSFUL)
517  {
518     printk("Error openning tty1 device\n");
519     return status;
520  }
521
522  /*
523   * Pass data area info down to driver
524   */
525  BSP_uart_termios_set( BSP_UART_COM2,
526                         ((rtems_libio_open_close_args_t *)arg)->iop->data1 );
527   /* Enable interrupts  on channel */
528  BSP_uart_intr_ctrl( BSP_UART_COM2, BSP_UART_INTR_CTRL_TERMIOS);
529  return RTEMS_SUCCESSFUL;
530}
531
532/*
533 * Handle ioctl request for TTY2
534 */
535rtems_device_driver
536tty2_control(rtems_device_major_number major,
537                rtems_device_minor_number minor,
538                void                      * arg
539)
540{
541   return tty_control( BSP_UART_COM2, arg );
542}
543
544static int
545tty2_conSetAttr( int minor, const struct termios *t)
546{
547  return conSetAttr( BSP_UART_COM2, minor, t );
548}
Note: See TracBrowser for help on using the repository browser.