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

Last change on this file since 2013 was 1621, checked in by achimha, 26 years ago

source code cleanup, remove warnings

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