parent
							
								
									a8177b34c6
								
							
						
					
					
						commit
						746ea7e667
					
				@ -0,0 +1,147 @@
 | 
				
			||||
/*
 | 
				
			||||
 *  linux/kernel/rs_io.s
 | 
				
			||||
 *
 | 
				
			||||
 *  (C) 1991  Linus Torvalds
 | 
				
			||||
 */
 | 
				
			||||
 | 
				
			||||
/*
 | 
				
			||||
 *	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 4
 | 
				
			||||
rs1_interrupt:
 | 
				
			||||
	pushl $table_list+8
 | 
				
			||||
	jmp rs_int
 | 
				
			||||
.align 4
 | 
				
			||||
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
 | 
				
			||||
	pushl $0x10
 | 
				
			||||
	pop %es
 | 
				
			||||
	movl 24(%esp),%edx
 | 
				
			||||
	movl (%edx),%edx
 | 
				
			||||
	movl rs_addr(%edx),%edx
 | 
				
			||||
	addl $2,%edx		/* interrupt ident. reg */
 | 
				
			||||
rep_int:
 | 
				
			||||
	xorl %eax,%eax
 | 
				
			||||
	inb %dx,%al
 | 
				
			||||
	testb $1,%al
 | 
				
			||||
	jne end
 | 
				
			||||
	cmpb $6,%al		/* this shouldn't happen, but ... */
 | 
				
			||||
	ja end
 | 
				
			||||
	movl 24(%esp),%ecx
 | 
				
			||||
	pushl %edx
 | 
				
			||||
	subl $2,%edx
 | 
				
			||||
	call jmp_table(,%eax,2)		/* NOTE! not *4, bit0 is 0 already */
 | 
				
			||||
	popl %edx
 | 
				
			||||
	jmp rep_int
 | 
				
			||||
end:	movb $0x20,%al
 | 
				
			||||
	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 4
 | 
				
			||||
modem_status:
 | 
				
			||||
	addl $6,%edx		/* clear intr by reading modem status reg */
 | 
				
			||||
	inb %dx,%al
 | 
				
			||||
	ret
 | 
				
			||||
 | 
				
			||||
.align 4
 | 
				
			||||
line_status:
 | 
				
			||||
	addl $5,%edx		/* clear intr by reading line status reg. */
 | 
				
			||||
	inb %dx,%al
 | 
				
			||||
	ret
 | 
				
			||||
 | 
				
			||||
.align 4
 | 
				
			||||
read_char:
 | 
				
			||||
	inb %dx,%al
 | 
				
			||||
	movl %ecx,%edx
 | 
				
			||||
	subl $table_list,%edx
 | 
				
			||||
	shrl $3,%edx
 | 
				
			||||
	movl (%ecx),%ecx		# read-queue
 | 
				
			||||
	movl head(%ecx),%ebx
 | 
				
			||||
	movb %al,buf(%ecx,%ebx)
 | 
				
			||||
	incl %ebx
 | 
				
			||||
	andl $size-1,%ebx
 | 
				
			||||
	cmpl tail(%ecx),%ebx
 | 
				
			||||
	je 1f
 | 
				
			||||
	movl %ebx,head(%ecx)
 | 
				
			||||
1:	pushl %edx
 | 
				
			||||
	call do_tty_interrupt
 | 
				
			||||
	addl $4,%esp
 | 
				
			||||
	ret
 | 
				
			||||
 | 
				
			||||
.align 4
 | 
				
			||||
write_char:
 | 
				
			||||
	movl 4(%ecx),%ecx		# write-queue
 | 
				
			||||
	movl head(%ecx),%ebx
 | 
				
			||||
	subl tail(%ecx),%ebx
 | 
				
			||||
	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
 | 
				
			||||
	movl $0,(%ebx)
 | 
				
			||||
1:	movl tail(%ecx),%ebx
 | 
				
			||||
	movb buf(%ecx,%ebx),%al
 | 
				
			||||
	outb %al,%dx
 | 
				
			||||
	incl %ebx
 | 
				
			||||
	andl $size-1,%ebx
 | 
				
			||||
	movl %ebx,tail(%ecx)
 | 
				
			||||
	cmpl head(%ecx),%ebx
 | 
				
			||||
	je write_buffer_empty
 | 
				
			||||
	ret
 | 
				
			||||
.align 4
 | 
				
			||||
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
 | 
				
			||||
	inb %dx,%al
 | 
				
			||||
	jmp 1f
 | 
				
			||||
1:	jmp 1f
 | 
				
			||||
1:	andb $0xd,%al		/* disable transmit interrupt */
 | 
				
			||||
	outb %al,%dx
 | 
				
			||||
	ret
 | 
				
			||||
					Loading…
					
					
				
		Reference in new issue