| 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
|
|---|