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

4.104.114.84.95
Last change on this file since 3299388d was b9ff276c, checked in by Joel Sherrill <joel.sherrill@…>, on 08/16/01 at 20:52:05

2001-08-16 Mike Siers <mikes@…>

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