root/kernel/chr_drv/serial.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. com1_timer
  2. com2_timer
  3. com3_timer
  4. com4_timer
  5. do_rs_write
  6. com1_timeout
  7. com2_timeout
  8. com3_timeout
  9. com4_timeout
  10. init
  11. serial_open
  12. rs_init
  13. rs_write

   1 /*
   2  *  linux/kernel/serial.c
   3  *
   4  *  (C) 1991  Linus Torvalds
   5  */
   6 
   7 /*
   8  *      serial.c
   9  *
  10  * This module implements the rs232 io functions
  11  *      void rs_write(struct tty_struct * queue);
  12  *      void rs_init(void);
  13  * and all interrupts pertaining to serial IO.
  14  */
  15 
  16 #include <linux/tty.h>
  17 #include <linux/sched.h>
  18 #include <linux/timer.h>
  19 #include <asm/system.h>
  20 #include <asm/io.h>
  21 
  22 #define WAKEUP_CHARS (TTY_BUF_SIZE/4)
  23 
  24 extern void rs1_interrupt(void);
  25 extern void rs2_interrupt(void);
  26 
  27 static void com1_timer(void)
     /* [previous][next][first][last][top][bottom][index][help] */
  28 {
  29         TTY_READ_FLUSH(tty_table+64);
  30 }
  31 
  32 static void com2_timer(void)
     /* [previous][next][first][last][top][bottom][index][help] */
  33 {
  34         TTY_READ_FLUSH(tty_table+65);
  35 }
  36 
  37 static void com3_timer(void)
     /* [previous][next][first][last][top][bottom][index][help] */
  38 {
  39         TTY_READ_FLUSH(tty_table+66);
  40 }
  41 
  42 static void com4_timer(void)
     /* [previous][next][first][last][top][bottom][index][help] */
  43 {
  44         TTY_READ_FLUSH(tty_table+67);
  45 }
  46 
  47 static inline void do_rs_write(unsigned int port)
     /* [previous][next][first][last][top][bottom][index][help] */
  48 {
  49         char c;
  50 
  51 #define TTY (tty_table[64+port].write_q)
  52 #define TIMER (SER1_TIMEOUT+port)
  53         cli();
  54         if (!EMPTY(TTY)) {
  55                 outb_p(inb_p(TTY->data+1)|0x02,TTY->data+1);
  56                 if (inb(TTY->data+5) & 0x20) {
  57                         GETCH(TTY,c);
  58                         outb(c,TTY->data);
  59                 }
  60                 timer_table[TIMER].expires = jiffies + 50;
  61                 timer_active |= 1 << TIMER;
  62         } else
  63                 timer_active &= ~(1 << TIMER);
  64         sti();
  65 #undef TIMER
  66 #undef TTY
  67 }
  68 
  69 static void com1_timeout(void)
     /* [previous][next][first][last][top][bottom][index][help] */
  70 {
  71         do_rs_write(0);
  72 }
  73 
  74 static void com2_timeout(void)
     /* [previous][next][first][last][top][bottom][index][help] */
  75 {
  76         do_rs_write(1);
  77 }
  78 
  79 static void com3_timeout(void)
     /* [previous][next][first][last][top][bottom][index][help] */
  80 {
  81         do_rs_write(2);
  82 }
  83 
  84 static void com4_timeout(void)
     /* [previous][next][first][last][top][bottom][index][help] */
  85 {
  86         do_rs_write(3);
  87 }
  88 
  89 static void init(int port)
     /* [previous][next][first][last][top][bottom][index][help] */
  90 {
  91         outb_p(0x80,port+3);    /* set DLAB of line control reg */
  92         outb_p(0x30,port);      /* LS of divisor (48 -> 2400 bps */
  93         outb_p(0x00,port+1);    /* MS of divisor */
  94         outb_p(0x03,port+3);    /* reset DLAB */
  95         outb_p(0x00,port+4);    /* reset DTR,RTS, OUT_2 */
  96         outb_p(0x0d,port+1);    /* enable all intrs but writes */
  97         (void)inb(port);        /* read data port to reset things (?) */
  98 }
  99 
 100 /*
 101  * this routine enables interrupts on 'line', and disables them on
 102  * 'line ^ 2', as they share the same IRQ. Braindamaged AT hardware.
 103  */
 104 void serial_open(unsigned int line)
     /* [previous][next][first][last][top][bottom][index][help] */
 105 {
 106         unsigned short port;
 107         unsigned short port2;
 108 
 109         if (line>3)
 110                 return;
 111         port = tty_table[64+line].read_q->data;
 112         if (!port)
 113                 return;
 114         port2 = tty_table[64+(line ^ 2)].read_q->data;
 115         cli();
 116         if (port2)
 117                 outb_p(0x00,port2+4);
 118         outb_p(0x03,port+3);    /* reset DLAB */
 119         outb_p(0x0f,port+4);    /* set DTR,RTS, OUT_2 */
 120         outb_p(0x0d,port+1);    /* enable all intrs but writes */
 121         inb_p(port+5);
 122         inb_p(port+0);
 123         inb(port+6);
 124         inb(port+2);
 125         sti();
 126 }
 127 
 128 void rs_init(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 129 {
 130 /* SERx_TIMER timers are used for receiving: timeout is always 0 (immediate) */
 131         timer_table[SER1_TIMER].fn = com1_timer;
 132         timer_table[SER1_TIMER].expires = 0;
 133         timer_table[SER2_TIMER].fn = com2_timer;
 134         timer_table[SER2_TIMER].expires = 0;
 135         timer_table[SER3_TIMER].fn = com3_timer;
 136         timer_table[SER3_TIMER].expires = 0;
 137         timer_table[SER4_TIMER].fn = com4_timer;
 138         timer_table[SER4_TIMER].expires = 0;
 139 /* SERx_TIMEOUT timers are used for writing: prevent serial lockups */
 140         timer_table[SER1_TIMEOUT].fn = com1_timeout;
 141         timer_table[SER1_TIMEOUT].expires = 0;
 142         timer_table[SER2_TIMEOUT].fn = com2_timeout;
 143         timer_table[SER2_TIMEOUT].expires = 0;
 144         timer_table[SER3_TIMEOUT].fn = com3_timeout;
 145         timer_table[SER3_TIMEOUT].expires = 0;
 146         timer_table[SER4_TIMEOUT].fn = com4_timeout;
 147         timer_table[SER4_TIMEOUT].expires = 0;
 148         set_intr_gate(0x24,rs1_interrupt);
 149         set_intr_gate(0x23,rs2_interrupt);
 150         init(tty_table[64].read_q->data);
 151         init(tty_table[65].read_q->data);
 152         init(tty_table[66].read_q->data);
 153         init(tty_table[67].read_q->data);
 154         outb(inb_p(0x21)&0xE7,0x21);
 155 }
 156 
 157 /*
 158  * This routine gets called when tty_write has put something into
 159  * the write_queue. It must check wheter the queue is empty, and
 160  * set the interrupt register accordingly
 161  *
 162  *      void _rs_write(struct tty_struct * tty);
 163  */
 164 void rs_write(struct tty_struct * tty)
     /* [previous][next][first][last][top][bottom][index][help] */
 165 {
 166         cli();
 167         if (!EMPTY(tty->write_q))
 168                 outb_p(inb_p(tty->write_q->data+1)|0x02,tty->write_q->data+1);
 169         timer_active |= 15 << SER1_TIMEOUT;
 170         sti();
 171 }

/* [previous][next][first][last][top][bottom][index][help] */