mirror of
https://github.com/reactos/reactos.git
synced 2025-02-22 08:25:03 +00:00
- Fixup all the file headers with proper paths and authors.
- Move sysbus.c contents (a 4 line function) into bus.c. - Unify initialization code. - Delete and disable stall execution calibration (currently using the default). Will implement later in a more precise manner (this routine was bizarly setting the MHz of the CPU in the PRCB in some cases...). svn path=/trunk/; revision=24964
This commit is contained in:
parent
f09a042483
commit
d466efb4fb
19 changed files with 68 additions and 262 deletions
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* PROJECT: ReactOS HAL
|
||||
* LICENSE: GPL - See COPYING in the top level directory
|
||||
* FILE: ntoskrnl/hal/x86/beep.c
|
||||
* FILE: hal/halx86/generic/beep.c
|
||||
* PURPOSE: Speaker support (beeping)
|
||||
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
|
||||
* Eric Kohl (ekohl@abo.rhein-zeitung.de)
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* PROJECT: ReactOS HAL
|
||||
* LICENSE: GPL - See COPYING in the top level directory
|
||||
* FILE: ntoskrnl/hal/halx86/generic/bus.c
|
||||
* FILE: hal/halx86/generic/bus.c
|
||||
* PURPOSE: Bus Support Routines
|
||||
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
|
||||
*/
|
||||
|
@ -63,6 +63,20 @@ HalpTranslateBusAddress(IN INTERFACE_TYPE InterfaceType,
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
ULONG
|
||||
NTAPI
|
||||
HalpGetSystemInterruptVector(IN ULONG BusNumber,
|
||||
IN ULONG BusInterruptLevel,
|
||||
IN ULONG BusInterruptVector,
|
||||
OUT PKIRQL Irql,
|
||||
OUT PKAFFINITY Affinity)
|
||||
{
|
||||
ULONG Vector = IRQ2VECTOR(BusInterruptVector);
|
||||
*Irql = (KIRQL)VECTOR2IRQL(Vector);
|
||||
*Affinity = 0xFFFFFFFF;
|
||||
return Vector;
|
||||
}
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
HalpInitNonBusHandler(VOID)
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
/*
|
||||
* PROJECT: ReactOS HAL
|
||||
* LICENSE: GPL - See COPYING in the top level directory
|
||||
* FILE: ntoskrnl/hal/halx86/generic/cmos.c
|
||||
* FILE: hal/halx86/generic/cmos.c
|
||||
* PURPOSE: CMOS Access Routines (Real Time Clock and LastKnownGood)
|
||||
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
|
||||
* Eric Kohl (ekohl@abo.rhein-zeitung.de)
|
||||
*/
|
||||
|
||||
/* INCLUDES ******************************************************************/
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* PROJECT: ReactOS HA:
|
||||
* PROJECT: ReactOS HAL
|
||||
* LICENSE: GPL - See COPYING in the top level directory
|
||||
* FILE: ntoskrnl/hal/halx86/generic/display.c
|
||||
* FILE: hal/halx86/generic/display.c
|
||||
* PURPOSE: Screen Display Routines, now useless since NT 5.1+
|
||||
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
|
||||
*/
|
||||
|
@ -11,7 +11,7 @@
|
|||
#include <debug.h>
|
||||
#include <ndk/inbvfuncs.h>
|
||||
|
||||
/* PUBLIC FUNCTIONS *********************************************************/
|
||||
/* PUBLIC FUNCTIONS **********************************************************/
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* PROJECT: ReactOS HA:
|
||||
* PROJECT: ReactOS HAL
|
||||
* LICENSE: GPL - See COPYING in the top level directory
|
||||
* FILE: ntoskrnl/hal/halx86/drive.c
|
||||
* FILE: hal/halx86/generic/drive.c
|
||||
* PURPOSE: I/O HAL Routines for Disk Access
|
||||
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
|
||||
*/
|
||||
|
|
|
@ -14,7 +14,6 @@
|
|||
<file>pci.c</file>
|
||||
<file>portio.c</file>
|
||||
<file>reboot.c</file>
|
||||
<file>sysbus.c</file>
|
||||
<file>sysinfo.c</file>
|
||||
<file>timer.c</file>
|
||||
<file>systimer.S</file>
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
* PROJECT: ReactOS HAL
|
||||
* LICENSE: GPL - See COPYING in the top level directory
|
||||
* FILE: ntoskrnl/hal/halx86/generic/processor.c
|
||||
* PURPOSE: HAL Processor Routines
|
||||
* FILE: hal/halx86/generic/halinit.c
|
||||
* PURPOSE: HAL Entrypoint and Initialization
|
||||
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
|
||||
*/
|
||||
|
||||
|
@ -92,8 +92,17 @@ HalInitSystem(IN ULONG BootPhase,
|
|||
KeBugCheckEx(MISMATCHED_HAL, 1, Prcb->MajorVersion, 1, 0);
|
||||
}
|
||||
|
||||
/* Continue with HAL-specific initialization */
|
||||
HalpInitPhase0(LoaderBlock);
|
||||
/* Initialize the PICs */
|
||||
HalpInitPICs();
|
||||
|
||||
/* Force initial PIC state */
|
||||
KfRaiseIrql(KeGetCurrentIrql());
|
||||
|
||||
/* Initialize the clock */
|
||||
HalpInitializeClock();
|
||||
|
||||
/* Setup busy waiting */
|
||||
//HalpCalibrateStallExecution();
|
||||
|
||||
/* Fill out the dispatch tables */
|
||||
HalQuerySystemInformation = HaliQuerySystemInformation;
|
||||
|
@ -110,8 +119,12 @@ HalInitSystem(IN ULONG BootPhase,
|
|||
/* Initialize the default HAL stubs for bus handling functions */
|
||||
HalpInitNonBusHandler();
|
||||
|
||||
/* Initialize the clock interrupt */
|
||||
HalpInitPhase1();
|
||||
/* Enable the clock interrupt */
|
||||
((PKIPCR)KeGetPcr())->IDT[0x30].ExtendedOffset =
|
||||
(USHORT)(((ULONG_PTR)HalpClockInterrupt >> 16) & 0xFFFF);
|
||||
((PKIPCR)KeGetPcr())->IDT[0x30].Offset =
|
||||
(USHORT)HalpClockInterrupt;
|
||||
HalEnableSystemInterrupt(0x30, CLOCK2_LEVEL, Latched);
|
||||
|
||||
/* Initialize DMA. NT does this in Phase 0 */
|
||||
HalpInitDma();
|
||||
|
@ -122,7 +135,7 @@ HalInitSystem(IN ULONG BootPhase,
|
|||
}
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
* @unimplemented
|
||||
*/
|
||||
VOID
|
||||
NTAPI
|
||||
|
@ -137,5 +150,4 @@ HalReportResourceUsage(VOID)
|
|||
/* FIXME: Report HAL Usage to kernel */
|
||||
}
|
||||
|
||||
|
||||
/* EOF */
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* PROJECT: ReactOS HAL
|
||||
* LICENSE: GPL - See COPYING in the top level directory
|
||||
* FILE: ntoskrnl/hal/halx86/misc.c
|
||||
* FILE: hal/halx86/generic/misc.c
|
||||
* PURPOSE: Miscellanous Routines
|
||||
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
|
||||
* Eric Kohl (ekohl@abo.rhein-zeitung.de)
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* PROJECT: ReactOS HAL
|
||||
* LICENSE: GPL - See COPYING in the top level directory
|
||||
* FILE: ntoskrnl/hal/halx86/generic/pci.c
|
||||
* FILE: hal/halx86/generic/pci.c
|
||||
* PURPOSE: PCI Bus Support (Configuration Space, Resource Allocation)
|
||||
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
|
||||
*/
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
/*
|
||||
* PROJECT: ReactOS HAL
|
||||
* LICENSE: GPL - See COPYING in the top level directory
|
||||
* FILE: ntoskrnl/hal/x86/portio.c
|
||||
* PURPOSE: I/O Functions for access to ports
|
||||
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
|
||||
*/
|
||||
* PROJECT: ReactOS HAL
|
||||
* LICENSE: GPL - See COPYING in the top level directory
|
||||
* FILE: hal/halx86/generic/portio.c
|
||||
* PURPOSE: I/O Functions for access to ports
|
||||
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
|
||||
*/
|
||||
|
||||
/* INCLUDES ******************************************************************/
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* PROJECT: ReactOS HAL
|
||||
* LICENSE: GPL - See COPYING in the top level directory
|
||||
* FILE: ntoskrnl/hal/halx86/generic/processor.c
|
||||
* FILE: hal/halx86/up/processor.c
|
||||
* PURPOSE: HAL Processor Routines
|
||||
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
|
||||
*/
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* PROJECT: ReactOS HAL
|
||||
* LICENSE: GPL - See COPYING in the top level directory
|
||||
* FILE: ntoskrnl/hal/x86/reboot.c
|
||||
* FILE: hal/halx86/generic/reboot.c
|
||||
* PURPOSE: Reboot functions
|
||||
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
|
||||
* Eric Kohl (ekohl@abo.rhein-zeitung.de)
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS kernel
|
||||
* FILE: ntoskrnl/hal/halx86/up/spinlock.c
|
||||
* PURPOSE: Implements spinlocks
|
||||
* PROGRAMMER: Alex Ionescu (alex@relsoft.net)
|
||||
* PROJECT: ReactOS HAL
|
||||
* LICENSE: GPL - See COPYING in the top level directory
|
||||
* FILE: hal/halx86/up/spinlock.c
|
||||
* PURPOSE: Spinlock and Queued Spinlock Support
|
||||
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
|
||||
*/
|
||||
|
||||
/* INCLUDES ****************************************************************/
|
||||
/* INCLUDES ******************************************************************/
|
||||
|
||||
#include <hal.h>
|
||||
#define NDEBUG
|
||||
|
@ -17,7 +17,7 @@
|
|||
#undef KeLowerIrql
|
||||
#undef KeRaiseIrql
|
||||
|
||||
/* FUNCTIONS ***************************************************************/
|
||||
/* FUNCTIONS *****************************************************************/
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
|
@ -199,5 +199,4 @@ KeTryToAcquireQueuedSpinLock(IN KSPIN_LOCK_QUEUE_NUMBER LockNumber,
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/* EOF */
|
||||
|
|
|
@ -1,34 +0,0 @@
|
|||
/* $Id$
|
||||
*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS kernel
|
||||
* FILE: ntoskrnl/hal/sysbus.c
|
||||
* PURPOSE: System bus handler functions
|
||||
* PROGRAMMER: Eric Kohl (ekohl@rz-online.de)
|
||||
* UPDATE HISTORY:
|
||||
* 09/04/2000 Created
|
||||
*/
|
||||
|
||||
/* INCLUDES *****************************************************************/
|
||||
|
||||
#include <hal.h>
|
||||
#define NDEBUG
|
||||
#include <debug.h>
|
||||
|
||||
/* FUNCTIONS ****************************************************************/
|
||||
|
||||
ULONG
|
||||
NTAPI
|
||||
HalpGetSystemInterruptVector(ULONG BusNumber,
|
||||
ULONG BusInterruptLevel,
|
||||
ULONG BusInterruptVector,
|
||||
PKIRQL Irql,
|
||||
PKAFFINITY Affinity)
|
||||
{
|
||||
ULONG Vector = IRQ2VECTOR(BusInterruptVector);
|
||||
*Irql = (KIRQL)VECTOR2IRQL(Vector);
|
||||
*Affinity = 0xFFFFFFFF;
|
||||
return Vector;
|
||||
}
|
||||
|
||||
/* EOF */
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* PROJECT: ReactOS HA:
|
||||
* LICENSE: GPL - See COPYING in the top level directory
|
||||
* FILE: ntoskrnl/hal/halx86/generic/sysinfo.c
|
||||
* FILE: hal/halx86/generic/sysinfo.c
|
||||
* PURPOSE: HAL Information Routines
|
||||
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
|
||||
*/
|
||||
|
|
|
@ -236,7 +236,6 @@ Spurious:
|
|||
|
||||
/* Exit the interrupt */
|
||||
add esp, 8
|
||||
mov esi, $
|
||||
jmp _Kei386EoiHelper@0
|
||||
.endfunc
|
||||
|
||||
|
|
|
@ -1,49 +1,17 @@
|
|||
/*
|
||||
* ReactOS kernel
|
||||
* Copyright (C) 2000 David Welch <welch@cwcom.net>
|
||||
* Copyright (C) 1999 Gareth Owen <gaz@athene.co.uk>, Ramon von Handel
|
||||
* Copyright (C) 1991, 1992 Linus Torvalds
|
||||
*
|
||||
* This software is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This software 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
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this software; see the file COPYING. If not, write
|
||||
* to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge,
|
||||
* MA 02139, USA.
|
||||
*
|
||||
*/
|
||||
/* $Id$
|
||||
*
|
||||
* PROJECT: ReactOS kernel
|
||||
* FILE: ntoskrnl/hal/x86/udelay.c
|
||||
* PURPOSE: Busy waiting
|
||||
* PROGRAMMER: David Welch (david.welch@seh.ox.ac.uk)
|
||||
* UPDATE HISTORY:
|
||||
* 06/11/99 Created
|
||||
* PROJECT: ReactOS HAL
|
||||
* LICENSE: GPL - See COPYING in the top level directory
|
||||
* FILE: hal/halx86/generic/timer.c
|
||||
* PURPOSE: HAL Timer Routines
|
||||
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
|
||||
*/
|
||||
|
||||
/* INCLUDES ***************************************************************/
|
||||
/* INCLUDES ******************************************************************/
|
||||
|
||||
#include <hal.h>
|
||||
#define NDEBUG
|
||||
#include <debug.h>
|
||||
|
||||
/* GLOBALS ******************************************************************/
|
||||
|
||||
#define MILLISEC 10 /* Number of millisec between interrupts */
|
||||
#define HZ (1000 / MILLISEC) /* Number of interrupts per second */
|
||||
#define CLOCK_TICK_RATE 1193182 /* Clock frequency of the timer chip */
|
||||
#define LATCH (CLOCK_TICK_RATE / HZ) /* Count to program into the timer chip */
|
||||
#define PRECISION 8 /* Number of bits to calibrate for delay loop */
|
||||
|
||||
/* GLOBALS *******************************************************************/
|
||||
|
||||
BOOLEAN HalpClockSetMSRate;
|
||||
|
@ -158,140 +126,4 @@ HalSetTimeIncrement(IN ULONG Increment)
|
|||
return HalpRolloverTable[Increment - 1].HighPart;
|
||||
}
|
||||
|
||||
/* STUFF *********************************************************************/
|
||||
|
||||
ULONG
|
||||
FORCEINLINE
|
||||
Read8254Timer(VOID)
|
||||
{
|
||||
ULONG Count;
|
||||
|
||||
/* Disable interrupts */
|
||||
_disable();
|
||||
|
||||
/* Set the rollover */
|
||||
__outbyte(TIMER_CONTROL_PORT, TIMER_SC0);
|
||||
Count = __inbyte(TIMER_DATA_PORT0);
|
||||
Count |= __inbyte(TIMER_DATA_PORT0) << 8;
|
||||
|
||||
/* Restore interrupts and return count*/
|
||||
_enable();
|
||||
return Count;
|
||||
}
|
||||
|
||||
VOID WaitFor8254Wraparound(VOID)
|
||||
{
|
||||
ULONG CurCount, PrevCount = ~0;
|
||||
LONG Delta;
|
||||
|
||||
CurCount = Read8254Timer();
|
||||
|
||||
do
|
||||
{
|
||||
PrevCount = CurCount;
|
||||
CurCount = Read8254Timer();
|
||||
Delta = CurCount - PrevCount;
|
||||
|
||||
/*
|
||||
* This limit for delta seems arbitrary, but it isn't, it's
|
||||
* slightly above the level of error a buggy Mercury/Neptune
|
||||
* chipset timer can cause.
|
||||
*/
|
||||
|
||||
}
|
||||
while (Delta < 300);
|
||||
}
|
||||
|
||||
VOID HalpCalibrateStallExecution(VOID)
|
||||
{
|
||||
ULONG i;
|
||||
ULONG calib_bit;
|
||||
ULONG CurCount;
|
||||
PKIPCR Pcr;
|
||||
LARGE_INTEGER StartCount, EndCount;
|
||||
|
||||
Pcr = (PKIPCR)KeGetPcr();
|
||||
|
||||
if (Pcr->PrcbData.FeatureBits & KF_RDTSC)
|
||||
{
|
||||
|
||||
WaitFor8254Wraparound();
|
||||
StartCount.QuadPart = (LONGLONG)__rdtsc();
|
||||
|
||||
WaitFor8254Wraparound();
|
||||
EndCount.QuadPart = (LONGLONG)__rdtsc();
|
||||
|
||||
Pcr->PrcbData.MHz = (ULONG)(EndCount.QuadPart - StartCount.QuadPart) / 10000;
|
||||
DPRINT("%luMHz\n", Pcr->PrcbData.MHz);
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
DPRINT("Calibrating delay loop... [");
|
||||
|
||||
/* Stage 1: Coarse calibration */
|
||||
|
||||
WaitFor8254Wraparound();
|
||||
|
||||
Pcr->StallScaleFactor = 1;
|
||||
|
||||
do
|
||||
{
|
||||
Pcr->StallScaleFactor <<= 1; /* Next delay count to try */
|
||||
|
||||
WaitFor8254Wraparound();
|
||||
|
||||
KeStallExecutionProcessor(Pcr->StallScaleFactor); /* Do the delay */
|
||||
|
||||
CurCount = Read8254Timer();
|
||||
}
|
||||
while (CurCount > LATCH / 2);
|
||||
|
||||
Pcr->StallScaleFactor >>= 1; /* Get bottom value for delay */
|
||||
|
||||
/* Stage 2: Fine calibration */
|
||||
DPRINT("delay_count: %d", Pcr->StallScaleFactor);
|
||||
|
||||
calib_bit = Pcr->StallScaleFactor; /* Which bit are we going to test */
|
||||
|
||||
for (i = 0; i < PRECISION; i++)
|
||||
{
|
||||
calib_bit >>= 1; /* Next bit to calibrate */
|
||||
if (!calib_bit)
|
||||
{
|
||||
break; /* If we have done all bits, stop */
|
||||
}
|
||||
|
||||
Pcr->StallScaleFactor |= calib_bit; /* Set the bit in delay_count */
|
||||
|
||||
WaitFor8254Wraparound();
|
||||
|
||||
KeStallExecutionProcessor(Pcr->StallScaleFactor); /* Do the delay */
|
||||
|
||||
CurCount = Read8254Timer();
|
||||
if (CurCount <= LATCH / 2) /* If a tick has passed, turn the */
|
||||
{ /* calibrated bit back off */
|
||||
Pcr->StallScaleFactor &= ~calib_bit;
|
||||
}
|
||||
}
|
||||
|
||||
/* We're finished: Do the finishing touches */
|
||||
|
||||
Pcr->StallScaleFactor /= (MILLISEC / 2); /* Calculate delay_count for 1ms */
|
||||
|
||||
DPRINT("]\n");
|
||||
DPRINT("delay_count: %d\n", Pcr->StallScaleFactor);
|
||||
DPRINT("CPU speed: %d\n", Pcr->StallScaleFactor / 250);
|
||||
#if 0
|
||||
DbgPrint("About to start delay loop test\n");
|
||||
DbgPrint("Waiting for five minutes...");
|
||||
for (i = 0; i < (5*60*1000*20); i++)
|
||||
{
|
||||
KeStallExecutionProcessor(50);
|
||||
}
|
||||
DbgPrint("finished\n");
|
||||
for(;;);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* EOF */
|
||||
|
|
|
@ -20,28 +20,13 @@
|
|||
VOID
|
||||
HalpInitPhase0(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
|
||||
{
|
||||
/* Initialize the PICs */
|
||||
HalpInitPICs();
|
||||
|
||||
/* Force initial PIC state */
|
||||
KfRaiseIrql(KeGetCurrentIrql());
|
||||
|
||||
/* Initialize the clock */
|
||||
HalpInitializeClock();
|
||||
|
||||
/* Setup busy waiting */
|
||||
HalpCalibrateStallExecution();
|
||||
}
|
||||
|
||||
VOID
|
||||
HalpInitPhase1(VOID)
|
||||
{
|
||||
/* Enable the clock interrupt */
|
||||
((PKIPCR)KeGetPcr())->IDT[0x30].ExtendedOffset =
|
||||
(USHORT)(((ULONG_PTR)HalpClockInterrupt >> 16) & 0xFFFF);
|
||||
((PKIPCR)KeGetPcr())->IDT[0x30].Offset =
|
||||
(USHORT)HalpClockInterrupt;
|
||||
HalEnableSystemInterrupt(0x30, CLOCK2_LEVEL, Latched);
|
||||
|
||||
}
|
||||
|
||||
/* EOF */
|
||||
|
|
|
@ -241,7 +241,6 @@ IncompleteTick2:
|
|||
|
||||
Done:
|
||||
/* Exit the interrupt */
|
||||
mov esi, $
|
||||
cli
|
||||
call _HalEndSystemInterrupt@8
|
||||
jmp _Kei386EoiHelper@0
|
||||
|
|
Loading…
Reference in a new issue