- Detect PS/2 Port and Pointer Device (Mouse).

- Calculate CPU speed.
- Fixed delay counter overrun.

svn path=/trunk/; revision=7131
This commit is contained in:
Eric Kohl 2003-12-20 12:35:27 +00:00
parent 57af3eb9c8
commit 8bb5ad2bd8
6 changed files with 363 additions and 15 deletions

View file

@ -1,3 +1,9 @@
Changes in v1.8.19 (12/20/2003) (ekohl)
- Detect PS/2 Port and Pointer Device (Mouse).
- Calculate CPU speed.
- Fixed delay counter overrun.
Changes in v1.8.18 (12/14/2003) (ekohl)
- Detect serial ports and serial pointer devices (Mice/Trackballs)

View file

@ -50,6 +50,42 @@
#define MOUSE_TYPE_MOUSESYSTEMS 4
/* PS2 stuff */
/* Controller registers. */
#define CONTROLLER_REGISTER_STATUS 0x64
#define CONTROLLER_REGISTER_CONTROL 0x64
#define CONTROLLER_REGISTER_DATA 0x60
/* Controller commands. */
#define CONTROLLER_COMMAND_READ_MODE 0x20
#define CONTROLLER_COMMAND_WRITE_MODE 0x60
#define CONTROLLER_COMMAND_GET_VERSION 0xA1
#define CONTROLLER_COMMAND_MOUSE_DISABLE 0xA7
#define CONTROLLER_COMMAND_MOUSE_ENABLE 0xA8
#define CONTROLLER_COMMAND_TEST_MOUSE 0xA9
#define CONTROLLER_COMMAND_SELF_TEST 0xAA
#define CONTROLLER_COMMAND_KEYBOARD_TEST 0xAB
#define CONTROLLER_COMMAND_KEYBOARD_DISABLE 0xAD
#define CONTROLLER_COMMAND_KEYBOARD_ENABLE 0xAE
#define CONTROLLER_COMMAND_WRITE_MOUSE_OUTPUT_BUFFER 0xD3
#define CONTROLLER_COMMAND_WRITE_MOUSE 0xD4
/* Controller status */
#define CONTROLLER_STATUS_OUTPUT_BUFFER_FULL 0x01
#define CONTROLLER_STATUS_INPUT_BUFFER_FULL 0x02
#define CONTROLLER_STATUS_SELF_TEST 0x04
#define CONTROLLER_STATUS_COMMAND 0x08
#define CONTROLLER_STATUS_UNLOCKED 0x10
#define CONTROLLER_STATUS_MOUSE_OUTPUT_BUFFER_FULL 0x20
#define CONTROLLER_STATUS_GENERAL_TIMEOUT 0x40
#define CONTROLLER_STATUS_PARITY_ERROR 0x80
#define AUX_STATUS_OUTPUT_BUFFER_FULL (CONTROLLER_STATUS_OUTPUT_BUFFER_FULL | \
CONTROLLER_STATUS_MOUSE_OUTPUT_BUFFER_FULL)
/* Timeout in ms for sending to keyboard controller. */
#define CONTROLLER_TIMEOUT 250
typedef struct _CM_INT13_DRIVE_PARAMETER
{
@ -122,7 +158,8 @@ __KeStallExecutionProcessor(U32 Loops)
VOID KeStallExecutionProcessor(U32 Microseconds)
{
__KeStallExecutionProcessor((delay_count * Microseconds) / 1000);
U64 LoopCount = ((U64)delay_count * (U64)Microseconds) / 1000ULL;
__KeStallExecutionProcessor((U32)LoopCount);
}
@ -214,7 +251,6 @@ HalpCalibrateStallExecution(VOID)
}
/* We're finished: Do the finishing touches */
delay_count /= (MILLISEC / 2); /* Calculate delay_count for 1ms */
}
@ -991,7 +1027,8 @@ DetectSerialPointerPeripheral(HKEY ControllerKey,
"Configuration Data",
REG_FULL_RESOURCE_DESCRIPTOR,
(PU8)&FullResourceDescriptor,
sizeof(CM_FULL_RESOURCE_DESCRIPTOR));
sizeof(CM_FULL_RESOURCE_DESCRIPTOR) -
sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
if (Error != ERROR_SUCCESS)
{
DbgPrint((DPRINT_HWDETECT,
@ -1016,8 +1053,7 @@ DetectSerialPointerPeripheral(HKEY ControllerKey,
static VOID
DetectSerialPorts(HKEY SystemKey,
HKEY BusKey)
DetectSerialPorts(HKEY BusKey)
{
PCM_FULL_RESOURCE_DESCRIPTOR FullResourceDescriptor;
PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor;
@ -1153,6 +1189,230 @@ DetectSerialPorts(HKEY SystemKey,
}
static VOID
PS2ControllerWait(VOID)
{
U32 Timeout;
U8 Status;
for (Timeout = 0; Timeout < CONTROLLER_TIMEOUT; Timeout++)
{
Status = READ_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_STATUS);
if ((Status & CONTROLLER_STATUS_INPUT_BUFFER_FULL) == 0)
return;
/* Sleep for one millisecond */
KeStallExecutionProcessor(1000);
}
}
static BOOLEAN
DetectPS2AuxPort(VOID)
{
U32 Loops;
U8 Scancode;
U8 Status;
/* Put the value 0x5A in the output buffer using the
* "WriteAuxiliary Device Output Buffer" command (0xD3).
* Poll the Status Register for a while to see if the value really turns up
* in the Data Register. If the KEYBOARD_STATUS_MOUSE_OBF bit is also set
* to 1 in the Status Register, we assume this controller has an
* Auxiliary Port (a.k.a. Mouse Port).
*/
PS2ControllerWait();
WRITE_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_CONTROL,
CONTROLLER_COMMAND_WRITE_MOUSE_OUTPUT_BUFFER);
PS2ControllerWait();
/* 0x5A is a random dummy value */
WRITE_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_DATA,
0x5A);
for (Loops = 0; Loops < 10; Loops++)
{
Status = READ_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_STATUS);
if ((Status & CONTROLLER_STATUS_OUTPUT_BUFFER_FULL) != 0)
{
Scancode = READ_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_DATA);
if ((Status & CONTROLLER_STATUS_MOUSE_OUTPUT_BUFFER_FULL) != 0)
{
return TRUE;
}
break;
}
KeStallExecutionProcessor(10000);
}
return FALSE;
}
static BOOLEAN
DetectPS2AuxDevice(VOID)
{
U8 Scancode;
U8 Status;
PS2ControllerWait();
WRITE_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_CONTROL,
CONTROLLER_COMMAND_WRITE_MOUSE);
PS2ControllerWait();
/* Identify device */
WRITE_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_DATA,
0xF2);
KeStallExecutionProcessor(10000);
Status = READ_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_STATUS);
if ((Status & CONTROLLER_STATUS_MOUSE_OUTPUT_BUFFER_FULL) == 0)
{
return FALSE;
}
Scancode = READ_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_DATA);
if (Scancode != 0xFA)
return FALSE;
KeStallExecutionProcessor(10000);
Status = READ_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_STATUS);
if ((Status & CONTROLLER_STATUS_MOUSE_OUTPUT_BUFFER_FULL) == 0)
{
return FALSE;
}
Scancode = READ_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_DATA);
if (Scancode != 0x00)
return FALSE;
return TRUE;
}
static VOID
DetectPS2Mouse(HKEY BusKey)
{
CM_FULL_RESOURCE_DESCRIPTOR FullResourceDescriptor;
HKEY ControllerKey;
HKEY PeripheralKey;
S32 Error;
if (DetectPS2AuxPort())
{
DbgPrint((DPRINT_HWDETECT, "Detected PS2 port\n"));
/* Create controller key */
Error = RegCreateKey(BusKey,
"PointerController\\0",
&ControllerKey);
if (Error != ERROR_SUCCESS)
{
DbgPrint((DPRINT_HWDETECT, "Failed to create controller key\n"));
return;
}
DbgPrint((DPRINT_HWDETECT, "Created key: PointerController\\0\n"));
/* Set 'ComponentInformation' value */
SetComponentInformation(ControllerKey,
0x20,
0,
0xFFFFFFFF);
memset(&FullResourceDescriptor, 0, sizeof(CM_FULL_RESOURCE_DESCRIPTOR));
/* Initialize resource descriptor */
FullResourceDescriptor.InterfaceType = Isa;
FullResourceDescriptor.BusNumber = 0;
FullResourceDescriptor.PartialResourceList.Count = 1;
/* Set Interrupt */
FullResourceDescriptor.PartialResourceList.PartialDescriptors[0].Type = CmResourceTypeInterrupt;
FullResourceDescriptor.PartialResourceList.PartialDescriptors[0].ShareDisposition = CmResourceShareUndetermined;
FullResourceDescriptor.PartialResourceList.PartialDescriptors[0].Flags = CM_RESOURCE_INTERRUPT_LATCHED;
FullResourceDescriptor.PartialResourceList.PartialDescriptors[0].u.Interrupt.Level = 12;
FullResourceDescriptor.PartialResourceList.PartialDescriptors[0].u.Interrupt.Vector = 12;
FullResourceDescriptor.PartialResourceList.PartialDescriptors[0].u.Interrupt.Affinity = 0xFFFFFFFF;
/* Set 'Configuration Data' value */
Error = RegSetValue(ControllerKey,
"Configuration Data",
REG_FULL_RESOURCE_DESCRIPTOR,
(PU8)&FullResourceDescriptor,
sizeof(CM_FULL_RESOURCE_DESCRIPTOR));
if (Error != ERROR_SUCCESS)
{
DbgPrint((DPRINT_HWDETECT,
"RegSetValue(Configuration Data) failed (Error %u)\n",
(int)Error));
return;
}
if (DetectPS2AuxDevice())
{
DbgPrint((DPRINT_HWDETECT, "Detected PS2 mouse\n"));
/* Create peripheral key */
Error = RegCreateKey(ControllerKey,
"PointerPeripheral\\0",
&PeripheralKey);
if (Error != ERROR_SUCCESS)
{
DbgPrint((DPRINT_HWDETECT, "Failed to create peripheral key\n"));
return;
}
DbgPrint((DPRINT_HWDETECT, "Created key: PointerPeripheral\\0\n"));
/* Set 'ComponentInformation' value */
SetComponentInformation(PeripheralKey,
0x20,
0,
0xFFFFFFFF);
/* Initialize resource descriptor */
memset(&FullResourceDescriptor, 0, sizeof(CM_FULL_RESOURCE_DESCRIPTOR));
FullResourceDescriptor.InterfaceType = Isa;
FullResourceDescriptor.BusNumber = 0;
FullResourceDescriptor.PartialResourceList.Count = 0;
/* Set 'Configuration Data' value */
Error = RegSetValue(PeripheralKey,
"Configuration Data",
REG_FULL_RESOURCE_DESCRIPTOR,
(PU8)&FullResourceDescriptor,
sizeof(CM_FULL_RESOURCE_DESCRIPTOR) -
sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
if (Error != ERROR_SUCCESS)
{
DbgPrint((DPRINT_HWDETECT,
"RegSetValue(Configuration Data) failed (Error %u)\n",
(int)Error));
return;
}
/* Set 'Identifier' value */
Error = RegSetValue(PeripheralKey,
"Identifier",
REG_SZ,
(PU8)"MICROSOFT PS2 MOUSE",
20);
if (Error != ERROR_SUCCESS)
{
DbgPrint((DPRINT_HWDETECT,
"RegSetValue() failed (Error %u)\n",
(int)Error));
return;
}
}
}
}
static VOID
DetectIsaBios(HKEY SystemKey, U32 *BusNumber)
{
@ -1224,18 +1484,23 @@ DetectIsaBios(HKEY SystemKey, U32 *BusNumber)
/* Detect ISA/BIOS devices */
DetectBiosDisks(SystemKey, BusKey);
#if 0
DetectBiosFloppyDisks(SystemKey, BusKey);
#endif
DetectSerialPorts(SystemKey, BusKey);
DetectSerialPorts(BusKey);
#if 0
DetectBiosParallelPorts();
DetectBiosKeyboard();
DetectBiosMouse();
#endif
#if 0
DetectBiosKeyboard(BusKey);
#endif
DetectPS2Mouse(BusKey);
/* FIXME: Detect more ISA devices */
}
@ -1280,10 +1545,10 @@ DetectHardware(VOID)
DbgPrint((DPRINT_HWDETECT, "DetectHardware() Done\n"));
#if 0
//#if 0
printf("*** System stopped ***\n");
for (;;);
#endif
//#endif
}
/* EOF */

