1 | ; **********************************************************************
|
---|
2 | ; Copyright (C) 1995 by Holger Veit (Holger.Veit@gmd.de)
|
---|
3 | ; Use at your own risk! No Warranty! The author is not responsible for
|
---|
4 | ; any damage or loss of data caused by proper or improper use of this
|
---|
5 | ; device driver.
|
---|
6 | ; **********************************************************************
|
---|
7 | ;
|
---|
8 | ; compile with ALP
|
---|
9 | ;
|
---|
10 | TITLE ICCIO.ASM
|
---|
11 | .386
|
---|
12 | .387
|
---|
13 | CODE32 SEGMENT DWORD USE32 PUBLIC 'CODE'
|
---|
14 | CODE32 ENDS
|
---|
15 | DATA32 SEGMENT DWORD USE32 PUBLIC 'DATA'
|
---|
16 | DATA32 ENDS
|
---|
17 | CONST32 SEGMENT DWORD USE32 PUBLIC 'CONST'
|
---|
18 | CONST32 ENDS
|
---|
19 | BSS32 SEGMENT DWORD USE32 PUBLIC 'BSS'
|
---|
20 | BSS32 ENDS
|
---|
21 | DGROUP GROUP CONST32, BSS32, DATA32
|
---|
22 | ASSUME CS:FLAT, DS:FLAT, SS:FLAT, ES:FLAT
|
---|
23 | DATA32 SEGMENT
|
---|
24 | DATA32 ENDS
|
---|
25 | BSS32 SEGMENT
|
---|
26 | BSS32 ENDS
|
---|
27 | CONST32 SEGMENT
|
---|
28 | CONST32 ENDS
|
---|
29 |
|
---|
30 | DATA32 SEGMENT
|
---|
31 | ioentry DWORD 0
|
---|
32 | gdt WORD 0
|
---|
33 | DATA32 ENDS
|
---|
34 |
|
---|
35 | CODE32 SEGMENT
|
---|
36 |
|
---|
37 | ; performs fast output of a byte to an I/O port
|
---|
38 | ; this routine is intended to be called from gcc C code
|
---|
39 | ;
|
---|
40 | ; Calling convention:
|
---|
41 | ; void c_outb1(short port,char data)
|
---|
42 | ;
|
---|
43 | ;
|
---|
44 | PUBLIC c_outb1
|
---|
45 | ALIGN 04H
|
---|
46 | c_outb1 PROC
|
---|
47 | MOV EDX, [ESP+4] ; get port
|
---|
48 | MOV AL, [ESP+8] ; get data
|
---|
49 | OUT DX,AL
|
---|
50 | RET
|
---|
51 | c_outb1 ENDP
|
---|
52 |
|
---|
53 | ; performs fast output of a word to an I/O port
|
---|
54 | ; this routine is intended to be called from gcc C code
|
---|
55 | ;
|
---|
56 | ; Calling convention:
|
---|
57 | ; void c_outw1(short port,short data)
|
---|
58 | ;
|
---|
59 | ;
|
---|
60 | PUBLIC c_outw1
|
---|
61 | ALIGN 04H
|
---|
62 | c_outw1 PROC
|
---|
63 | MOV EDX, [ESP+4] ; get port
|
---|
64 | MOV AX, [ESP+8] ; get data
|
---|
65 | OUT DX,AX
|
---|
66 | RET
|
---|
67 | c_outw1 ENDP
|
---|
68 |
|
---|
69 | ; performs fast output of a longword to an I/O port
|
---|
70 | ; this routine is intended to be called from gcc C code
|
---|
71 | ;
|
---|
72 | ; Calling convention:
|
---|
73 | ; void c_outl1(short port,long data)
|
---|
74 | ;
|
---|
75 | ;
|
---|
76 | PUBLIC c_outl1
|
---|
77 | ALIGN 04H
|
---|
78 | c_outl1 PROC
|
---|
79 | MOV EDX, [ESP+4] ; get port
|
---|
80 | MOV EAX, [ESP+8] ; get data
|
---|
81 | OUT DX, EAX
|
---|
82 | RET
|
---|
83 | c_outl1 ENDP
|
---|
84 |
|
---|
85 | ; performs fast input of a byte from an I/O port
|
---|
86 | ; this routine is intended to be called from gcc C code
|
---|
87 | ;
|
---|
88 | ; Calling convention:
|
---|
89 | ; char c_inb1(short port)
|
---|
90 | ;
|
---|
91 | ;
|
---|
92 | PUBLIC c_inb1
|
---|
93 | ALIGN 04H
|
---|
94 | c_inb1 PROC
|
---|
95 | MOV EDX, [ESP+4] ; get port
|
---|
96 | IN AL,DX
|
---|
97 | AND EAX, 000000FFh
|
---|
98 | RET
|
---|
99 | c_inb1 ENDP
|
---|
100 |
|
---|
101 | ; performs fast input of a word from an I/O port
|
---|
102 | ; this routine is intended to be called from gcc C code
|
---|
103 | ;
|
---|
104 | ; Calling convention:
|
---|
105 | ; short c_inw1(short port)
|
---|
106 | ;
|
---|
107 | ;
|
---|
108 | PUBLIC c_inw1
|
---|
109 | ALIGN 04H
|
---|
110 | c_inw1 PROC
|
---|
111 | MOV EDX, [ESP+4] ; get port
|
---|
112 | IN AX, DX
|
---|
113 | AND EAX, 0000FFFFh ; mask out word
|
---|
114 | RET
|
---|
115 | c_inw1 ENDP
|
---|
116 |
|
---|
117 | ; performs fast input of a longword from an I/O port
|
---|
118 | ; this routine is intended to be called from gcc C code
|
---|
119 | ;
|
---|
120 | ; Calling convention:
|
---|
121 | ; lomg c_inl1(short port)
|
---|
122 | ;
|
---|
123 | ;
|
---|
124 | PUBLIC c_inl1
|
---|
125 | ALIGN 04H
|
---|
126 | c_inl1 PROC
|
---|
127 | MOV EDX, [ESP+4] ; get port
|
---|
128 | IN EAX, DX
|
---|
129 | RET
|
---|
130 | c_inl1 ENDP
|
---|
131 |
|
---|
132 | CODE32 ENDS
|
---|
133 |
|
---|
134 | ;------------------------------------------------------------------------------
|
---|
135 |
|
---|
136 | ; Initialize I/O access via the driver.
|
---|
137 | ; You *must* call this routine once for each *thread* that wants to do
|
---|
138 | ; I/O.
|
---|
139 | ;
|
---|
140 | ; The routine is mainly equivalent to a C routine performing the
|
---|
141 | ; following (but no need to add another file):
|
---|
142 | ; DosOpen("/dev/fastio$", read, nonexclusive)
|
---|
143 | ; DosDevIOCtl(device, XFREE86IO, IOGETSEL32)
|
---|
144 | ; selector -> ioentry+4
|
---|
145 | ; DosClose(device)
|
---|
146 | ;
|
---|
147 | ; Calling convention:
|
---|
148 | ; int io_init1(void)
|
---|
149 | ; Return:
|
---|
150 | ; 0 if successful
|
---|
151 | ; standard APIRET RETurn code if error
|
---|
152 | ;
|
---|
153 |
|
---|
154 | CONST32 SEGMENT
|
---|
155 | ALIGN 04H
|
---|
156 | devname:
|
---|
157 | DB "/dev/fastio$",0
|
---|
158 | CONST32 ENDS
|
---|
159 |
|
---|
160 |
|
---|
161 | CODE32 SEGMENT
|
---|
162 | PUBLIC io_init1
|
---|
163 | EXTRN DosOpen:PROC
|
---|
164 | EXTRN DosClose:PROC
|
---|
165 | EXTRN DosDevIOCtl:PROC
|
---|
166 | ALIGN 04H
|
---|
167 | io_init1 PROC
|
---|
168 | PUSH EBP
|
---|
169 | MOV EBP, ESP ; standard stack frame
|
---|
170 | SUB ESP, 16 ; reserve memory
|
---|
171 | ; -16 = len arg of DosDevIOCtl
|
---|
172 | ; -12 = action arg of DosOpen
|
---|
173 | ; -8 = fd arg of DosOpen
|
---|
174 | ; -2 = short GDT selector arg
|
---|
175 | PUSH 0 ; (PEAOP2)NULL
|
---|
176 | PUSH 66 ; OPENACCESSREADWRITE|OPENSHAREDENYNONE
|
---|
177 | PUSH 1 ; FILEOPEN
|
---|
178 | PUSH 0 ; FILENORMAL
|
---|
179 | PUSH 0 ; initial size
|
---|
180 | LEA EAX, [EBP-12] ; Adress of 'action' arg
|
---|
181 | PUSH EAX
|
---|
182 | LEA EAX, [EBP-8] ; Address of 'fd' arg
|
---|
183 | PUSH EAX
|
---|
184 | PUSH OFFSET FLAT:devname
|
---|
185 | CALL DosOpen ; call DosOpen
|
---|
186 | ADD ESP, 32 ; cleanup stack frame
|
---|
187 | CMP EAX, 0 ; is return code zero?
|
---|
188 | JE goon ; yes, proceed
|
---|
189 | LEAVE ; no RETurn error
|
---|
190 | RET
|
---|
191 | ALIGN 04H
|
---|
192 | goon:
|
---|
193 | LEA EAX, [EBP-16] ; address of 'len' arg of DosDevIOCtl
|
---|
194 | PUSH EAX
|
---|
195 | PUSH 2 ; sizeof(short)
|
---|
196 | LEA EAX, [EBP-2] ; address to return the GDT selector
|
---|
197 | PUSH EAX
|
---|
198 | PUSH 0 ; no parameter len
|
---|
199 | PUSH 0 ; no parameter size
|
---|
200 | PUSH 0 ; no parameter address
|
---|
201 | PUSH 100 ; function code IOGETSEL32
|
---|
202 | PUSH 118 ; category code XFREE6IO
|
---|
203 | MOV EAX,[EBP-8] ; file handle
|
---|
204 | PUSH EAX
|
---|
205 | CALL DosDevIOCtl ; perform ioctl
|
---|
206 | ADD ESP, 36 ; cleanup stack
|
---|
207 | CMP EAX, 0 ; is return code = 0?
|
---|
208 | JE ok ; yes, proceed
|
---|
209 | PUSH EAX ; was error, save error code
|
---|
210 | MOV EAX, [EBP-8] ; file handle
|
---|
211 | PUSH EAX
|
---|
212 | CALL DosClose ; close device
|
---|
213 | ADD ESP,4 ; clean stack
|
---|
214 | POP EAX ; get error code
|
---|
215 | LEAVE ; return error
|
---|
216 | RET
|
---|
217 |
|
---|
218 | ALIGN 04H
|
---|
219 | ok:
|
---|
220 | MOV EAX, [EBP-8] ; file handle
|
---|
221 | PUSH EAX ; do normal close
|
---|
222 | CALL DosClose
|
---|
223 | ADD ESP,4 ; clean stack
|
---|
224 |
|
---|
225 | MOV AX, [EBP-2] ; load gdt selector
|
---|
226 | MOV gdt, AX ; store in ioentry address selector part
|
---|
227 | XOR EAX, EAX ; EAX = 0
|
---|
228 | MOV DWORD PTR [ioentry], EAX ; clear ioentry offset part
|
---|
229 | ; return code = 0 (in EAX)
|
---|
230 |
|
---|
231 | ; now use this function to raise the IOPL
|
---|
232 | PUSH EBX ; bird fix
|
---|
233 | MOV EBX,13 ; special function code
|
---|
234 | CALL FWORD PTR [ioentry] ; CALL intersegment indirect 16:32
|
---|
235 | POP EBX ; bird fix
|
---|
236 |
|
---|
237 | ; thread should now be running at IOPL=3
|
---|
238 |
|
---|
239 | XOR EAX, EAX ; return code = 0
|
---|
240 | LEAVE ; clean stack frame
|
---|
241 | RET ; exit
|
---|
242 | io_init1 ENDP
|
---|
243 |
|
---|
244 | ; void in_init(short)
|
---|
245 | PUBLIC io_init2
|
---|
246 | ALIGN 04H
|
---|
247 | io_init2 PROC
|
---|
248 | MOV EAX, dword ptr [ESP+4]
|
---|
249 | MOV gdt, AX ; store in ioentry address selector part
|
---|
250 | XOR EAX, EAX ; EAX = 0
|
---|
251 | MOV DWORD PTR [ioentry], EAX ; clear ioentry offset part
|
---|
252 | ; return code = 0 (in EAX)
|
---|
253 |
|
---|
254 | ; now use this function to raise the IOPL
|
---|
255 | PUSH EBX ; bird fix
|
---|
256 | MOV EBX,13 ; special function code
|
---|
257 | CALL FWORD PTR [ioentry] ; CALL intersegment indirect 16:32
|
---|
258 | POP EBX ; bird fix
|
---|
259 |
|
---|
260 | XOR EAX, EAX ; return code = 0
|
---|
261 | ret
|
---|
262 | io_init2 ENDP
|
---|
263 |
|
---|
264 | PUBLIC io_exit1
|
---|
265 | ALIGN 04H
|
---|
266 | io_exit1 PROC
|
---|
267 | push EBP
|
---|
268 | MOV EBP, ESP ; stackframe, I am accustomed to this :-)
|
---|
269 |
|
---|
270 | MOV AX, gdt ; check if ioinit was called once
|
---|
271 | OR AX, AX
|
---|
272 | JZ exerr ; no gdt entry, so process cannot be at IOPL=3
|
---|
273 | ; through this mechanism
|
---|
274 | PUSH EBX ; bird fix
|
---|
275 | MOV EBX, 14 ; function code to disable iopl
|
---|
276 | CALL FWORD PTR [ioentry] ; call intersegment indirect 16:32
|
---|
277 | POP EBX ; bird fix
|
---|
278 |
|
---|
279 | ; process should now be at IOPL=3 again
|
---|
280 | XOR EAX, EAX ; ok, RETurn code = 0
|
---|
281 | LEAVE
|
---|
282 | RET
|
---|
283 | exerr: XOR EAX, EAX ; not ok, RETurn code = ffffffff
|
---|
284 | DEC EAX
|
---|
285 | LEAVE
|
---|
286 | RET
|
---|
287 | io_exit1 ENDP
|
---|
288 |
|
---|
289 |
|
---|
290 |
|
---|
291 | ; for diagnostic only
|
---|
292 |
|
---|
293 | ;; PUBLIC psw
|
---|
294 | ;; ALIGN 04H
|
---|
295 | ;;psw PROC
|
---|
296 | ;; PUSHF ; get the current PSW
|
---|
297 | ;; POP EAX ; into EAX
|
---|
298 | ;; RET
|
---|
299 | ;;psw ENDP
|
---|
300 |
|
---|
301 | CODE32 ENDS
|
---|
302 | END
|
---|