[FREELDR] Separate PC beep routines out into its own file (#2347)

- Remove now unused i386rtl.c (and it doesn't contains RTL functions nowadays).
- Separate PC beep routines out into its own file.
- Also use delay function instead of BIOS interrupts.
- Improve as well the accuracy of KeStallExecutionProcessor() by using the same HW delay function.
This commit is contained in:
Dmitry Borisov 2020-02-15 00:22:17 +06:00 committed by GitHub
parent 571407c7d2
commit 747d50c52e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 69 additions and 164 deletions

View file

@ -121,7 +121,6 @@ if(ARCH STREQUAL "i386")
arch/i386/hwpci.c
arch/i386/i386bug.c
arch/i386/i386idt.c
arch/i386/i386rtl.c
arch/i386/i386vid.c
disk/scsiport.c)
@ -129,6 +128,7 @@ if(ARCH STREQUAL "i386")
list(APPEND FREELDR_ARC_SOURCE
# FIXME: Abstract things better so we don't need to include /pc/* here
arch/i386/pc/machpc.c # machxbox.c depends on it
arch/i386/pc/pcbeep.c # machxbox.c depends on it
arch/i386/pc/pcdisk.c # hwdisk.c depends on it
arch/i386/pc/pcmem.c # hwacpi.c/xboxmem.c depends on it
arch/i386/xbox/machxbox.c
@ -142,6 +142,7 @@ if(ARCH STREQUAL "i386")
else()
list(APPEND FREELDR_ARC_SOURCE
arch/i386/pc/machpc.c
arch/i386/pc/pcbeep.c
arch/i386/pc/pccons.c
arch/i386/pc/pcdisk.c
arch/i386/pc/pcmem.c
@ -169,9 +170,9 @@ elseif(ARCH STREQUAL "amd64")
arch/i386/hwdisk.c
arch/i386/hwpci.c
arch/i386/i386bug.c
arch/i386/i386rtl.c
arch/i386/i386vid.c
arch/i386/pc/machpc.c
arch/i386/pc/pcbeep.c
arch/i386/pc/pccons.c
arch/i386/pc/pcdisk.c
arch/i386/pc/pcmem.c

View file

@ -1,117 +0,0 @@
/*
* FreeLoader
* Copyright (C) 1998-2003 Brian Palmer <brianp@sginet.com>
*
* This program 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 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. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <freeldr.h>
void sound(int freq);
void delay(unsigned msec);
VOID PcBeep(VOID)
{
sound(700);
delay(200);
sound(0);
}
void delay(unsigned msec)
{
REGS Regs;
unsigned usec;
unsigned msec_this;
// Int 15h AH=86h
// BIOS - WAIT (AT,PS)
//
// AH = 86h
// CX:DX = interval in microseconds
// Return:
// CF clear if successful (wait interval elapsed)
// CF set on error or AH=83h wait already in progress
// AH = status (see #00496)
// Note: The resolution of the wait period is 977 microseconds on
// many systems because many BIOSes use the 1/1024 second fast
// interrupt from the AT real-time clock chip which is available on INT 70;
// because newer BIOSes may have much more precise timers available, it is
// not possible to use this function accurately for very short delays unless
// the precise behavior of the BIOS is known (or found through testing)
while (msec)
{
msec_this = msec;
if (msec_this > 4000)
{
msec_this = 4000;
}
usec = msec_this * 1000;
Regs.b.ah = 0x86;
Regs.w.cx = usec >> 16;
Regs.w.dx = usec & 0xffff;
Int386(0x15, &Regs, &Regs);
msec -= msec_this;
}
}
void sound(int freq)
{
int scale;
if (freq == 0)
{
WRITE_PORT_UCHAR((PUCHAR)0x61, READ_PORT_UCHAR((PUCHAR)0x61) & ~3);
return;
}
scale = 1193046 / freq;
WRITE_PORT_UCHAR((PUCHAR)0x43, 0xb6);
WRITE_PORT_UCHAR((PUCHAR)0x42, scale & 0xff);
WRITE_PORT_UCHAR((PUCHAR)0x42, scale >> 8);
WRITE_PORT_UCHAR((PUCHAR)0x61, READ_PORT_UCHAR((PUCHAR)0x61) | 3);
}
VOID __cdecl ChainLoadBiosBootSectorCode(
IN UCHAR BootDrive OPTIONAL,
IN ULONG BootPartition OPTIONAL)
{
REGS Regs;
RtlZeroMemory(&Regs, sizeof(Regs));
/* Set the boot drive and the boot partition */
Regs.b.dl = (UCHAR)(BootDrive ? BootDrive : FrldrBootDrive);
Regs.b.dh = (UCHAR)(BootPartition ? BootPartition : FrldrBootPartition);
/*
* Don't stop the floppy drive motor when we are just booting a bootsector,
* a drive, or a partition. If we were to stop the floppy motor, the BIOS
* wouldn't be informed and if the next read is to a floppy then the BIOS
* will still think the motor is on and this will result in a read error.
*/
// DiskStopFloppyMotor();
Relocator16Boot(&Regs,
/* Stack segment:pointer */
0x0000, 0x7C00,
/* Code segment:pointer */
0x0000, 0x7C00);
}

View file

@ -10,11 +10,6 @@
#include <ntoskrnl.h>
/* For KeStallExecutionProcessor */
#if defined(_M_IX86) || defined(_M_AMD64)
#include <arch/pc/pcbios.h>
#endif
/* FUNCTIONS *****************************************************************/
VOID
@ -99,44 +94,5 @@ NTAPI
KeStallExecutionProcessor(
IN ULONG MicroSeconds)
{
#if defined(_M_IX86) || defined(_M_AMD64)
REGS Regs;
ULONG usec_this;
// Int 15h AH=86h
// BIOS - WAIT (AT,PS)
//
// AH = 86h
// CX:DX = interval in microseconds
// Return:
// CF clear if successful (wait interval elapsed)
// CF set on error or AH=83h wait already in progress
// AH = status (see #00496)
// Note: The resolution of the wait period is 977 microseconds on
// many systems because many BIOSes use the 1/1024 second fast
// interrupt from the AT real-time clock chip which is available on INT 70;
// because newer BIOSes may have much more precise timers available, it is
// not possible to use this function accurately for very short delays unless
// the precise behavior of the BIOS is known (or found through testing)
while (MicroSeconds)
{
usec_this = MicroSeconds;
if (usec_this > 4000000)
{
usec_this = 4000000;
}
Regs.b.ah = 0x86;
Regs.w.cx = usec_this >> 16;
Regs.w.dx = usec_this & 0xffff;
Int386(0x15, &Regs, &Regs);
MicroSeconds -= usec_this;
}
#else
#error unimplemented
#endif
StallExecutionProcessor(MicroSeconds);
}

View file

@ -1416,6 +1416,32 @@ PcHwIdle(VOID)
*/
}
VOID __cdecl ChainLoadBiosBootSectorCode(
IN UCHAR BootDrive OPTIONAL,
IN ULONG BootPartition OPTIONAL)
{
REGS Regs;
RtlZeroMemory(&Regs, sizeof(Regs));
/* Set the boot drive and the boot partition */
Regs.b.dl = (UCHAR)(BootDrive ? BootDrive : FrldrBootDrive);
Regs.b.dh = (UCHAR)(BootPartition ? BootPartition : FrldrBootPartition);
/*
* Don't stop the floppy drive motor when we are just booting a bootsector,
* a drive, or a partition. If we were to stop the floppy motor, the BIOS
* wouldn't be informed and if the next read is to a floppy then the BIOS
* will still think the motor is on and this will result in a read error.
*/
// DiskStopFloppyMotor();
Relocator16Boot(&Regs,
/* Stack segment:pointer */
0x0000, 0x7C00,
/* Code segment:pointer */
0x0000, 0x7C00);
}
/******************************************************************************/

View file

@ -0,0 +1,39 @@
/*
* PROJECT: FreeLoader
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
* PURPOSE: Hardware-specific beep routine
* COPYRIGHT: Copyright 1998-2003 Brian Palmer (brianp@reactos.org)
*/
#include <freeldr.h>
#if defined(SARCH_XBOX)
#define CLOCK_TICK_RATE 1125000
#else
#define CLOCK_TICK_RATE 1193182
#endif
static VOID
Sound(USHORT Frequency)
{
USHORT Scale;
if (Frequency == 0)
{
WRITE_PORT_UCHAR((PUCHAR)0x61, READ_PORT_UCHAR((PUCHAR)0x61) & ~3);
return;
}
Scale = CLOCK_TICK_RATE / Frequency;
WRITE_PORT_UCHAR((PUCHAR)0x43, 0xB6);
WRITE_PORT_UCHAR((PUCHAR)0x42, Scale & 0xFF);
WRITE_PORT_UCHAR((PUCHAR)0x42, Scale >> 8);
WRITE_PORT_UCHAR((PUCHAR)0x61, READ_PORT_UCHAR((PUCHAR)0x61) | 3);
}
VOID PcBeep(VOID)
{
Sound(700);
StallExecutionProcessor(100000);
Sound(0);
}