source: trunk/src/kernel32/old/iccio.asm@ 1036

Last change on this file since 1036 was 955, checked in by sandervl, 26 years ago

Backup copy of old kernel32

File size: 14.4 KB
Line 
1; $Id: iccio.asm,v 1.1 1999-09-15 23:32:56 sandervl Exp $
2
3; **********************************************************************
4; Copyright (C) 1995 by Holger Veit (Holger.Veit@gmd.de)
5; Use at your own risk! No Warranty! The author is not responsible for
6; any damage or loss of data caused by proper or improper use of this
7; device driver.
8; **********************************************************************
9;
10; compile with ALP
11;
12 TITLE ICCIO.ASM
13 .386
14 .387
15
16DATA32 SEGMENT DWORD PUBLIC USE32 'DATA'
17 ASSUME CS:FLAT ,DS:FLAT,SS:FLAT
18 EXTRN ioentry:DWORD
19 EXTRN gdt:WORD
20 EXTRN devname:BYTE
21DATA32 ENDS
22
23CODE32 SEGMENT DWORD PUBLIC USE32 'CODE'
24 ASSUME CS:FLAT ,DS:FLAT,SS:FLAT
25
26 ALIGN 04H
27
28; performs fast output of a byte to an I/O port
29; this routine is intended to be called from icc C code
30;
31; Calling convention:
32; void _c_outb(short port,char data)
33;
34;
35 PUBLIC _c_outb
36_c_outb PROC
37 MOV EDX, DWORD PTR [ESP+4] ; get port
38 MOV AL, BYTE PTR [ESP+8] ; get data
39 PUSH EBX ; save register
40 MOV EBX, 4 ; function code 4 = write byte
41 CALL FWORD PTR [ioentry] ; call intersegment indirect 16:32
42 POP EBX
43 RET
44_c_outb ENDP
45
46; performs fast output of a word to an I/O port
47; this routine is intended to be called from icc C code
48;
49; Calling convention:
50; void _c_outw(short port,short data)
51;
52;
53 ALIGN 04H
54
55 PUBLIC _c_outw
56_c_outw PROC
57 MOV EDX, DWORD PTR [ESP+4] ; get port
58 MOV AX, WORD PTR [ESP+8] ; get data
59 PUSH EBX ; save register
60 MOV EBX, 5 ; function code 5 = write word
61 CALL FWORD PTR [ioentry] ; call intersegment indirect 16:32
62 POP EBX
63 RET
64_c_outw ENDP
65
66; performs fast output of a dword to an I/O port
67; this routine is intended to be called from icc C code
68;
69; Calling convention:
70; void _c_outl(short port,long data)
71;
72;
73 ALIGN 04H
74
75 PUBLIC _c_outl
76_c_outl PROC
77 MOV EDX, DWORD PTR [ESP+4] ; get port
78 MOV EAX, DWORD PTR [ESP+8] ; get data
79 PUSH EBX ; save register
80 MOV EBX, 6 ; function code 6 = write dword
81 CALL FWORD PTR [ioentry] ; call intersegment indirect 16:32
82 POP EBX
83 RET
84_c_outl ENDP
85
86; performs fast input of a byte from an I/O port
87; this routine is intended to be called from gcc C code
88;
89; Calling convention:
90; char _c_inb(short port)
91;
92;
93 ALIGN 04H
94 PUBLIC _c_inb
95_c_inb PROC
96 MOV EDX, DWORD PTR [ESP+4] ; get port number
97 PUSH EBX ; save register
98 MOV EBX, 1 ; function code 1 = read byte
99 CALL FWORD PTR [ioentry] ; call intersegment indirect 16:32
100 AND EAX, 000000ffH ; mask out required byte
101 POP EBX ; restore register
102 RET
103_c_inb ENDP
104
105; performs fast input of a word from an I/O port
106; this routine is intended to be called from gcc C code
107;
108; Calling convention:
109; short _c_inw(short port)
110;
111;
112 ALIGN 04H
113 PUBLIC _c_inw
114_c_inw PROC
115 MOV EDX, DWORD PTR [ESP+4] ; get port number
116 PUSH EBX ; save register
117 MOV EBX, 2 ; function code 2 = read short
118 CALL FWORD PTR [ioentry] ; call intersegment indirect 16:32
119 AND EAX, 0000ffffH ; mask out required byte
120 POP EBX ; restore register
121 RET
122_c_inw ENDP
123
124; performs fast input of a dword from an I/O port
125; this routine is intended to be called from gcc C code
126;
127; Calling convention:
128; long _c_inl(short port)
129;
130;
131 ALIGN 04H
132 PUBLIC _c_inl
133_c_inl PROC
134 MOV EDX, DWORD PTR [ESP+4] ; get port number
135 PUSH EBX ; save register
136 MOV EBX, 3 ; function code 3 = read long
137 CALL FWORD PTR [ioentry] ; call intersegment indirect 16:32
138; AND EAX, 000000ffH ; mask out required byte
139 POP EBX ; restore register
140 RET
141_c_inl ENDP
142
143 ALIGN 4
144 PUBLIC _c_readmsr
145_c_readmsr PROC NEAR
146 PUSH EBP
147 MOV EBP, ESP
148 PUSH EAX
149 PUSH EBX
150 PUSH ECX
151 PUSH EDX ; save register
152 MOV ECX, DWORD PTR [EBP+8] ; get msr reg
153 MOV EBX, 7 ; function code 7 = read msr
154 CALL FWORD PTR [ioentry] ; call intersegment indirect 16:32
155 MOV EBX, DWORD PTR [EBP+12] ; LONGLONG ptr
156 MOV DWORD PTR [EBX+4], EDX
157 MOV DWORD PTR [EBX], EAX
158 POP EDX
159 POP ECX
160 POP EBX ; restore register
161 POP EAX
162 POP EBP
163 RET
164_c_readmsr ENDP
165
166;------------------------------------------------------------------------------
167
168; performs fast output of a byte to an I/O port
169; this routine is intended to be called from assembler code
170; note there is no stack frame, however 8 byte stack space is required
171;
172; calling convention:
173; MOV EDX, portnr
174; MOV AL, data
175; CALL a_outb
176;
177;
178 ALIGN 04H
179 PUBLIC a_outb
180a_outb PROC
181 PUSH EBX ; save register
182 MOV EBX, 4 ; function code 4 = write byte
183 CALL FWORD PTR [ioentry] ; call intersegment indirect 16:32
184 POP EBX ; restore bx
185 RET
186a_outb ENDP
187
188; performs fast output of a word to an I/O port
189; this routine is intended to be called from assembler code
190; note there is no stack frame, however 8 byte stack space is required
191;
192; calling convention:
193; MOV EDX, portnr
194; MOV AX, data
195; CALL a_outw
196;
197;
198 ALIGN 04H
199 PUBLIC a_outw
200a_outw PROC
201 PUSH EBX ; save register
202 MOV EBX, 5 ; function code 5 = write word
203 CALL FWORD PTR [ioentry] ; call intersegment indirect 16:32
204 POP EBX ; restore bx
205 RET
206a_outw ENDP
207
208; performs fast output of a long to an I/O port
209; this routine is intended to be called from assembler code
210; note there is no stack frame, however 8 byte stack space is required
211;
212; calling convention:
213; MOV EDX, portnr
214; MOV EAX, data
215; CALL a_outl
216;
217;
218 ALIGN 04H
219 PUBLIC a_outl
220a_outl PROC
221 PUSH EBX ; save register
222 MOV EBX, 6 ; function code 6 = write long
223 CALL FWORD PTR [ioentry] ; call intersegment indirect 16:32
224 POP EBX ; restore bx
225 RET
226a_outl ENDP
227
228; performs fast input of a byte from an I/O port
229; this routine is intended to be called from assembler code
230; note there is no stack frame, however 8 byte stack space is required
231;
232; calling convention:
233; MOV EDX, portnr
234; CALL a_inb
235; ;data in AL
236;
237 ALIGN 04H
238 PUBLIC a_inb
239a_inb PROC
240 PUSH EBX ; save register
241 MOV EBX, 1 ; function code 1 = read byte
242 CALL FWORD PTR [ioentry] ; call intersegment indirect 16:32
243 AND EAX, 000000FFh ; mask byte
244 POP EBX ; restore register
245 RET
246a_inb ENDP
247
248
249; performs fast input of a word from an I/O port
250; this routine is intended to be called from assembler code
251; note there is no stack frame, however 8 byte stack space is required
252;
253; calling convention:
254; MOV EDX, portnr
255; CALL a_inb
256; ;data in AX
257;
258 ALIGN 04H
259 PUBLIC a_inw
260a_inw PROC
261 PUSH EBX ; save register
262 MOV EBX, 2 ; function code 2 = read word
263 CALL FWORD PTR [ioentry] ; call intersegment indirect 16:32
264 AND EAX, 0000FFFFh ; mask byte
265 POP EBX ; restore register
266 RET
267a_inw ENDP
268
269; performs fast input of a dword from an I/O port
270; this routine is intended to be called from assembler code
271; note there is no stack frame, however 8 byte stack space is required
272;
273; calling convention:
274; MOV EDX, portnr
275; CALL a_inl
276; ;data in EAX
277;
278 ALIGN 04H
279 PUBLIC a_inl
280a_inl PROC
281 PUSH EBX ; save register
282 MOV EBX, 3 ; function code 3 = read dword
283 CALL FWORD PTR [ioentry] ; call intersegment indirect 16:32
284 POP EBX ; restore register
285 RET
286a_inl ENDP
287
288CODE32 ENDS
289
290;------------------------------------------------------------------------------
291
292; Initialize I/O access via the driver.
293; You *must* call this routine once for each executable that wants to do
294; I/O.
295;
296; The routine is mainly equivalent to a C routine performing the
297; following (but no need to add another file):
298; DosOpen("/dev/fastio$", read, nonexclusive)
299; DosDevIOCtl(device, XFREE86_IO, IO_GETSEL32)
300; selector -> ioentry+4
301; DosClose(device)
302;
303; Calling convention:
304; int io_init(void)
305; Return:
306; 0 if successful
307; standard APIRET return code if error
308;
309
310CODE32 SEGMENT
311 PUBLIC _io_init
312 EXTRN DosOpen:PROC
313 EXTRN DosClose:PROC
314 EXTRN DosDevIOCtl:PROC
315_io_init PROC
316 PUSH EBP
317 MOV EBP, ESP ; standard stack frame
318 SUB ESP, 16 ; reserve memory
319 ; -16 = len arg of DosDevIOCtl
320 ; -12 = action arg of DosOpen
321 ; -8 = fd arg of DosOpen
322 ; -2 = short GDT selector arg
323 PUSH 0 ; (PEAOP2)NULL
324 PUSH 66 ; OPEN_ACCESS_READWRITE|OPEN_SHARE_DENYNONE
325 PUSH 1 ; FILE_OPEN
326 PUSH 0 ; FILE_NORMAL
327 PUSH 0 ; initial size
328 LEA EAX, [EBP-12] ; Adress of 'action' arg
329 PUSH EAX
330 LEA EAX, [EBP-8] ; Address of 'fd' arg
331 PUSH EAX
332 PUSH OFFSET devname
333 CALL DosOpen ; call DosOpen
334 ADD ESP, 32 ; cleanup stack frame
335 CMP EAX, 0 ; is return code zero?
336 JE goon ; yes, proceed
337 LEAVE ; no return error
338 RET
339
340 ALIGN 04H
341goon:
342 LEA EAX, [EBP-16] ; address of 'len' arg of DosDevIOCtl
343 PUSH EAX
344 PUSH 2 ; sizeof(short)
345 LEA EAX, [EBP-2] ; address to return the GDT selector
346 PUSH EAX
347 PUSH 0 ; no parameter len
348 PUSH 0 ; no parameter size
349 PUSH 0 ; no parameter address
350 PUSH 100 ; function code IO_GETSEL32
351 PUSH 118 ; category code XFREE6_IO
352 MOV EAX, [EBP-8] ; file handle
353 PUSH EAX
354 CALL DosDevIOCtl ; perform ioctl
355 ADD ESP, 36 ; cleanup stack
356 CMP EAX, 0 ; is return code = 0?
357 JE ok ; yes, proceed
358 PUSH EAX ; was error, save error code
359 MOV EAX, [EBP-8] ; file handle
360 PUSH EAX
361 CALL DosClose ; close device
362 ADD ESP, 4 ; clean stack
363 POP EAX ; get error code
364 LEAVE ; return error
365 RET
366
367 ALIGN 04H
368ok:
369 MOV EAX,[EBP-8] ; file handle
370 PUSH EAX ; do normal close
371 CALL DosClose
372 ADD ESP, 4 ; clean stack
373
374 MOV AX, WORD PTR [EBP-2] ; load gdt selector
375 MOV gdt, AX ; store in ioentry address selector part
376 XOR EAX, EAX ; eax = 0
377 MOV DWORD PTR [ioentry], EAX ; clear ioentry offset part
378 ; return code = 0 (in %eax)
379 LEAVE ; clean stack frame
380 RET ; exit
381_io_init ENDP
382
383; just for symmetry, does nothing
384
385 ALIGN 04H
386 PUBLIC _io_exit
387_io_exit PROC
388 XOR EAX,EAX
389 RET
390_io_exit ENDP
391
392 ALIGN 04H
393 PUBLIC int03
394
395int03 PROC
396 INT 3
397 RET
398int03 ENDP
399
400;------------------------------------------------------------------------------
401
402; Initialize I/O access via the driver.
403; You *must* call this routine once for each *thread* that wants to do
404; I/O.
405;
406; The routine is mainly equivalent to a C routine performing the
407; following (but no need to add another file):
408; DosOpen("/dev/fastio$", read, nonexclusive)
409; DosDevIOCtl(device, XFREE86IO, IOGETSEL32)
410; selector -> ioentry+4
411; DosClose(device)
412;
413; Calling convention:
414; int io_init1(void)
415; Return:
416; 0 if successful
417; standard APIRET RETurn code if error
418;
419
420 PUBLIC _io_init1
421 ALIGN 04H
422_io_init1 PROC
423 PUSH EBP
424 MOV EBP, ESP ; standard stack frame
425 SUB ESP, 16 ; reserve memory
426 ; -16 = len arg of DosDevIOCtl
427 ; -12 = action arg of DosOpen
428 ; -8 = fd arg of DosOpen
429 ; -2 = short GDT selector arg
430 PUSH 0 ; (PEAOP2)NULL
431 PUSH 66 ; OPENACCESSREADWRITE|OPENSHAREDENYNONE
432 PUSH 1 ; FILEOPEN
433 PUSH 0 ; FILENORMAL
434 PUSH 0 ; initial size
435 LEA EAX, [EBP-12] ; Adress of 'action' arg
436 PUSH EAX
437 LEA EAX, [EBP-8] ; Address of 'fd' arg
438 PUSH EAX
439 PUSH OFFSET devname
440 CALL DosOpen ; call DosOpen
441 ADD ESP, 32 ; cleanup stack frame
442 CMP EAX, 0 ; is return code zero?
443 JE goon1 ; yes, proceed
444 LEAVE ; no RETurn error
445 RET
446 ALIGN 04H
447goon1:
448 LEA EAX, [EBP-16] ; address of 'len' arg of DosDevIOCtl
449 PUSH EAX
450 PUSH 2 ; sizeof(short)
451 LEA EAX, [EBP-2] ; address to return the GDT selector
452 PUSH EAX
453 PUSH 0 ; no parameter len
454 PUSH 0 ; no parameter size
455 PUSH 0 ; no parameter address
456 PUSH 100 ; function code IOGETSEL32
457 PUSH 118 ; category code XFREE6IO
458 MOV EAX,[EBP-8] ; file handle
459 PUSH EAX
460 CALL DosDevIOCtl ; perform ioctl
461 ADD ESP, 36 ; cleanup stack
462 CMP EAX, 0 ; is return code = 0?
463 JE ok1 ; yes, proceed
464 PUSH EAX ; was error, save error code
465 MOV EAX, [EBP-8] ; file handle
466 PUSH EAX
467 CALL DosClose ; close device
468 ADD ESP,4 ; clean stack
469 POP EAX ; get error code
470 LEAVE ; return error
471 RET
472
473 ALIGN 04H
474ok1:
475 MOV EAX, [EBP-8] ; file handle
476 PUSH EAX ; do normal close
477 CALL DosClose
478 ADD ESP,4 ; clean stack
479
480 MOV AX, [EBP-2] ; load gdt selector
481 MOV gdt, AX ; store in ioentry address selector part
482 XOR EAX, EAX ; EAX = 0
483 MOV DWORD PTR [ioentry], EAX ; clear ioentry offset part
484 ; return code = 0 (in EAX)
485
486 ; now use this function to raise the IOPL
487 MOV EBX,13 ; special function code
488 CALL FWORD PTR [ioentry] ; CALL intersegment indirect 16:32
489
490 ; thread should now be running at IOPL=3
491
492 XOR EAX, EAX ; return code = 0
493 LEAVE ; clean stack frame
494 RET ; exit
495_io_init1 ENDP
496
497 PUBLIC _io_exit1
498 ALIGN 04H
499_io_exit1 PROC
500 push EBP
501 MOV EBP, ESP ; stackframe, I am accustomed to this :-)
502
503 MOV AX, gdt ; check if ioinit was called once
504 OR AX, AX
505 JZ exerr ; no gdt entry, so process cannot be at IOPL=3
506 ; through this mechanism
507
508 MOV EBX, 14 ; function code to disable iopl
509 CALL FWORD PTR [ioentry] ; call intersegment indirect 16:32
510
511 ; process should now be at IOPL=3 again
512 XOR EAX, EAX ; ok, RETurn code = 0
513 LEAVE
514 RET
515exerr: XOR EAX, EAX ; not ok, RETurn code = ffffffff
516 DEC EAX
517 LEAVE
518 RET
519_io_exit1 ENDP
520
521; for diagnostic only
522
523 PUBLIC psw
524 ALIGN 04H
525psw PROC
526 PUSHF ; get the current PSW
527 POP EAX ; into EAX
528 RET
529psw ENDP
530
531CODE32 ENDS
532 END
Note: See TracBrowser for help on using the repository browser.