{ This file is part of the Free Pascal run time library. Copyright (c) 1997-2004 by the Free Pascal development team Some x86 specific stuff. Has to be fixed still for *BSD See the file COPYING.FPC, included in this distribution, for details about the copyright. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. **********************************************************************} unit x86; interface Uses BaseUnix; function ReadPortB (Port : Longint): Byte; function ReadPortW (Port : Longint): Word; function ReadPortL (Port : Longint): Longint; Procedure ReadPort (Port : Longint; Var Value : Byte); Procedure ReadPort (Port : Longint; Var Value : Longint); Procedure ReadPort (Port : Longint; Var Value : Word); Procedure ReadPortB (Port : Longint; Var Buf; Count: longint); Procedure ReadPortL (Port : Longint; Var Buf; Count: longint); Procedure ReadPortW (Port : Longint; Var Buf; Count: longint); Procedure WritePort (Port : Longint; Value : Byte); Procedure WritePort (Port : Longint; Value : Longint); Procedure WritePort (Port : Longint; Value : Word); Procedure WritePortB (Port : Longint; Value : Byte); Procedure WritePortB (Port : Longint; Var Buf; Count: longint); Procedure WritePortL (Port : Longint; Value : Longint); Procedure WritePortW (Port : Longint; Value : Word); Procedure WritePortW (Port : Longint; Var Buf; Count: longint); Procedure WritePortl (Port : Longint; Var Buf; Count: longint); Function fpIOperm (From,Num : Cardinal; Value : cint) : cint; Function fpIoPL(Level : cint) : cint; implementation {$ASMMODE ATT} Uses Syscall; Procedure WritePort (Port : Longint; Value : Byte); { Writes 'Value' to port 'Port' } begin asm {$ifdef CPU386} movl port,%edx movb value,%al outb %al,%dx {$endif CPU386} {$ifdef CPUX86_64} movl port,%edx movb value,%al outb %al,%dx {$endif CPUX86_64} end; end; Procedure WritePort (Port : Longint; Value : Word); { Writes 'Value' to port 'Port' } begin asm {$ifdef CPU386} movl port,%edx movw value,%ax outw %ax,%dx {$endif CPU386} {$ifdef CPUX86_64} movl port,%edx movw value,%ax outw %ax,%dx {$endif CPUX86_64} end; end; Procedure WritePort (Port : Longint; Value : Longint); { Writes 'Value' to port 'Port' } begin asm {$ifdef CPU386} movl port,%edx movl value,%eax outl %eax,%dx {$endif CPU386} {$ifdef CPUX86_64} movl port,%edx movl value,%eax outl %eax,%dx {$endif CPUX86_64} end; end; Procedure WritePortB (Port : Longint; Value : Byte); { Writes 'Value' to port 'Port' } begin asm {$ifdef CPU386} movl port,%edx movb value,%al outb %al,%dx {$endif CPU386} {$ifdef CPUX86_64} movl port,%edx movb value,%al outb %al,%dx {$endif CPUX86_64} end; end; Procedure WritePortW (Port : Longint; Value : Word); { Writes 'Value' to port 'Port' } begin asm {$ifdef CPU386} movl port,%edx movw value,%ax outw %ax,%dx {$endif CPU386} {$ifdef CPUX86_64} movl port,%edx movw value,%ax outw %ax,%dx {$endif CPUX86_64} end; end; Procedure WritePortL (Port : Longint; Value : Longint); { Writes 'Value' to port 'Port' } begin asm {$ifdef CPU386} movl port,%edx movl value,%eax outl %eax,%dx {$endif CPU386} {$ifdef CPUX86_64} movl port,%edx movl value,%eax outl %eax,%dx {$endif CPUX86_64} end; end; Procedure WritePortl (Port : Longint; Var Buf; Count: longint); { Writes 'Count' longints from 'Buf' to Port } begin asm {$ifdef CPU386} movl count,%ecx movl buf,%esi movl port,%edx cld rep outsl {$endif CPU386} {$ifdef CPUX86_64} movl count,%ecx movq buf,%rsi movl port,%edx cld rep outsl {$endif CPUX86_64} end; end; Procedure WritePortW (Port : Longint; Var Buf; Count: longint); { Writes 'Count' words from 'Buf' to Port } begin asm {$ifdef CPU386} movl count,%ecx movl buf,%esi movl port,%edx cld rep outsw {$endif CPU386} {$ifdef CPUX86_64} movl count,%ecx movq buf,%rsi movl port,%edx cld rep outsw {$endif CPUX86_64} end; end; Procedure WritePortB (Port : Longint; Var Buf; Count: longint); { Writes 'Count' bytes from 'Buf' to Port } begin asm {$ifdef CPU386} movl count,%ecx movl buf,%esi movl port,%edx cld rep outsb {$endif CPU386} {$ifdef CPUX86_64} movl count,%ecx movq buf,%rsi movl port,%edx cld rep outsb {$endif CPUX86_64} end; end; Procedure ReadPort (Port : Longint; Var Value : Byte); { Reads 'Value' from port 'Port' } begin asm {$ifdef CPU386} movl port,%edx inb %dx,%al movl value,%edx movb %al,(%edx) {$endif CPU386} {$ifdef CPUX86_64} movl port,%edx inb %dx,%al movq value,%rdx movb %al,(%rdx) {$endif CPUX86_64} end; end; Procedure ReadPort (Port : Longint; Var Value : Word); { Reads 'Value' from port 'Port' } begin asm {$ifdef CPU386} movl port,%edx inw %dx,%ax movl value,%edx movw %ax,(%edx) {$endif CPU386} {$ifdef CPUX86_64} movl port,%edx inw %dx,%ax movq value,%rdx movw %ax,(%rdx) {$endif CPUX86_64} end; end; Procedure ReadPort (Port : Longint; Var Value : Longint); { Reads 'Value' from port 'Port' } begin asm {$ifdef CPU386} movl port,%edx inl %dx,%eax movl value,%edx movl %eax,(%edx) {$endif CPU386} {$ifdef CPUX86_64} movl port,%edx inl %dx,%eax movq value,%rdx movl %eax,(%rdx) {$endif CPUX86_64} end; end; function ReadPortB (Port : Longint): Byte; assembler; { Reads a byte from port 'Port' } asm {$ifdef CPU386} movl port,%edx xorl %eax,%eax inb %dx,%al {$endif CPU386} {$ifdef CPUX86_64} movl port,%edx xorl %eax,%eax inb %dx,%al {$endif CPUX86_64} end; function ReadPortW (Port : Longint): Word; assembler; { Reads a word from port 'Port' } asm {$ifdef CPU386} movl port,%edx xorl %eax,%eax inw %dx,%ax {$endif CPU386} {$ifdef CPUX86_64} movl port,%edx xorl %eax,%eax inw %dx,%ax {$endif CPUX86_64} end; function ReadPortL (Port : Longint): LongInt; assembler; { Reads a LongInt from port 'Port' } asm {$ifdef CPU386} movl port,%edx inl %dx,%eax {$endif CPU386} {$ifdef CPUX86_64} movl port,%edx inl %dx,%eax {$endif CPUX86_64} end; Procedure ReadPortL (Port : Longint; Var Buf; Count: longint); { Reads 'Count' longints from port 'Port' to 'Buf'. } begin asm {$ifdef CPU386} movl count,%ecx movl buf,%edi movl port,%edx cld rep insl {$endif CPU386} {$ifdef CPUX86_64} movl count,%ecx movq buf,%rdi movl port,%edx cld rep insl {$endif CPUX86_64} end; end; Procedure ReadPortW (Port : Longint; Var Buf; Count: longint); { Reads 'Count' words from port 'Port' to 'Buf'. } begin asm {$ifdef CPU386} movl count,%ecx movl buf,%edi movl port,%edx cld rep insw {$endif CPU386} {$ifdef CPUX86_64} movl count,%ecx movq buf,%rdi movl port,%edx cld rep insw {$endif CPUX86_64} end; end; Procedure ReadPortB (Port : Longint; Var Buf; Count: longint); { Reads 'Count' bytes from port 'Port' to 'Buf'. } begin asm {$ifdef CPU386} movl count,%ecx movl buf,%edi movl port,%edx cld rep insb {$endif CPU386} {$ifdef CPUX86_64} movl count,%ecx movq buf,%rdi movl port,%edx cld rep insb {$endif CPUX86_64} end; end; {$if defined(linux) or defined(android)} Function fpIOperm (From,Num : Cardinal; Value : cint) : cint; { Set permissions on NUM ports starting with port FROM to VALUE this works ONLY as root. } begin fpIOPerm:=do_Syscall(Syscall_nr_ioperm,TSysParam(From),TSysParam(Num),TSysParam(Value)); end; {$else} {$packrecords C} TYPE uint=CARDINAL; CONST I386_GET_LDT =0; I386_SET_LDT =1; { I386_IOPL } I386_GET_IOPERM =3; I386_SET_IOPERM =4; { xxxxx } I386_VM86 =6; type { i386_ldt_args = record int start : longint; union descriptor *descs; int num; end; } i386_ioperm_args = record start : cuint; length : cuint; enable : cint; end; i386_vm86_args = record sub_op : cint; { sub-operation to perform } sub_args : pchar; { args } end; sysarch_args = record op : longint; parms : pchar; end; Function fpIOPerm(From,Num:CARDINAL;Value:cint):cint; var sg : i386_ioperm_args; sa : sysarch_args; begin sg.start:=From; sg.length:=Num; sg.enable:=value; sa.op:=i386_SET_IOPERM; sa.parms:=@sg; fpIOPerm:=do_syscall(syscall_nr_sysarch,TSysParam(@sa)); end; {$endif} Function fpIoPL(Level : cint) : cint; begin {$ifdef Linux} fpIOPL:=do_Syscall(Syscall_nr_iopl,TSysParam(Level)); {$else} fpIOPL:=-1; FpSetErrNo(ESysENoSys); {$endif} end; end.