⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rs_io.s

📁 linux的内核源码
💻 S
字号:
/*
 *	rs_io.s
 *
 * This module implements the rs232 io interrupts.
 */

.text
.globl _rs1_interrupt,_rs2_interrupt

size	= 1024				/* must be power of two !
					   and must match the value
					   in tty_io.c!!! */

/* these are the offsets into the read/write buffer structures */
rs_addr = 0
head = 4
tail = 8
proc_list = 12
buf = 16

startup	= 256		/* chars left in write queue when we restart it */

/*
 * These are the actual interrupt routines. They look where
 * the interrupt is coming from, and take appropriate action.
 */
.align 2
_rs1_interrupt:
	pushl $_table_list+8		//这里在tty_io.c中定义的table_list结构的基地址+8就是偏移量8个字节(就是table_list[1].read_q结构的首地址),这个结构的第一个成员是data(0x3f8),此行就是将它入栈
	jmp rs_int
.align 2
_rs2_interrupt:
	pushl $_table_list+16
rs_int:
	pushl %edx
	pushl %ecx
	pushl %ebx
	pushl %eax
	push %es
	push %ds		/* as this is an interrupt, we cannot */
	pushl $0x10		/* know that bs is ok. Load it */
	pop %ds			//将ds设为0X10
	pushl $0x10
	pop %es			//将es设为0X10
	movl 24(%esp),%edx		//将指针指向$_table_list+8的地址0x3F8(esp+24)
	movl (%edx),%edx		//将地址上的值送入edx,值为0x3F8
	movl rs_addr(%edx),%edx
	addl $2,%edx		/* interrupt ident. reg */		//=0X3FA
rep_int:
	xorl %eax,%eax
	inb %dx,%al			//UART寄存器2(中断标识寄存器)
	testb $1,%al			//如果0位为1,那么无中断挂起,结束
	jne end
	cmpb $6,%al		/* this shouldn't happen, but ... */	//如果al>6,就是第3位设为1,就是字符超时,结束
	ja end
	movl 24(%esp),%ecx		//将$_table_list+8(table_list[1].read_q)的基地址送入ecx
	pushl %edx
	subl $2,%edx			//0X3F8
	call jmp_table(,%eax,2)		/* NOTE! not *4, bit0 is 0 already */
	popl %edx
	jmp rep_int			//循环,不停的检查是否有中断发生
end:	movb $0x20,%al		//向端口20发送命令20是结束中断
	outb %al,$0x20		/* EOI */
	pop %ds
	pop %es
	popl %eax
	popl %ebx
	popl %ecx
	popl %edx
	addl $4,%esp		# jump over _table_list entry
	iret

jmp_table:
	.long modem_status,write_char,read_char,line_status

.align 2
modem_status:				//读取寄存器状态使此0X3F8+6的寄存器的0—3位设置为0
	addl $6,%edx		/* clear intr by reading modem status reg */
	inb %dx,%al
	ret

.align 2
line_status:				//读取寄存器状态,使此0X3F8+5的寄存器设置为60H,表示没有错误,传送缓冲区为空
	addl $5,%edx		/* clear intr by reading line status reg. */
	inb %dx,%al
	ret

.align 2
read_char:
	inb %dx,%al			//0X3F8寄存器输入是获得接收缓冲区数据字节
	movl %ecx,%edx		//此时ecx中是table_list[1].read_q的地址
	subl $_table_list,%edx	//edx=8
	shrl $3,%edx			//edx=1
	movl (%ecx),%ecx		# read-queue	//将table_list[1].read_q的地址(ecx)中的值送入ecx,data值为3F8
	movl head(%ecx),%ebx		//将table_list[1].read_q结构中的第2个成员地址(head)中的值送入ebx,为0
	movb %al,buf(%ecx,%ebx)	//将字符数据放入结构中的char
	incl %ebx			//ebx=1
	andl $size-1,%ebx		//andl	3FF	%ebx
	cmpl tail(%ecx),%ebx		//第一次循环期间tail(%ecx)为0
	je 1f
	movl %ebx,head(%ecx)		//将结构成员head的值设为1
	pushl %edx
	call _do_tty_interrupt
	addl $4,%esp
1:	ret

.align 2
write_char:
	movl 4(%ecx),%ecx		# write-queue		//ecx=table_list[1].write_q
	movl head(%ecx),%ebx		//ebx=table_list[1].write_q结构中的head成员=0
	subl tail(%ecx),%ebx		//指向table_list[1].write_q结构中的tail成员=0
	andl $size-1,%ebx		# nr chars in queue
	je write_buffer_empty
	cmpl $startup,%ebx
	ja 1f
	movl proc_list(%ecx),%ebx	# wake up sleeping process
	testl %ebx,%ebx			# is there any?
	je 1f				//ebx=0时跳转
	movl $0,(%ebx)
1:	movl tail(%ecx),%ebx
	movb buf(%ecx,%ebx),%al	//将缓冲区的字节数据送入al,实际写数据的代码
	outb %al,%dx
	incl %ebx			//调整table_list[1].write_q中的状态
	andl $size-1,%ebx
	movl %ebx,tail(%ecx)
	cmpl head(%ecx),%ebx
	je write_buffer_empty
	ret
.align 2
write_buffer_empty:
	movl proc_list(%ecx),%ebx	# wake up sleeping process
	testl %ebx,%ebx			# is there any?
	je 1f
	movl $0,(%ebx)
1:	incl %edx			//0X3F9是中断开放寄存器,低4位有用
	inb %dx,%al
	jmp 1f
1:	jmp 1f
1:	andb $0xd,%al		/* disable transmit interrupt */
	outb %al,%dx
	ret

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -