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

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