View file

@ -153,6 +153,8 @@ typedef struct _CM_COMPONENT_INFORMATION
/* PROTOTYPES ***************************************************************/
/* hardware.c */
VOID KeStallExecutionProcessor(U32 Microseconds);
VOID SetComponentInformation(HKEY ComponentKey,
U32 Flags,
U32 Key,
@ -168,6 +170,7 @@ VOID GetCpuid(U32 Level,
U32 *ebx,
U32 *ecx,
U32 *edx);
U64 RDTSC(VOID);
/* i386pnp.S */
U32 PnpBiosSupported(VOID);

View file

@ -77,6 +77,36 @@ typedef struct _MP_PROCESSOR_ENTRY
/* FUNCTIONS ****************************************************************/
static U32
GetCpuSpeed(VOID)
{
U64 Timestamp1;
U64 Timestamp2;
U64 Diff;
/* Read TSC (Time Stamp Counter) */
Timestamp1 = RDTSC();
/* Wait for 0.1 seconds (= 100 milliseconds = 100000 microseconds)*/
KeStallExecutionProcessor(100000);
/* Read TSC (Time Stamp Counter) again */
Timestamp2 = RDTSC();
/* Calculate elapsed time (check for counter overrun) */
if (Timestamp2 > Timestamp1)
{
Diff = Timestamp2 - Timestamp1;
}
else
{
Diff = Timestamp2 + (((U64)-1) - Timestamp1);
}
return (U32)(Diff / 100000);
}
static VOID
DetectCPU(HKEY CpuKey,
HKEY FpuKey)
@ -92,6 +122,9 @@ DetectCPU(HKEY CpuKey,
U32 edx = 0;
U32 *Ptr;
S32 Error;
BOOL SupportTSC = FALSE;
U32 CpuSpeed;
/* Create the CPU instance key */
Error = RegCreateKey(CpuKey,
@ -136,6 +169,8 @@ DetectCPU(HKEY CpuKey,
(unsigned int)((eax >> 4) & 0x0F),
(unsigned int)(eax & 0x0F));
FeatureSet = edx;
if (((eax >> 8) & 0x0F) >= 5)
SupportTSC = TRUE;
}
else
{
@ -207,7 +242,21 @@ DetectCPU(HKEY CpuKey,
/* FIXME: Set 'Update Status' value (CPU only) */
/* FIXME: Set '~MHz' value (CPU only) */
/* Set '~MHz' value (CPU only) */
if (SupportTSC)
{
CpuSpeed = GetCpuSpeed();
Error = RegSetValue(CpuInstKey,
"~MHz",
REG_DWORD,
(PU8)&CpuSpeed,
sizeof(U32));
if (Error != ERROR_SUCCESS)
{
DbgPrint((DPRINT_HWDETECT, "RegSetValue() failed (Error %u)\n", (int)Error));
}
}
}
@ -228,6 +277,7 @@ SetMpsProcessor(HKEY CpuKey,
U32 edx = 0;
U32 *Ptr;
S32 Error;
U32 CpuSpeed;
/* Get processor instance number */
sprintf(Buffer, "%u", CpuEntry->LocalApicId);
@ -336,7 +386,21 @@ SetMpsProcessor(HKEY CpuKey,
/* FIXME: Set 'Update Status' value (CPU only) */
/* FIXME: Set '~MHz' value (CPU only) */
/* Set '~MHz' value (CPU only) */
if (((CpuEntry->CpuSignature >> 8) & 0x0F) >= 5)
{
CpuSpeed = GetCpuSpeed();
Error = RegSetValue(CpuInstKey,
"~MHz",
REG_DWORD,
(PU8)&CpuSpeed,
sizeof(U32));
if (Error != ERROR_SUCCESS)
{
DbgPrint((DPRINT_HWDETECT, "RegSetValue() failed (Error %u)\n", (int)Error));
}
}
}

View file

@ -118,4 +118,14 @@ EXTERN(_GetCpuid)
popl %ebp
ret
/*
* U64 RDTSC(VOID);
*/
EXTERN(_RDTSC)
.code32
rdtsc
ret
/* EOF */

View file

@ -22,7 +22,7 @@
/* just some stuff */
#define VERSION "FreeLoader v1.8.18"
#define VERSION "FreeLoader v1.8.19"
#define COPYRIGHT "Copyright (C) 1998-2003 Brian Palmer <brianp@sginet.com>"
#define AUTHOR_EMAIL "<brianp@sginet.com>"
#define BY_AUTHOR "by Brian Palmer"
@ -36,7 +36,7 @@
//
#define FREELOADER_MAJOR_VERSION 1
#define FREELOADER_MINOR_VERSION 8
#define FREELOADER_PATCH_VERSION 18
#define FREELOADER_PATCH_VERSION 19
#ifndef ASM