Merge io.cc and io_pro.cc (required for future VMX use)
This commit is contained in:
parent
aee488ea3a
commit
0836545037
@ -72,7 +72,6 @@ OBJS = \
|
||||
xsave.o \
|
||||
aes.o \
|
||||
soft_int.o \
|
||||
io_pro.o \
|
||||
apic.o \
|
||||
bcd.o \
|
||||
mult16.o \
|
||||
@ -467,16 +466,6 @@ io.o: io.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../bx_debug/debug.h \
|
||||
../cpu/xmm.h stack.h ../iodev/iodev.h ../iodev/vga.h \
|
||||
../iodev/svga_cirrus.h ../iodev/ioapic.h ../cpu/apic.h \
|
||||
../iodev/keyboard.h
|
||||
io_pro.o: io_pro.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../bx_debug/debug.h \
|
||||
../config.h ../osdep.h ../bxversion.h ../gui/siminterface.h \
|
||||
../memory/memory.h ../pc_system.h ../plugin.h ../extplugin.h ../ltdl.h \
|
||||
../gui/gui.h ../gui/textconfig.h ../gui/keymap.h \
|
||||
../instrument/stubs/instrument.h cpu.h ../disasm/disasm.h crregs.h \
|
||||
descriptor.h instr.h lazy_flags.h icache.h apic.h ../cpu/i387.h \
|
||||
../fpu/softfloat.h ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h \
|
||||
../cpu/xmm.h stack.h ../iodev/iodev.h ../iodev/vga.h \
|
||||
../iodev/svga_cirrus.h ../iodev/ioapic.h ../cpu/apic.h \
|
||||
../iodev/keyboard.h
|
||||
iret.o: iret.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../bx_debug/debug.h \
|
||||
../config.h ../osdep.h ../bxversion.h ../gui/siminterface.h \
|
||||
../memory/memory.h ../pc_system.h ../plugin.h ../extplugin.h ../ltdl.h \
|
||||
|
@ -1,5 +1,5 @@
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// $Id: cpu.h,v 1.549 2009-01-10 10:07:57 sshwarts Exp $
|
||||
// $Id: cpu.h,v 1.550 2009-01-15 16:53:08 sshwarts Exp $
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2001 MandrakeSoft S.A.
|
||||
@ -3142,12 +3142,6 @@ public: // for now...
|
||||
BX_SMF Bit32u force_flags(void);
|
||||
BX_SMF Bit32u read_eflags(void) { return BX_CPU_THIS_PTR force_flags(); }
|
||||
|
||||
BX_SMF Bit8u inp8(Bit16u addr) BX_CPP_AttrRegparmN(1);
|
||||
BX_SMF void outp8(Bit16u addr, Bit8u value) BX_CPP_AttrRegparmN(2);
|
||||
BX_SMF Bit16u inp16(Bit16u addr) BX_CPP_AttrRegparmN(1);
|
||||
BX_SMF void outp16(Bit16u addr, Bit16u value) BX_CPP_AttrRegparmN(2);
|
||||
BX_SMF Bit32u inp32(Bit16u addr) BX_CPP_AttrRegparmN(1);
|
||||
BX_SMF void outp32(Bit16u addr, Bit32u value) BX_CPP_AttrRegparmN(2);
|
||||
BX_SMF bx_bool allow_io(Bit16u addr, unsigned len);
|
||||
BX_SMF void parse_selector(Bit16u raw_selector, bx_selector_t *selector) BX_CPP_AttrRegparmN(2);
|
||||
BX_SMF void parse_descriptor(Bit32u dword1, Bit32u dword2, bx_descriptor_t *temp) BX_CPP_AttrRegparmN(3);
|
||||
|
202
bochs/cpu/io.cc
202
bochs/cpu/io.cc
@ -1,5 +1,5 @@
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// $Id: io.cc,v 1.70 2008-12-29 17:35:35 sshwarts Exp $
|
||||
// $Id: io.cc,v 1.71 2009-01-15 16:53:08 sshwarts Exp $
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2001 MandrakeSoft S.A.
|
||||
@ -683,60 +683,236 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::OUTSD64_DXXd(bxInstruction_c *i)
|
||||
|
||||
void BX_CPP_AttrRegparmN(1) BX_CPU_C::IN_ALIb(bxInstruction_c *i)
|
||||
{
|
||||
AL = BX_CPU_THIS_PTR inp8(i->Ib());
|
||||
unsigned port = i->Ib();
|
||||
|
||||
if (! BX_CPU_THIS_PTR allow_io(port, 1)) {
|
||||
BX_DEBUG(("IN_ALIb: I/O access not allowed !"));
|
||||
exception(BX_GP_EXCEPTION, 0, 0);
|
||||
}
|
||||
|
||||
#if BX_SUPPORT_VMX
|
||||
VMexit_IO(i, port, VMEXIT_IO_INTR_LEN(1) | VMEXIT_IO_INSTR_PORTIN | VMEXIT_IO_INSTR_IMM);
|
||||
#endif
|
||||
|
||||
AL = BX_INP(port, 1);
|
||||
}
|
||||
|
||||
void BX_CPP_AttrRegparmN(1) BX_CPU_C::IN_AXIb(bxInstruction_c *i)
|
||||
{
|
||||
AX = BX_CPU_THIS_PTR inp16(i->Ib());
|
||||
unsigned port = i->Ib();
|
||||
|
||||
if (! BX_CPU_THIS_PTR allow_io(port, 2)) {
|
||||
BX_DEBUG(("IN_AXIb: I/O access not allowed !"));
|
||||
exception(BX_GP_EXCEPTION, 0, 0);
|
||||
}
|
||||
|
||||
#if BX_SUPPORT_VMX
|
||||
VMexit_IO(i, port, VMEXIT_IO_INTR_LEN(2) | VMEXIT_IO_INSTR_PORTIN | VMEXIT_IO_INSTR_IMM);
|
||||
#endif
|
||||
|
||||
AX = BX_INP(port, 2);
|
||||
}
|
||||
|
||||
void BX_CPP_AttrRegparmN(1) BX_CPU_C::IN_EAXIb(bxInstruction_c *i)
|
||||
{
|
||||
RAX = BX_CPU_THIS_PTR inp32(i->Ib());
|
||||
unsigned port = i->Ib();
|
||||
|
||||
if (! BX_CPU_THIS_PTR allow_io(port, 4)) {
|
||||
BX_DEBUG(("IN_EAXIb: I/O access not allowed !"));
|
||||
exception(BX_GP_EXCEPTION, 0, 0);
|
||||
}
|
||||
|
||||
#if BX_SUPPORT_VMX
|
||||
VMexit_IO(i, port, VMEXIT_IO_INTR_LEN(4) | VMEXIT_IO_INSTR_PORTIN | VMEXIT_IO_INSTR_IMM);
|
||||
#endif
|
||||
|
||||
RAX = BX_INP(port, 4);
|
||||
}
|
||||
|
||||
void BX_CPP_AttrRegparmN(1) BX_CPU_C::OUT_IbAL(bxInstruction_c *i)
|
||||
{
|
||||
BX_CPU_THIS_PTR outp8(i->Ib(), AL);
|
||||
unsigned port = i->Ib();
|
||||
|
||||
if (! BX_CPU_THIS_PTR allow_io(port, 1)) {
|
||||
BX_DEBUG(("OUT_IbAL: I/O access not allowed !"));
|
||||
exception(BX_GP_EXCEPTION, 0, 0);
|
||||
}
|
||||
|
||||
#if BX_SUPPORT_VMX
|
||||
VMexit_IO(i, port, VMEXIT_IO_INTR_LEN(1) | VMEXIT_IO_INSTR_IMM);
|
||||
#endif
|
||||
|
||||
BX_OUTP(port, AL, 1);
|
||||
}
|
||||
|
||||
void BX_CPP_AttrRegparmN(1) BX_CPU_C::OUT_IbAX(bxInstruction_c *i)
|
||||
{
|
||||
BX_CPU_THIS_PTR outp16(i->Ib(), AX);
|
||||
unsigned port = i->Ib();
|
||||
|
||||
if (! BX_CPU_THIS_PTR allow_io(port, 2)) {
|
||||
BX_DEBUG(("OUT_IbAX: I/O access not allowed !"));
|
||||
exception(BX_GP_EXCEPTION, 0, 0);
|
||||
}
|
||||
|
||||
#if BX_SUPPORT_VMX
|
||||
VMexit_IO(i, port, VMEXIT_IO_INTR_LEN(2) | VMEXIT_IO_INSTR_IMM);
|
||||
#endif
|
||||
|
||||
BX_OUTP(port, AX, 2);
|
||||
}
|
||||
|
||||
void BX_CPP_AttrRegparmN(1) BX_CPU_C::OUT_IbEAX(bxInstruction_c *i)
|
||||
{
|
||||
BX_CPU_THIS_PTR outp32(i->Ib(), EAX);
|
||||
unsigned port = i->Ib();
|
||||
|
||||
if (! BX_CPU_THIS_PTR allow_io(port, 4)) {
|
||||
BX_DEBUG(("OUT_IbEAX: I/O access not allowed !"));
|
||||
exception(BX_GP_EXCEPTION, 0, 0);
|
||||
}
|
||||
|
||||
#if BX_SUPPORT_VMX
|
||||
VMexit_IO(i, port, VMEXIT_IO_INTR_LEN(4) | VMEXIT_IO_INSTR_IMM);
|
||||
#endif
|
||||
|
||||
BX_OUTP(port, EAX, 4);
|
||||
}
|
||||
|
||||
void BX_CPP_AttrRegparmN(1) BX_CPU_C::IN_ALDX(bxInstruction_c *i)
|
||||
{
|
||||
AL = BX_CPU_THIS_PTR inp8(DX);
|
||||
unsigned port = DX;
|
||||
|
||||
if (! BX_CPU_THIS_PTR allow_io(port, 1)) {
|
||||
BX_DEBUG(("IN_ALDX: I/O access not allowed !"));
|
||||
exception(BX_GP_EXCEPTION, 0, 0);
|
||||
}
|
||||
|
||||
#if BX_SUPPORT_VMX
|
||||
VMexit_IO(i, port, VMEXIT_IO_INTR_LEN(1) | VMEXIT_IO_INSTR_PORTIN);
|
||||
#endif
|
||||
|
||||
AL = BX_INP(port, 1);
|
||||
}
|
||||
|
||||
void BX_CPP_AttrRegparmN(1) BX_CPU_C::IN_AXDX(bxInstruction_c *i)
|
||||
{
|
||||
AX = BX_CPU_THIS_PTR inp16(DX);
|
||||
unsigned port = DX;
|
||||
|
||||
if (! BX_CPU_THIS_PTR allow_io(port, 2)) {
|
||||
BX_DEBUG(("IN_AXDX: I/O access not allowed !"));
|
||||
exception(BX_GP_EXCEPTION, 0, 0);
|
||||
}
|
||||
|
||||
#if BX_SUPPORT_VMX
|
||||
VMexit_IO(i, port, VMEXIT_IO_INTR_LEN(2) | VMEXIT_IO_INSTR_PORTIN);
|
||||
#endif
|
||||
|
||||
AX = BX_INP(port, 2);
|
||||
}
|
||||
|
||||
void BX_CPP_AttrRegparmN(1) BX_CPU_C::IN_EAXDX(bxInstruction_c *i)
|
||||
{
|
||||
RAX = BX_CPU_THIS_PTR inp32(DX);
|
||||
unsigned port = DX;
|
||||
|
||||
if (! BX_CPU_THIS_PTR allow_io(port, 4)) {
|
||||
BX_DEBUG(("IN_EAXDX: I/O access not allowed !"));
|
||||
exception(BX_GP_EXCEPTION, 0, 0);
|
||||
}
|
||||
|
||||
#if BX_SUPPORT_VMX
|
||||
VMexit_IO(i, port, VMEXIT_IO_INTR_LEN(4) | VMEXIT_IO_INSTR_PORTIN);
|
||||
#endif
|
||||
|
||||
RAX = BX_INP(port, 4);
|
||||
}
|
||||
|
||||
void BX_CPP_AttrRegparmN(1) BX_CPU_C::OUT_DXAL(bxInstruction_c *i)
|
||||
{
|
||||
BX_CPU_THIS_PTR outp8(DX, AL);
|
||||
unsigned port = DX;
|
||||
|
||||
if (! BX_CPU_THIS_PTR allow_io(port, 1)) {
|
||||
BX_DEBUG(("OUT_DXAL: I/O access not allowed !"));
|
||||
exception(BX_GP_EXCEPTION, 0, 0);
|
||||
}
|
||||
|
||||
#if BX_SUPPORT_VMX
|
||||
VMexit_IO(i, port, VMEXIT_IO_INTR_LEN(1));
|
||||
#endif
|
||||
|
||||
BX_OUTP(port, AL, 1);
|
||||
}
|
||||
|
||||
void BX_CPP_AttrRegparmN(1) BX_CPU_C::OUT_DXAX(bxInstruction_c *i)
|
||||
{
|
||||
BX_CPU_THIS_PTR outp16(DX, AX);
|
||||
unsigned port = DX;
|
||||
|
||||
if (! BX_CPU_THIS_PTR allow_io(port, 2)) {
|
||||
BX_DEBUG(("OUT_DXAX: I/O access not allowed !"));
|
||||
exception(BX_GP_EXCEPTION, 0, 0);
|
||||
}
|
||||
|
||||
#if BX_SUPPORT_VMX
|
||||
VMexit_IO(i, port, VMEXIT_IO_INTR_LEN(2));
|
||||
#endif
|
||||
|
||||
BX_OUTP(port, AX, 2);
|
||||
}
|
||||
|
||||
void BX_CPP_AttrRegparmN(1) BX_CPU_C::OUT_DXEAX(bxInstruction_c *i)
|
||||
{
|
||||
BX_CPU_THIS_PTR outp32(DX, EAX);
|
||||
unsigned port = DX;
|
||||
|
||||
if (! BX_CPU_THIS_PTR allow_io(port, 4)) {
|
||||
BX_DEBUG(("OUT_DXEAX: I/O access not allowed !"));
|
||||
exception(BX_GP_EXCEPTION, 0, 0);
|
||||
}
|
||||
|
||||
#if BX_SUPPORT_VMX
|
||||
VMexit_IO(i, port, VMEXIT_IO_INTR_LEN(4));
|
||||
#endif
|
||||
|
||||
BX_OUTP(port, EAX, 4);
|
||||
}
|
||||
|
||||
bx_bool BX_CPU_C::allow_io(Bit16u port, unsigned len)
|
||||
{
|
||||
/* If CPL <= IOPL, then all IO portesses are accessible.
|
||||
* Otherwise, must check the IO permission map on >286.
|
||||
* On the 286, there is no IO permissions map */
|
||||
|
||||
if (BX_CPU_THIS_PTR cr0.get_PE() && (BX_CPU_THIS_PTR get_VM() || (CPL>BX_CPU_THIS_PTR get_IOPL())))
|
||||
{
|
||||
if (BX_CPU_THIS_PTR tr.cache.valid==0 ||
|
||||
(BX_CPU_THIS_PTR tr.cache.type != BX_SYS_SEGMENT_AVAIL_386_TSS &&
|
||||
BX_CPU_THIS_PTR tr.cache.type != BX_SYS_SEGMENT_BUSY_386_TSS))
|
||||
{
|
||||
BX_ERROR(("allow_io(): TR doesn't point to a valid 32bit TSS, TR.TYPE=%u", BX_CPU_THIS_PTR tr.cache.type));
|
||||
return(0);
|
||||
}
|
||||
|
||||
if (BX_CPU_THIS_PTR tr.cache.u.system.limit_scaled < 103) {
|
||||
BX_ERROR(("allow_io(): TR.limit < 103"));
|
||||
return(0);
|
||||
}
|
||||
|
||||
Bit16u io_base = system_read_word(BX_CPU_THIS_PTR tr.cache.u.system.base + 102);
|
||||
|
||||
if ((io_base + port/8) >= BX_CPU_THIS_PTR tr.cache.u.system.limit_scaled) {
|
||||
BX_DEBUG(("allow_io(): IO port %x (len %d) outside TSS IO permission map (base=%x, limit=%x) #GP(0)",
|
||||
port, len, io_base, BX_CPU_THIS_PTR tr.cache.u.system.limit_scaled));
|
||||
return(0);
|
||||
}
|
||||
|
||||
Bit16u permission16 = system_read_word(BX_CPU_THIS_PTR tr.cache.u.system.base + io_base + port/8);
|
||||
|
||||
unsigned bit_index = port & 0x7;
|
||||
unsigned mask = (1 << len) - 1;
|
||||
if ((permission16 >> bit_index) & mask)
|
||||
return(0);
|
||||
}
|
||||
|
||||
#if BX_X86_DEBUGGER
|
||||
iobreakpoint_match(port, len);
|
||||
#endif
|
||||
|
||||
return(1);
|
||||
}
|
||||
|
@ -1,147 +0,0 @@
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// $Id: io_pro.cc,v 1.39 2008-09-14 20:58:20 sshwarts Exp $
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2001 MandrakeSoft S.A.
|
||||
//
|
||||
// MandrakeSoft S.A.
|
||||
// 43, rue d'Aboukir
|
||||
// 75002 Paris - France
|
||||
// http://www.linux-mandrake.com/
|
||||
// http://www.mandrakesoft.com/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 2 of the License, or (at your option) any later version.
|
||||
//
|
||||
// This library 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. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#define NEED_CPU_REG_SHORTCUTS 1
|
||||
#include "bochs.h"
|
||||
#include "cpu.h"
|
||||
#define LOG_THIS BX_CPU_THIS_PTR
|
||||
|
||||
#include "iodev/iodev.h"
|
||||
|
||||
Bit16u BX_CPP_AttrRegparmN(1)
|
||||
BX_CPU_C::inp16(Bit16u port)
|
||||
{
|
||||
if (! BX_CPU_THIS_PTR allow_io(port, 2)) {
|
||||
BX_DEBUG(("inp16(): I/O access not allowed !"));
|
||||
exception(BX_GP_EXCEPTION, 0, 0);
|
||||
}
|
||||
|
||||
Bit16u ret16 = BX_INP(port, 2);
|
||||
return ret16;
|
||||
}
|
||||
|
||||
void BX_CPP_AttrRegparmN(2)
|
||||
BX_CPU_C::outp16(Bit16u port, Bit16u value)
|
||||
{
|
||||
if (! BX_CPU_THIS_PTR allow_io(port, 2)) {
|
||||
BX_DEBUG(("outp16(): I/O access not allowed !"));
|
||||
exception(BX_GP_EXCEPTION, 0, 0);
|
||||
}
|
||||
|
||||
BX_OUTP(port, value, 2);
|
||||
}
|
||||
|
||||
Bit32u BX_CPP_AttrRegparmN(1)
|
||||
BX_CPU_C::inp32(Bit16u port)
|
||||
{
|
||||
if (! BX_CPU_THIS_PTR allow_io(port, 4)) {
|
||||
BX_DEBUG(("inp32(): I/O access not allowed !"));
|
||||
exception(BX_GP_EXCEPTION, 0, 0);
|
||||
}
|
||||
|
||||
Bit32u ret32 = BX_INP(port, 4);
|
||||
return ret32;
|
||||
}
|
||||
|
||||
void BX_CPP_AttrRegparmN(2)
|
||||
BX_CPU_C::outp32(Bit16u port, Bit32u value)
|
||||
{
|
||||
if (! BX_CPU_THIS_PTR allow_io(port, 4)) {
|
||||
BX_DEBUG(("outp32(): I/O access not allowed !"));
|
||||
exception(BX_GP_EXCEPTION, 0, 0);
|
||||
}
|
||||
|
||||
BX_OUTP(port, value, 4);
|
||||
}
|
||||
|
||||
Bit8u BX_CPP_AttrRegparmN(1)
|
||||
BX_CPU_C::inp8(Bit16u port)
|
||||
{
|
||||
if (! BX_CPU_THIS_PTR allow_io(port, 1)) {
|
||||
BX_DEBUG(("inp8(): I/O access not allowed !"));
|
||||
exception(BX_GP_EXCEPTION, 0, 0);
|
||||
}
|
||||
|
||||
Bit8u ret8 = BX_INP(port, 1);
|
||||
return ret8;
|
||||
}
|
||||
|
||||
void BX_CPP_AttrRegparmN(2)
|
||||
BX_CPU_C::outp8(Bit16u port, Bit8u value)
|
||||
{
|
||||
if (! BX_CPU_THIS_PTR allow_io(port, 1)) {
|
||||
BX_DEBUG(("outp8(): I/O access not allowed !"));
|
||||
exception(BX_GP_EXCEPTION, 0, 0);
|
||||
}
|
||||
|
||||
BX_OUTP(port, value, 1);
|
||||
}
|
||||
|
||||
bx_bool BX_CPU_C::allow_io(Bit16u port, unsigned len)
|
||||
{
|
||||
/* If CPL <= IOPL, then all IO portesses are accessible.
|
||||
* Otherwise, must check the IO permission map on >286.
|
||||
* On the 286, there is no IO permissions map */
|
||||
|
||||
if (BX_CPU_THIS_PTR cr0.get_PE() && (BX_CPU_THIS_PTR get_VM() || (CPL>BX_CPU_THIS_PTR get_IOPL())))
|
||||
{
|
||||
if (BX_CPU_THIS_PTR tr.cache.valid==0 ||
|
||||
(BX_CPU_THIS_PTR tr.cache.type != BX_SYS_SEGMENT_AVAIL_386_TSS &&
|
||||
BX_CPU_THIS_PTR tr.cache.type != BX_SYS_SEGMENT_BUSY_386_TSS))
|
||||
{
|
||||
BX_ERROR(("allow_io(): TR doesn't point to a valid 32bit TSS, TR.TYPE=%u", BX_CPU_THIS_PTR tr.cache.type));
|
||||
return(0);
|
||||
}
|
||||
|
||||
if (BX_CPU_THIS_PTR tr.cache.u.system.limit_scaled < 103) {
|
||||
BX_ERROR(("allow_io(): TR.limit < 103"));
|
||||
return(0);
|
||||
}
|
||||
|
||||
Bit16u io_base = system_read_word(BX_CPU_THIS_PTR tr.cache.u.system.base + 102);
|
||||
|
||||
if ((io_base + port/8) >= BX_CPU_THIS_PTR tr.cache.u.system.limit_scaled) {
|
||||
BX_DEBUG(("allow_io(): IO port %x (len %d) outside TSS IO permission map (base=%x, limit=%x) #GP(0)",
|
||||
port, len, io_base, BX_CPU_THIS_PTR tr.cache.u.system.limit_scaled));
|
||||
return(0);
|
||||
}
|
||||
|
||||
Bit16u permission16 = system_read_word(BX_CPU_THIS_PTR tr.cache.u.system.base + io_base + port/8);
|
||||
|
||||
unsigned bit_index = port & 0x7;
|
||||
unsigned mask = (1 << len) - 1;
|
||||
if ((permission16 >> bit_index) & mask)
|
||||
return(0);
|
||||
}
|
||||
|
||||
#if BX_X86_DEBUGGER
|
||||
iobreakpoint_match(port, len);
|
||||
#endif
|
||||
|
||||
return(1);
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user