/* * linux/kernel/serial.c * * (C) 1991 Linus Torvalds */
/* * serial.c * * This module implements the rs232 io functions * void rs_write(struct tty_struct * queue); * void rs_init(void); * and all interrupts pertaining to serial IO. */
#include <linux/tty.h> #include <linux/sched.h> #include <asm/system.h> #include <asm/io.h>
#define WAKEUP_CHARS (TTY_BUF_SIZE/4)//当写队列中含有WAKEUP_CHARS 个字符时,就开始发送(向串口发送)
extern void rs1_interrupt(void);// 串行口1 的中断处理程序(rs_io.s, 34)。
extern void rs2_interrupt(void);// 串行口2 的中断处理程序(rs_io.s, 38)。
static void init(int port)//// 初始化串行端口,port串行端口基地址, port: 串口1 - 0x3F8,串口2 - 0x2F8。
{ outb_p(0x80,port+3); /* set DLAB of line control reg *//* 线路控制寄存器LCR,设置线路控制寄存器的DLAB 位(位7) */ outb_p(0x30,port); /* LS of divisor (48 -> 2400 bps *//*除数锁存寄存器LSB, 发送波特率因子低字节,0x30->2400bps */ outb_p(0x00,port+1); /* MS of divisor *//* 除数锁存寄存器MSB,发送波特率因子高字节,0x00 */ outb_p(0x03,port+3); /* reset DLAB *//* 线路控制寄存器LCR,复位DLAB 位,数据位为8 位 */ outb_p(0x0b,port+4); /* set DTR,RTS, OUT_2 *//*MODEN控制寄存器, 设置DTR,RTS,辅助用户输出2 */ outb_p(0x0d,port+1); /* enable all intrs but writes *//*中断充许寄存器IER, 除了写(写保持空)以外,允许所有中断源中断 */ (void)inb(port); /* read data port to reset things (?) *//* 读数据口,以进行复位操作(?) */ }
void rs_init(void)//// 初始化串行中断程序和串行接口
{ set_intr_gate(0x24,rs1_interrupt);// 设置串行口1 的中断门向量(硬件IRQ4 信号)。
set_intr_gate(0x23,rs2_interrupt);// 设置串行口2 的中断门向量(硬件IRQ3 信号)。
init(tty_table[1].read_q.data);// 初始化串行口1
init(tty_table[2].read_q.data);// 初始化串行口2
outb(inb_p(0x21)&0xE7,0x21);// 允许主8259A 芯片的IRQ3,IRQ4 中断信号请求
}
/* * This routine gets called when tty_write has put something into * the write_queue. It must check wheter the queue is empty, and * set the interrupt register accordingly * * void _rs_write(struct tty_struct * tty); */ void rs_write(struct tty_struct * tty)//串口数据发送函数
{ cli();//关中断
if (!EMPTY(tty->write_q))//TTY写队列不为空
outb(inb_p(tty->write_q.data+1)|0x02,tty->write_q.data+1);//则从0x3f9(或0x2f9) 首先读取中断允许寄存器内容,添上发送保持寄存器中断允许标志(位1)后,再写回该寄存器,从而引发中断,其中断处理过程由rs_io.s来完成
sti();//开中断
}
|