source: trunk/src/kernel32/iccio.asm@ 73

Last change on this file since 73 was 46, checked in by sandervl, 26 years ago

* empty log message *

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