summaryrefslogtreecommitdiffstats
path: root/src/kernel/chr_drv/rs_io.s
diff options
context:
space:
mode:
Diffstat (limited to 'src/kernel/chr_drv/rs_io.s')
-rw-r--r--src/kernel/chr_drv/rs_io.s147
1 files changed, 147 insertions, 0 deletions
diff --git a/src/kernel/chr_drv/rs_io.s b/src/kernel/chr_drv/rs_io.s
new file mode 100644
index 0000000..6788658
--- /dev/null
+++ b/src/kernel/chr_drv/rs_io.s
@@ -0,0 +1,147 @@
1/*
2 * linux/kernel/rs_io.s
3 *
4 * (C) 1991 Linus Torvalds
5 */
6
7/*
8 * rs_io.s
9 *
10 * This module implements the rs232 io interrupts.
11 */
12
13.text
14.globl rs1_interrupt,rs2_interrupt
15
16size = 1024 /* must be power of two !
17 and must match the value
18 in tty_io.c!!! */
19
20/* these are the offsets into the read/write buffer structures */
21rs_addr = 0
22head = 4
23tail = 8
24proc_list = 12
25buf = 16
26
27startup = 256 /* chars left in write queue when we restart it */
28
29/*
30 * These are the actual interrupt routines. They look where
31 * the interrupt is coming from, and take appropriate action.
32 */
33.align 2
34rs1_interrupt:
35 pushl $table_list+8
36 jmp rs_int
37.align 2
38rs2_interrupt:
39 pushl $table_list+16
40rs_int:
41 pushl %edx
42 pushl %ecx
43 pushl %ebx
44 pushl %eax
45 push %es
46 push %ds /* as this is an interrupt, we cannot */
47 pushl $0x10 /* know that bs is ok. Load it */
48 pop %ds
49 pushl $0x10
50 pop %es
51 movl 24(%esp),%edx
52 movl (%edx),%edx
53 movl rs_addr(%edx),%edx
54 addl $2,%edx /* interrupt ident. reg */
55rep_int:
56 xorl %eax,%eax
57 inb %dx,%al
58 testb $1,%al
59 jne end
60 cmpb $6,%al /* this shouldn't happen, but ... */
61 ja end
62 movl 24(%esp),%ecx
63 pushl %edx
64 subl $2,%edx
65 call *jmp_table(,%eax,2) /* NOTE! not *4, bit0 is 0 already */
66 popl %edx
67 jmp rep_int
68end: movb $0x20,%al
69 outb %al,$0x20 /* EOI */
70 pop %ds
71 pop %es
72 popl %eax
73 popl %ebx
74 popl %ecx
75 popl %edx
76 addl $4,%esp # jump over _table_list entry
77 iret
78
79jmp_table:
80 .long modem_status,write_char,read_char,line_status
81
82.align 2
83modem_status:
84 addl $6,%edx /* clear intr by reading modem status reg */
85 inb %dx,%al
86 ret
87
88.align 2
89line_status:
90 addl $5,%edx /* clear intr by reading line status reg. */
91 inb %dx,%al
92 ret
93
94.align 2
95read_char:
96 inb %dx,%al
97 movl %ecx,%edx
98 subl $table_list,%edx
99 shrl $3,%edx
100 movl (%ecx),%ecx # read-queue
101 movl head(%ecx),%ebx
102 movb %al,buf(%ecx,%ebx)
103 incl %ebx
104 andl $size-1,%ebx
105 cmpl tail(%ecx),%ebx
106 je 1f
107 movl %ebx,head(%ecx)
1081: pushl %edx
109 call do_tty_interrupt
110 addl $4,%esp
111 ret
112
113.align 2
114write_char:
115 movl 4(%ecx),%ecx # write-queue
116 movl head(%ecx),%ebx
117 subl tail(%ecx),%ebx
118 andl $size-1,%ebx # nr chars in queue
119 je write_buffer_empty
120 cmpl $startup,%ebx
121 ja 1f
122 movl proc_list(%ecx),%ebx # wake up sleeping process
123 testl %ebx,%ebx # is there any?
124 je 1f
125 movl $0,(%ebx)
1261: movl tail(%ecx),%ebx
127 movb buf(%ecx,%ebx),%al
128 outb %al,%dx
129 incl %ebx
130 andl $size-1,%ebx
131 movl %ebx,tail(%ecx)
132 cmpl head(%ecx),%ebx
133 je write_buffer_empty
134 ret
135.align 2
136write_buffer_empty:
137 movl proc_list(%ecx),%ebx # wake up sleeping process
138 testl %ebx,%ebx # is there any?
139 je 1f
140 movl $0,(%ebx)
1411: incl %edx
142 inb %dx,%al
143 jmp 1f
1441: jmp 1f
1451: andb $0xd,%al /* disable transmit interrupt */
146 outb %al,%dx
147 ret