NT4/private/ntos/nthals/halncr/i386/ncrioacc.asm
2020-09-30 17:12:29 +02:00

731 lines
18 KiB
NASM

title "ix ioaccess"
;++
;
; Copyright (c) 1989 Microsoft Corporation
;
; Module Name:
;
; ncrioacc.asm
;
; Abstract:
;
; Procedures to correctly touch I/O registers.
;
; Author:
;
; Bryan Willman (bryanwi) 16 May 1990
; Rick Ulmer (rick.ulmer@columbiasc.ncr.com) 1 March 1994
;
; Environment:
;
; User or Kernel, although privledge (IOPL) may be required.
;
; Revision History:
;
; RMU - Added support for SMC for NCR 35xx systems.
;
;--
.386p
.xlist
include hal386.inc
include callconv.inc ; calling convention macros
.list
extrn _NCRSegmentIoRegister:DWORD
_TEXT$00 SEGMENT DWORD PUBLIC 'CODE'
ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
;++
;
; I/O port space read and write functions.
;
; These have to be actual functions on the 386, because we need
; to use assembler, but cannot return a value if we inline it.
;
; This set of functions manipulates I/O registers in PORT space.
; (Uses x86 in and out instructions)
;
; WARNING: Port addresses must always be in the range 0 to 64K, because
; that's the range the hardware understands.
;
;--
;++
;
; UCHAR
; READ_PORT_UCHAR(
; PUCHAR Port
; )
;
; Arguments:
; (esp+4) = Port
;
; Returns:
; Value in Port.
;
;--
cPublicProc _READ_PORT_UCHAR ,1
cPublicFpo 1, 0
mov edx,[esp+4] ; (dx) = Port
; port = ??srpppph
; sr = segment register
; pppp = port
test edx, 00010000h ; test for secondary access
jnz short ReadUcharSmca
;
; PMCA access
;
in al,dx
stdRET _READ_PORT_UCHAR
ReadUcharSmca:
;
; SMCA access
;
mov ecx,_NCRSegmentIoRegister ; get segment register
ror edx, 8 ; get segreg as byte in dh
pushfd
cli ; disable interrupts
mov BYTE PTR[ecx], dh ; set segment register
rol edx, 8 ; restore port
;
in al,dx
;
mov BYTE PTR[ecx], 0 ; clear segment register back to zero
popfd ; enable interrupt
stdRET _READ_PORT_UCHAR
stdENDP _READ_PORT_UCHAR
;++
;
; USHORT
; READ_PORT_USHORT(
; PUSHORT Port
; )
;
; Arguments:
; (esp+4) = Port
;
; Returns:
; Value in Port.
;
;--
cPublicProc _READ_PORT_USHORT ,1
cPublicFpo 1, 0
mov edx,[esp+4] ; (dx) = Port
; port = ??srpppph
; sr = segment register
; pppp = port
test edx, 00010000h ; test for secondary access
jnz short ReadUshortSmca
;
; PMCA access
;
in ax,dx
stdRET _READ_PORT_USHORT
ReadUshortSmca:
;
; SMCA access
;
mov ecx,_NCRSegmentIoRegister ; get segment register
ror edx, 8 ; get segreg as byte in dh
pushfd
cli ; disable interrupts
mov BYTE PTR[ecx], dh ; set segment register
rol edx, 8 ; restore port
;
in ax,dx
;
mov BYTE PTR[ecx], 0 ; clear segment register back to zero
popfd ; enable interrupt
stdRET _READ_PORT_USHORT
stdENDP _READ_PORT_USHORT
;++
;
; ULONG
; READ_PORT_ULONG(
; PULONG Port
; )
;
; Arguments:
; (esp+4) = Port
;
; Returns:
; Value in Port.
;
;--
cPublicProc _READ_PORT_ULONG ,1
cPublicFpo 1, 0
mov edx,[esp+4] ; (dx) = Port
; port = ??srpppph
; sr = segment register
; pppp = port
test edx, 00010000h ; test for secondary access
jnz short ReadUlongSmca
;
; PMCA access
;
in eax,dx
stdRET _READ_PORT_ULONG
ReadUlongSmca:
;
; SMCA access
;
mov ecx,_NCRSegmentIoRegister ; get segment register
ror edx, 8 ; get segreg as byte in dh
pushfd
cli ; disable interrupts
mov BYTE PTR[ecx], dh ; set segment register
rol edx, 8 ; restore port
;
in eax,dx
;
mov BYTE PTR[ecx], 0 ; clear segment register back to zero
popfd ; enable interrupt
stdRET _READ_PORT_ULONG
stdENDP _READ_PORT_ULONG
;++
;
; VOID
; READ_PORT_BUFFER_UCHAR(
; PUCHAR Port,
; PUCHAR Buffer,
; ULONG Count
; )
;
; Arguments:
; (esp+4) = Port
; (esp+8) = Buffer address
; (esp+12) = Count
;
;--
cPublicProc _READ_PORT_BUFFER_UCHAR ,3
cPublicFpo 3, 0
mov eax, edi ; Save edi
mov edx,[esp+4] ; (dx) = Port
; port = ??srpppph
; sr = segment register
; pppp = port
test edx, 00010000h ; test for secondary access
jnz short ReadBufferUcharSmca
;
; PMCA access
;
mov edi,[esp+8] ; (edi) = buffer
mov ecx,[esp+12] ; (ecx) = transfer count
rep insb
mov edi, eax
stdRET _READ_PORT_BUFFER_UCHAR
ReadBufferUcharSmca:
;
; SMCA access
;
mov edi,[esp+8] ; (edi) = buffer
mov ecx,[esp+12] ; (ecx) = transfer count
push ebx ; save ebx
mov ebx,_NCRSegmentIoRegister ; get segment register
ror edx, 8 ; get segreg as byte in dh
pushfd
cli ; disable interrupts
mov BYTE PTR[ebx], dh ; set segment register
rol edx, 8 ; restore port
;
rep insb
;
mov BYTE PTR[ebx], 0 ; clear segment register back to zero
popfd ; enable interrupt
pop ebx ; restore ebx
mov edi, eax
stdRET _READ_PORT_BUFFER_UCHAR
stdENDP _READ_PORT_BUFFER_UCHAR
;++
;
; VOID
; READ_PORT_BUFFER_USHORT(
; PUSHORT Port,
; PUSHORT Buffer,
; ULONG Count
; )
;
; Arguments:
; (esp+4) = Port
; (esp+8) = Buffer address
; (esp+12) = Count
;
;--
cPublicProc _READ_PORT_BUFFER_USHORT ,3
cPublicFpo 3, 0
mov eax, edi ; Save edi
mov edx,[esp+4] ; (dx) = Port
; port = ??srpppph
; sr = segment register
; pppp = port
test edx, 00010000h ; test for secondary access
jnz short ReadBufferUshortSmca
;
; PMCA access
;
mov edi,[esp+8] ; (edi) = buffer
mov ecx,[esp+12] ; (ecx) = transfer count
rep insw
mov edi, eax
stdRET _READ_PORT_BUFFER_USHORT
ReadBufferUshortSmca:
;
; SMCA access
;
mov edi,[esp+8] ; (edi) = buffer
mov ecx,[esp+12] ; (ecx) = transfer count
push ebx ; save ebx
mov ebx,_NCRSegmentIoRegister ; get segment register
ror edx, 8 ; get segreg as byte in dh
pushfd
cli ; disable interrupts
mov BYTE PTR[ebx], dh ; set segment register
rol edx, 8 ; restore port
;
rep insw
;
mov BYTE PTR[ebx], 0 ; clear segment register back to zero
popfd ; enable interrupt
pop ebx ; restore ebx
mov edi, eax
stdRET _READ_PORT_BUFFER_USHORT
stdENDP _READ_PORT_BUFFER_USHORT
;++
;
; VOID
; READ_PORT_BUFFER_ULONG(
; PULONG Port,
; PULONG Buffer,
; ULONG Count
; )
;
; Arguments:
; (esp+4) = Port
; (esp+8) = Buffer address
; (esp+12) = Count
;
;--
cPublicProc _READ_PORT_BUFFER_ULONG ,3
cPublicFpo 3, 0
mov eax, edi ; Save edi
mov edx,[esp+4] ; (dx) = Port
; port = ??srpppph
; sr = segment register
; pppp = port
test edx, 00010000h ; test for secondary access
jnz short ReadBufferUlongSmca
;
; PMCA access
;
mov edi,[esp+8] ; (edi) = buffer
mov ecx,[esp+12] ; (ecx) = transfer count
rep insd
mov edi, eax
stdRET _READ_PORT_BUFFER_ULONG
ReadBufferUlongSmca:
;
; SMCA access
;
mov edi,[esp+8] ; (edi) = buffer
mov ecx,[esp+12] ; (ecx) = transfer count
push ebx ; save ebx
mov ebx,_NCRSegmentIoRegister ; get segment register
ror edx, 8 ; get segreg as byte in dh
pushfd
cli ; disable interrupts
mov BYTE PTR[ebx], dh ; set segment register
rol edx, 8 ; restore port
;
rep insd
;
mov BYTE PTR[ebx], 0 ; clear segment register back to zero
popfd ; enable interrupt
pop ebx ; restore ebx
mov edi, eax
stdRET _READ_PORT_BUFFER_ULONG
stdENDP _READ_PORT_BUFFER_ULONG
;++
;
; VOID
; WRITE_PORT_UCHAR(
; PUCHAR Port,
; UCHAR Value
; )
;
; Arguments:
; (esp+4) = Port
; (esp+8) = Value
;
;--
cPublicProc _WRITE_PORT_UCHAR ,2
cPublicFpo 2, 0
mov edx,[esp+4] ; (dx) = Port
; port = ??srpppph
; sr = segment register
; pppp = port
test edx, 00010000h ; test for secondary access
jnz short WriteUcharSmca
;
; PMCA access
;
mov al,[esp+8] ; (al) = Value
out dx,al
stdRET _WRITE_PORT_UCHAR
WriteUcharSmca:
;
; SMCA access
;
mov ecx,_NCRSegmentIoRegister ; get segment register
mov al,[esp+8] ; (al) = Value
ror edx, 8 ; get segreg as byte in dh
pushfd
cli ; disable interrupts
mov BYTE PTR[ecx], dh ; set segment register
rol edx, 8 ; restore port
;
out dx,al
;
mov BYTE PTR[ecx], 0 ; clear segment register back to zero
popfd ; enable interrupt
stdRET _WRITE_PORT_UCHAR
stdENDP _WRITE_PORT_UCHAR
;++
;
; VOID
; WRITE_PORT_USHORT(
; PUSHORT Port,
; USHORT Value
; )
;
; Arguments:
; (esp+4) = Port
; (esp+8) = Value
;
;--
cPublicProc _WRITE_PORT_USHORT ,2
cPublicFpo 2, 0
mov edx,[esp+4] ; (dx) = Port
; port = ??srpppph
; sr = segment register
; pppp = port
test edx, 00010000h ; test for secondary access
jnz short WriteUshortSmca
;
; PMCA access
;
mov eax,[esp+8] ; (ax) = Value
out dx,ax
stdRET _WRITE_PORT_USHORT
WriteUshortSmca:
;
; SMCA access
;
mov ecx,_NCRSegmentIoRegister ; get segment register
mov eax,[esp+8] ; (ax) = Value
ror edx, 8 ; get segreg as byte in dh
pushfd
cli ; disable interrupts
mov BYTE PTR[ecx], dh ; set segment register
rol edx, 8 ; restore port
;
out dx,ax
;
mov BYTE PTR[ecx], 0 ; clear segment register back to zero
popfd ; enable interrupt
stdRET _WRITE_PORT_USHORT
stdENDP _WRITE_PORT_USHORT
;++
;
; VOID
; WRITE_PORT_ULONG(
; PULONG Port,
; ULONG Value
; )
;
; Arguments:
; (esp+4) = Port
; (esp+8) = Value
;
;--
cPublicProc _WRITE_PORT_ULONG ,2
cPublicFpo 2, 0
mov edx,[esp+4] ; (dx) = Port
; port = ??srpppph
; sr = segment register
; pppp = port
test edx, 00010000h ; test for secondary access
jnz short WriteUlongSmca
;
; PMCA access
;
mov eax,[esp+8] ; (eax) = Value
out dx,eax
stdRET _WRITE_PORT_ULONG
WriteUlongSmca:
;
; SMCA access
;
mov ecx,_NCRSegmentIoRegister ; get segment register
mov eax,[esp+8] ; (eax) = Value
ror edx, 8 ; get segreg as byte in dh
pushfd
cli ; disable interrupts
mov BYTE PTR[ecx], dh ; set segment register
rol edx, 8 ; restore port
;
out dx,eax
;
mov BYTE PTR[ecx], 0 ; clear segment register back to zero
popfd ; enable interrupt
stdRET _WRITE_PORT_ULONG
stdENDP _WRITE_PORT_ULONG
;++
;
; VOID
; WRITE_PORT_BUFFER_UCHAR(
; PUCHAR Port,
; PUCHAR Buffer,
; ULONG Count
; )
;
; Arguments:
; (esp+4) = Port
; (esp+8) = Buffer address
; (esp+12) = Count
;
;--
cPublicProc _WRITE_PORT_BUFFER_UCHAR ,3
cPublicFpo 3, 0
mov eax,esi ; Save esi
mov edx,[esp+4] ; (dx) = Port
; port = ??srpppph
; sr = segment register
; pppp = port
test edx, 00010000h ; test for secondary access
jnz short WriteBufferUcharSmca
;
; PMCA access
;
mov esi,[esp+8] ; (esi) = buffer
mov ecx,[esp+12] ; (ecx) = transfer count
rep outsb
mov esi,eax
stdRET _WRITE_PORT_BUFFER_UCHAR
WriteBufferUcharSmca:
;
; SMCA access
;
mov esi,[esp+8] ; (esi) = buffer
mov ecx,[esp+12] ; (ecx) = transfer count
push ebx ; save ebx
mov ebx,_NCRSegmentIoRegister ; get segment register
ror edx, 8 ; get segreg as byte in dh
pushfd
cli ; disable interrupts
mov BYTE PTR[ebx], dh ; set segment register
rol edx, 8 ; restore port
;
rep outsb
;
mov BYTE PTR[ebx], 0 ; clear segment register back to zero
popfd ; enable interrupt
pop ebx ; restore ebx
mov esi,eax
stdRET _WRITE_PORT_BUFFER_UCHAR
stdENDP _WRITE_PORT_BUFFER_UCHAR
;++
;
; VOID
; WRITE_PORT_BUFFER_USHORT(
; PUSHORT Port,
; PUSHORT Buffer,
; ULONG Count
; )
;
; Arguments:
; (esp+4) = Port
; (esp+8) = Buffer address
; (esp+12) = Count
;
;--
cPublicProc _WRITE_PORT_BUFFER_USHORT ,3
cPublicFpo 3, 0
mov eax,esi ; Save esi
mov edx,[esp+4] ; (dx) = Port
; port = ??srpppph
; sr = segment register
; pppp = port
test edx, 00010000h ; test for secondary access
jnz short WriteBufferUshortSmca
;
; PMCA access
;
mov esi,[esp+8] ; (esi) = buffer
mov ecx,[esp+12] ; (ecx) = transfer count
rep outsw
mov esi,eax
stdRET _WRITE_PORT_BUFFER_USHORT
WriteBufferUshortSmca:
;
; SMCA access
;
mov esi,[esp+8] ; (esi) = buffer
mov ecx,[esp+12] ; (ecx) = transfer count
push ebx ; save ebx
mov ebx,_NCRSegmentIoRegister ; get segment register
ror edx, 8 ; get segreg as byte in dh
pushfd
cli ; disable interrupts
mov BYTE PTR[ebx], dh ; set segment register
rol edx, 8 ; restore port
;
rep outsw
;
mov BYTE PTR[ebx], 0 ; clear segment register back to zero
popfd ; enable interrupt
pop ebx ; restore ebx
mov esi,eax
stdRET _WRITE_PORT_BUFFER_USHORT
stdENDP _WRITE_PORT_BUFFER_USHORT
;++
;
; VOID
; WRITE_PORT_BUFFER_ULONG(
; PULONG Port,
; PULONG Buffer,
; ULONG Count
; )
;
; Arguments:
; (esp+4) = Port
; (esp+8) = Buffer address
; (esp+12) = Count
;
;--
cPublicProc _WRITE_PORT_BUFFER_ULONG ,3
cPublicFpo 3, 0
mov eax,esi ; Save esi
mov edx,[esp+4] ; (dx) = Port
; port = ??srpppph
; sr = segment register
; pppp = port
test edx, 00010000h ; test for secondary access
jnz short WriteBufferUlongSmca
;
; PMCA access
;
mov esi,[esp+8] ; (esi) = buffer
mov ecx,[esp+12] ; (ecx) = transfer count
rep outsd
mov esi,eax
stdRET _WRITE_PORT_BUFFER_ULONG
WriteBufferUlongSmca:
;
; SMCA access
;
mov esi,[esp+8] ; (esi) = buffer
mov ecx,[esp+12] ; (ecx) = transfer count
push ebx ; save ebx
mov ebx,_NCRSegmentIoRegister ; get segment register
ror edx, 8 ; get segreg as byte in dh
pushfd
cli ; disable interrupts
mov BYTE PTR[ebx], dh ; set segment register
rol edx, 8 ; restore port
;
rep outsd
;
mov BYTE PTR[ebx], 0 ; clear segment register back to zero
popfd ; enable interrupt
pop ebx ; restore ebx
mov esi,eax
stdRET _WRITE_PORT_BUFFER_ULONG
stdENDP _WRITE_PORT_BUFFER_ULONG
_TEXT$00 ends
end