2020-09-30 17:12:29 +02:00

1452 lines
28 KiB
C
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*++
Copyright (c) 1991 Microsoft Corporation
Copyright (c) 1992 Digital Equipment Corporation
Module Name:
xxenvir.c
Abstract:
This module implements the ARC firmware Environment Variable functions as
described in the Advanced Risc Computing Specification (Revision 1.00),
section 3.3.3.11, for the Alpha Jensen system.
Author:
David M. Robinson (davidro) 13-June-1991
Revision History:
Jeff McLeman (DEC) 31-Jul-1992
modify for Jensen
This module is for Jensen only. Jensen uses a 1 Mbyte sector eraseable
flash prom. Due to the long delays needed to store the environment in the
prom, we must implement a timer, instead of using
KeStallExecutionProcessor(). The prom may take up to a second to perform
the function, so we will go away while it is still running, and comeback
when it is done.
--*/
#include "halp.h"
#if defined(JENSEN)
#include "jxenv.h"
#endif
#include "arccodes.h"
//
// Static data.
//
UCHAR OutputString[MAXIMUM_ENVIRONMENT_VALUE];
PUCHAR VolatileEnvironment;
PCHAR VolatileConfig;
PCHAR VolatileEisaData;
PCONFIGURATION Configuration;
PROMTIMER PromTimer;
KEVENT PromEvent;
//
// Routine prototypes.
//
ARC_STATUS
HalpEnvironmentCheckChecksum (
VOID
);
ARC_STATUS
HalpEnvironmentSetChecksum (
VOID
);
ARC_STATUS
HalpConfigurationSetChecksum (
VOID
);
ARC_STATUS
HalpEisaSetChecksum (
VOID
);
ARC_STATUS
HalpFindEnvironmentVariable (
IN PCHAR Variable,
OUT PULONG VariableIndex,
OUT PULONG ValueIndex
);
VOID
HalpInitializePromTimer(
IN OUT PPROMTIMER PrmTimer,
IN PVOID FunctionContext
);
VOID
HalpSetPromTimer(
IN PPROMTIMER PrmTimer,
IN ULONG MillisecondsToDelay
);
VOID
HalpPromDpcHandler(
IN PVOID SystemSpecific,
IN PVOID Context,
IN PVOID SystemArgument1,
IN PVOID SystemArgument2
);
VOID
HalpPromDelay(
IN ULONG Milliseconds
);
ARC_STATUS
HalpEnvironmentInitialize (
VOID
)
/*++
Routine Description:
This routine initializes the environment routine addresses.
Arguments:
None.
Return Value:
None.
--*/
{
ULONG status = 0;
//
// Determine the ROM type in this machine
//
if (HalpROMDetermineMachineROMType() != ESUCCESS) {
HalDisplayString("*** Unknown ROM Type in Machine ***\n");
HalDisplayString(" Please contact Digital Field Services \n");
HalpPromDelay(10*1000);
HalpReboot();
}
//
// Allocate enough memory to load the environment for loaded programs.
//
VolatileEnvironment = ExAllocatePool(NonPagedPool, LENGTH_OF_ENVIRONMENT);
if (VolatileEnvironment == 0) {
status = FALSE;
}
HalpEnvironmentLoad();
HalpInitializePromTimer(&PromTimer,0);
return(status);
}
ARC_STATUS
HalpEnvironmentCheckChecksum (
VOID
)
/*++
Routine Description:
This routine checks the environment area checksum.
Arguments:
None.
Return Value:
If the checksum is good, ESUCCESS is returned, otherwise EIO is returned.
--*/
{
PUCHAR NvChars;
PNV_CONFIGURATION NvConfiguration;
ULONG Index;
ULONG Checksum1, Checksum2;
NvConfiguration = (PNV_CONFIGURATION)NVRAM_CONFIGURATION;
//
// Form checksum from NVRAM data.
//
Checksum1 = 0;
NvChars = (PUCHAR)&NvConfiguration->Environment[0];
for ( Index = 0 ;
Index < LENGTH_OF_ENVIRONMENT;
Index++ ) {
Checksum1 += READ_PORT_UCHAR( NvChars++ );
}
//
// Reconstitute checksum and return error if no compare.
//
Checksum2 = (ULONG)READ_PORT_UCHAR( &NvConfiguration->Checksum2[0] ) |
(ULONG)READ_PORT_UCHAR( &NvConfiguration->Checksum2[1] ) << 8 |
(ULONG)READ_PORT_UCHAR( &NvConfiguration->Checksum2[2] ) << 16 |
(ULONG)READ_PORT_UCHAR( &NvConfiguration->Checksum2[3] ) << 24 ;
if (Checksum1 != Checksum2) {
return EIO;
} else {
return ESUCCESS;
}
}
ARC_STATUS
HalGetEnvironmentVariable (
IN PCHAR Variable,
IN USHORT length,
OUT PCHAR Buffer
)
/*++
Routine Description:
This routine searches (not case sensitive) the non-volatile ram for
Variable, and if found returns a pointer to a zero terminated string that
contains the value, otherwise a NULL pointer is returned.
Arguments:
Variable - Supplies a zero terminated string containing an environment
variable.
Length - Supplies the length of the vlaue buffer in bytes
Buffer - Supplies a pointer to a buffer that will recieve the
environment variable.
Return Value:
If successful, returns a zero terminated string that is the value of
Variable, otherwise NULL is returned.
--*/
{
PNV_CONFIGURATION NvConfiguration;
ULONG VariableIndex;
ULONG ValueIndex;
ULONG Index;
ARC_STATUS Status;
KIRQL OldIrql;
//
// Raise IRQL to synchronize
//
KeRaiseIrql(DEVICE_LEVEL, &OldIrql);
NvConfiguration = (PNV_CONFIGURATION)NVRAM_CONFIGURATION;
//
// If checksum is wrong, or the variable can't be found, return NULL.
//
if ((HalpEnvironmentCheckChecksum() != ESUCCESS) ||
(HalpFindEnvironmentVariable(Variable, &VariableIndex, &ValueIndex) != ESUCCESS)) {
Status = ENOENT;
} else {
//
// Copy value to an output string, break on zero terminator or string max.
//
for ( Index = 0 ; Index < length ; Index += 1 ) {
*Buffer =
READ_PORT_UCHAR( &NvConfiguration->Environment[ValueIndex] );
if (*Buffer== 0) {
break;
}
Buffer += 1;
ValueIndex += 1;
}
if (Index == length) {
Status = ENOMEM;
} else {
Status = ESUCCESS;
}
}
//
// Lower IRQL back to where it was
//
KeLowerIrql(OldIrql);
return Status;
}
#ifdef JENSEN
ARC_STATUS
HalSetEnvironmentVariable (
IN PCHAR Variable,
IN PCHAR Value
)
/*++
Routine Description:
This routine sets Variable (not case sensitive) to Value.
The MIPS version of this code modified the NVRAM directly.
For Alpha/Jensen, we have to modify the volatile area and then
update the PROM configuration block.
Arguments:
Variable - Supplies a zero terminated string containing an environment
variable.
Value - Supplies a zero terminated string containing an environment
variable value.
Return Value:
Returns ESUCCESS if the set completed successfully, otherwise one of
the following error codes is returned.
ENOSPC No space in NVRAM for set operation.
EIO Invalid Checksum.
--*/
{
PNV_CONFIGURATION NvConfiguration;
ULONG VariableIndex;
ULONG ValueIndex;
ULONG TopOfEnvironment;
PCHAR String;
PUCHAR VChars;
LONG Count;
CHAR Char;
KIRQL OldIrql;
ARC_STATUS Status;
//
// Raise Irql to Synchronize
//
KeRaiseIrql(DEVICE_LEVEL, &OldIrql);
NvConfiguration = (PNV_CONFIGURATION)NVRAM_CONFIGURATION;
//
// If checksum is wrong, return EIO;
//
if (HalpEnvironmentCheckChecksum() != ESUCCESS) {
KeLowerIrql(OldIrql);
return EIO;
}
VChars = VolatileEnvironment;
//
// Determine the top of the environment space by looking for the first
// non-null character from the top.
//
TopOfEnvironment = LENGTH_OF_ENVIRONMENT - 1;
while (VChars[--TopOfEnvironment] == 0) {
if (TopOfEnvironment == 0) {
break;
}
}
//
// Adjust TopOfEnvironment to the first new character, unless environment
// space is empty.
//
if (TopOfEnvironment != 0) {
TopOfEnvironment += 2;
}
//
// Check to see if the variable already has a value.
//
Count = LENGTH_OF_ENVIRONMENT - TopOfEnvironment;
if (HalpFindEnvironmentVariable(Variable, &VariableIndex, &ValueIndex) == ESUCCESS) {
//
// Count free space, starting with the free area at the top and adding
// the old variable value.
//
for ( String = VChars + ValueIndex ;
*String != 0 ;
String++ ) {
Count++;
}
//
// Determine if free area is large enough to handle new value, if not
// return error.
//
for ( String = Value ; *String != 0 ; String++ ) {
if (Count-- == 0) {
KeLowerIrql(OldIrql);
return ENOSPC;
}
}
//
// Move ValueIndex to the end of the value and compress strings.
//
while(VChars[ValueIndex++] != 0) {
}
while (ValueIndex < TopOfEnvironment ) {
VChars[VariableIndex++] = VChars[ValueIndex++];
}
//
// Adjust new top of environment.
//
TopOfEnvironment = VariableIndex;
//
// Zero to the end.
//
while (VariableIndex < LENGTH_OF_ENVIRONMENT) {
VChars[VariableIndex++] = 0;
}
} else {
//
// Variable is new.
//
//
// Determine if free area is large enough to handle new value, if not
// return error.
//
//
// From the length of free space subtract new variable's length,
// Value's length and 2 chars, one for the '=' sign and one of the
// null terminator.
//
Count -= ( strlen(Variable) + strlen(Value) + 2 );
//
// Check if there is space to fit the new variable.
//
if (Count < 0) {
KeLowerIrql(OldIrql);
return ENOSPC;
}
}
//
// If Value is not zero, write new variable and value.
//
if (*Value != 0) {
//
// Write new variable, converting to upper case.
//
while (*Variable != 0) {
VChars[TopOfEnvironment++] =
((*Variable >= 'a') && (*Variable <= 'z') ? (*Variable - 'a' + 'A') : *Variable);
Variable++;
}
//
// Write equal sign.
//
VChars[TopOfEnvironment++] = '=';
//
// Write new value.
//
while (*Value != 0) {
VChars[TopOfEnvironment++] = *Value++;
}
}
//
// Lower Irql back to where it was
//
KeLowerIrql(OldIrql);
/* Now update the Jensen PROM */
Status = HalpSaveConfiguration();
return Status;
// return ESUCCESS;
}
#endif
ARC_STATUS
HalpFindEnvironmentVariable (
IN PCHAR Variable,
OUT PULONG VariableIndex,
OUT PULONG ValueIndex
)
/*++
Routine Description:
This routine searches (not case sensitive) the non-volatile ram for
Variable.
Arguments:
Variable - Supplies a zero terminated string containing an environment
variable.
Return Value:
If successful, returns ESUCCESS, otherwise returns ENOENT.
--*/
{
PNV_CONFIGURATION NvConfiguration;
PUCHAR String;
PUCHAR Environment;
ULONG Index;
NvConfiguration = (PNV_CONFIGURATION)NVRAM_CONFIGURATION;
//
// If Variable is null, return immediately.
//
if (*Variable == 0) {
return ENOENT;
}
Environment = NvConfiguration->Environment;
Index = 0;
while (TRUE) {
//
// Set string to beginning of Variable.
//
String = Variable;
*VariableIndex = Index;
//
// Search until the end of NVRAM.
//
while ( Index < LENGTH_OF_ENVIRONMENT ) {
//
// Convert to uppercase and break if mismatch.
//
if ( READ_PORT_UCHAR( &Environment[Index] ) !=
((*String >= 'a') &&
(*String <= 'z') ?
(*String - 'a' + 'A') : *String) ) {
break;
}
String++;
Index++;
}
//
// Check to see if we're at the end of the string and the variable,
// which means a match.
//
if ((*String == 0) && (READ_PORT_UCHAR( &Environment[Index] ) == '=')) {
*ValueIndex = ++Index;
return ESUCCESS;
}
//
// Move index to the start of the next variable.
//
while (READ_PORT_UCHAR( &Environment[Index++] ) != 0) {
if (Index >= LENGTH_OF_ENVIRONMENT) {
return ENOENT;
}
}
}
}
PCHAR
HalpEnvironmentLoad (
VOID
)
/*++
Routine Description:
This routine loads the entire environment into the volatile environment
area.
Arguments:
None.
Return Value:
If the checksum is good, a pointer to the environment in returned,
otherwise NULL is returned.
--*/
{
ULONG Index;
PUCHAR NvChars;
PUCHAR VChars;
PNV_CONFIGURATION NvConfiguration;
if (HalpEnvironmentCheckChecksum() == ESUCCESS) {
NvConfiguration = (PNV_CONFIGURATION)NVRAM_CONFIGURATION;
//
// Copy the data into the volatile area.
//
NvChars = (PUCHAR)&NvConfiguration->Environment[0];
VChars = VolatileEnvironment;
// READ_PORT_BUFFER_UCHAR(NvChars, VChars, LENGTH_OF_ENVIRONMENT);
for ( Index = 0 ;
Index < LENGTH_OF_ENVIRONMENT;
Index++ ) {
*VChars++ = READ_PORT_UCHAR( NvChars++ );
}
return (PCHAR)VolatileEnvironment;
} else {
return NULL;
}
}
ARC_STATUS
HalpEnvironmentSetChecksum (
VOID
)
/*++
Routine Description:
This routine sets the environment area checksum.
For Alpha/Jensen builds, this must ONLY be called from
HalpEnvironmentStore, as the previous block erase & storage
of the entire environment variable area must have been done.
Arguments:
None.
Return Value:
None.
--*/
{
PUCHAR NvChars;
PNV_CONFIGURATION NvConfiguration;
ULONG Index;
ULONG Checksum;
KIRQL OldIrql;
NvConfiguration = (PNV_CONFIGURATION)NVRAM_CONFIGURATION;
//
// Form checksum from NVRAM data.
//
Checksum = 0;
NvChars = (PUCHAR)&NvConfiguration->Environment[0];
HalpROMSetReadMode(NvChars);
KeRaiseIrql(DEVICE_LEVEL, &OldIrql);
for ( Index = 0 ;
Index < LENGTH_OF_ENVIRONMENT;
Index++ ) {
Checksum += READ_PORT_UCHAR( NvChars++ );
}
KeLowerIrql(OldIrql);
//
// Write environment checksum.
//
HalpROMResetStatus((PUCHAR)&NvConfiguration->Environment[0]);
if ((HalpROMByteWrite( &NvConfiguration->Checksum2[0],
(UCHAR)(Checksum & 0xFF)) != ESUCCESS) ||
(HalpROMByteWrite( &NvConfiguration->Checksum2[1],
(UCHAR)((Checksum >> 8) & 0xFF)) != ESUCCESS) ||
(HalpROMByteWrite( &NvConfiguration->Checksum2[2],
(UCHAR)((Checksum >> 16) & 0xFF)) != ESUCCESS) ||
(HalpROMByteWrite( &NvConfiguration->Checksum2[3],
(UCHAR)(Checksum >> 24)) != ESUCCESS)) {
return EIO;
} else {
return ESUCCESS;
}
}
ARC_STATUS
HalpEnvironmentStore (
VOID
)
/*++
Routine Description:
This loads the entire environment into the non-volatile environment area.
It's needed only in Jensen, which uses a segmented block-erase
PROM. When the code wants to store one environment variable,
it has to store all of them. This causes the least pertubations
in the firmware code.
This routine must *only* be called from HalpSaveConfiguration, which
does the block-erase and the store of the other part of the
non-volatile configuration information.
Arguments:
None.
Return Value:
ESUCCESS if the writes were OK.
EIO otherwise.
--*/
{
ULONG Index;
PNV_CONFIGURATION NvConfiguration;
PUCHAR NvChars, VChars;
extern PUCHAR VolatileEnvironment; // defined in jxenvir.c
NvConfiguration = (PNV_CONFIGURATION)NVRAM_CONFIGURATION;
VChars = VolatileEnvironment;
NvChars = (PUCHAR)&NvConfiguration->Environment[0];
#if DBG
DbgPrint("WriteEnv: NvChars=%x, VChars=%x, loe = %x\n",
NvChars,VChars,LENGTH_OF_ENVIRONMENT);
#endif
for (Index = 0; Index < LENGTH_OF_ENVIRONMENT; Index++) {
if (HalpROMByteWrite(NvChars++, *VChars++) != ESUCCESS) {
return EIO;
}
}
if (HalpEnvironmentSetChecksum() != ESUCCESS) {
return EIO;
}
return ESUCCESS;
}
ARC_STATUS
HalpSaveConfiguration (
VOID
)
/*++
Routine Description:
This routine stores all of the configuration entries into NVRAM,
including the associated identifier strings and configuration data.
The Alpha/Jensen version of this code saves the entire configuration
structure, i.e. including the environment variables. The ARC CDS
+ environment variables are all in one structure, and unfortunately
Jensen has a segmented block-erase PROM instead of an NVRAM. Doing
a complete save is a change that is least likely to break anything.
Arguments:
None.
Return Value:
Returns ESUCCESS if the save completed successfully, otherwise one of the
following error codes is returned.
ENOSPC Not enough space in the NVRAM to save all of the data.
EIO Some write error happened in the PROM.
--*/
{
ULONG EntryIndex;
ULONG Index;
// ULONG NumBytes;
PNV_CONFIGURATION NvConfiguration;
PUCHAR NvChars, VChars;
ULONG ConfigSize;
KIRQL OldIrql;
ULONG EisaSize = LENGTH_OF_EISA_DATA;
#if DBG
DbgPrint("HalpSaveConfiguration: Entered\n");
#endif
NvConfiguration = (PNV_CONFIGURATION)NVRAM_CONFIGURATION;
ConfigSize= (
(sizeof(COMPRESSED_CONFIGURATION_PACKET) * NUMBER_OF_ENTRIES) +
LENGTH_OF_IDENTIFIER + LENGTH_OF_DATA);
VolatileConfig = ExAllocatePool(NonPagedPool, PAGE_SIZE);
if (VolatileConfig == NULL) {
return(ENOMEM);
}
VolatileEisaData = ExAllocatePool(NonPagedPool, PAGE_SIZE);
if (VolatileEisaData == NULL) {
ExFreePool(VolatileConfig);
return(ENOMEM);
}
//
// Copy the component structure first
//
VChars = VolatileConfig;
NvChars = (PUCHAR)NVRAM_CONFIGURATION;
KeRaiseIrql(DEVICE_LEVEL, &OldIrql);
//
// Copy the config data from the rom to the volatile pool
//
#if DBG
DbgPrint("HalpSaveConfiguration: Reading Config data\n");
DbgPrint("Prom address = %x, Volatile Address = %x\n",NvChars,VChars);
DbgPrint("ConfigSize = %X\n",ConfigSize);
#endif
for (Index = 0; Index < ConfigSize; Index++) {
*VChars++ = READ_PORT_UCHAR(NvChars++);
}
KeLowerIrql(OldIrql);
//
// Now copy the EISA data
//
VChars = VolatileEisaData;
NvChars = (PUCHAR)&NvConfiguration->EisaData[0];
KeRaiseIrql(DEVICE_LEVEL, &OldIrql);
//
// Copy the eisa data from the rom to the volatile pool
//
#if DBG
DbgPrint("HalpSaveConfiguration: Reading Eisa data\n");
DbgPrint("Prom address = %x, Volatile Address = %x\n",NvChars,VChars);
DbgPrint("ConfigSize = %X\n",EisaSize);
#endif
for (Index = 0; Index < EisaSize; Index++) {
*VChars++ = READ_PORT_UCHAR(NvChars++);
}
KeLowerIrql(OldIrql);
/*
* Erase the PROM block we are going to update.
*/
#if DBG
DbgPrint("HalpSaveConfiguration: Erasing prom block \n");
#endif
if (HalpROMEraseBlock((PUCHAR)NVRAM_CONFIGURATION) != ESUCCESS) {
ExFreePool(VolatileEisaData);
ExFreePool(VolatileConfig);
return ENOSPC;
}
//
// Write the configuration stuff back into the rom.
//
VChars = VolatileConfig;
NvChars = (PUCHAR)NVRAM_CONFIGURATION;
#if DBG
DbgPrint("HalpSaveConfiguration: Writing Config data\n");
DbgPrint("Prom address = %x, Volatile Address = %x\n",NvChars,VChars);
DbgPrint("ConfigSize = %X\n",ConfigSize);
#endif
for (Index = 0; Index < ConfigSize; Index++) {
if (HalpROMByteWrite(NvChars++, *VChars++) != ESUCCESS) {
DbgPrint("HalpSaveConfig: Error Writing the Prom byte\n");
DbgPrint("ERROR: Prom address = %x, Volatile Address = %x\n",NvChars,VChars);
ExFreePool(VolatileEisaData);
ExFreePool(VolatileConfig);
return EIO;
}
}
#if DBG
DbgPrint("HalpSaveConfig: Wrote Config data to rom\n");
DbgPrint("Writing Config Checksum...\n");
#endif
if (HalpConfigurationSetChecksum() != ESUCCESS) {
DbgPrint("HalpSaveConfig: Error setting checksum\n");
HalpROMSetReadMode((PUCHAR)NvConfiguration);
ExFreePool(VolatileEisaData);
ExFreePool(VolatileConfig);
return EIO;
}
//
// Free up the pool
//
ExFreePool(VolatileConfig);
/*
* If the PROM status is OK then update the environment
* variables. If *that* is done OK too, return ESUCCESS.
*/
#if DBG
DbgPrint("HalpSaveConfiguration: Writing Environment Variables\n");
#endif
if (HalpEnvironmentStore() != ESUCCESS) {
HalpROMSetReadMode((PUCHAR)NVRAM_CONFIGURATION);
return EIO;
}
//
// Write the eisa data back into the rom.
//
VChars = VolatileEisaData;
NvChars = (PUCHAR)&NvConfiguration->EisaData[0];
#if DBG
DbgPrint("HalpSaveConfiguration: Writing Eisa Data to Prom\n");
DbgPrint("Prom address = %x, Volatile Address = %x\n",NvChars,VChars);
DbgPrint("ConfigSize = %X\n",EisaSize);
#endif
for (Index = 0; Index < EisaSize; Index++) {
if (HalpROMByteWrite(NvChars++, *VChars++) != ESUCCESS) {
return EIO;
}
}
if (HalpEisaSetChecksum() != ESUCCESS) {
HalpROMSetReadMode((PUCHAR)NVRAM_CONFIGURATION);
return EIO;
}
//
// Free up the pool
//
ExFreePool(VolatileEisaData);
HalpROMSetReadMode((PUCHAR)NVRAM_CONFIGURATION);
//
// Re-read the prom block back into pool for later use
//
#if DBG
DbgPrint("HalpSaveConfiguration: ReLoading Environment\n");
#endif
HalpEnvironmentLoad();
return ESUCCESS;
}
ARC_STATUS
HalpConfigurationSetChecksum (
VOID
)
/*++
Routine Description:
This routine sets the configuration checksum.
This has been coded for Alpha/Jensen. It assumes that the
block containing the checksum has already been erased and
written to, and that the status of these previous operations
has already been checked. This is because we have to set the
PROM into ReadArray mode in order to compute the checksum,
and this will cause previous status to be lost.
Arguments:
None.
Return Value:
None. The PROM status is *not* checked by this function!
--*/
{
PUCHAR NvChars;
PNV_CONFIGURATION NvConfiguration;
ULONG Index;
ULONG Checksum1;
KIRQL OldIrql;
#if DBG
DbgPrint("In set Config Checksum\n");
#endif
NvConfiguration = (PNV_CONFIGURATION)NVRAM_CONFIGURATION;
//
// Form checksum from NVRAM data.
//
Checksum1 = 0;
NvChars = (PUCHAR)NvConfiguration;
HalpROMSetReadMode(NvChars);
KeRaiseIrql(DEVICE_LEVEL, &OldIrql);
for ( Index = 0 ;
Index < sizeof(COMPRESSED_CONFIGURATION_PACKET) * NUMBER_OF_ENTRIES +
LENGTH_OF_IDENTIFIER + LENGTH_OF_DATA;
Index++ ) {
Checksum1 += READ_PORT_UCHAR( NvChars++ );
}
KeLowerIrql(OldIrql);
//
// Set checksum.
//
HalpROMResetStatus((PUCHAR)NvConfiguration);
if ((HalpROMByteWrite( &NvConfiguration->Checksum1[0],
(UCHAR)(Checksum1 & 0xFF)) != ESUCCESS) ||
(HalpROMByteWrite( &NvConfiguration->Checksum1[1],
(UCHAR)((Checksum1 >> 8) & 0xFF)) != ESUCCESS) ||
(HalpROMByteWrite( &NvConfiguration->Checksum1[2],
(UCHAR)((Checksum1 >> 16) & 0xFF)) != ESUCCESS) ||
(HalpROMByteWrite( &NvConfiguration->Checksum1[3],
(UCHAR)(Checksum1 >> 24)) != ESUCCESS)) {
return EIO;
} else {
return ESUCCESS;
}
}
ARC_STATUS
HalpEisaSetChecksum (
VOID
)
/*++
Routine Description:
This routine sets the eisa data checksum.
This has been coded for Alpha/Jensen. It assumes that the
block containing the checksum has already been erased and
written to, and that the status of these previous operations
has already been checked. This is because we have to set the
PROM into ReadArray mode in order to compute the checksum,
and this will cause previous status to be lost.
Arguments:
None.
Return Value:
None. The PROM status is *not* checked by this function!
--*/
{
PUCHAR NvChars;
PNV_CONFIGURATION NvConfiguration;
ULONG Index;
ULONG Checksum3;
KIRQL OldIrql;
NvConfiguration = (PNV_CONFIGURATION)NVRAM_CONFIGURATION;
//
// Form checksum from NVRAM data.
//
Checksum3 = 0;
NvChars = (PUCHAR)&NvConfiguration->EisaData[0];
HalpROMSetReadMode(NvChars);
KeRaiseIrql(DEVICE_LEVEL, &OldIrql);
for ( Index = 0 ;
Index < LENGTH_OF_EISA_DATA;
Index++ ) {
Checksum3 += READ_PORT_UCHAR( NvChars++ );
}
KeLowerIrql(OldIrql);
//
// Set checksum.
//
HalpROMResetStatus((PUCHAR)&NvConfiguration->EisaData[0]);
if ((HalpROMByteWrite( &NvConfiguration->Checksum3[0],
(UCHAR)(Checksum3 & 0xFF)) != ESUCCESS) ||
(HalpROMByteWrite( &NvConfiguration->Checksum3[1],
(UCHAR)((Checksum3 >> 8) & 0xFF)) != ESUCCESS) ||
(HalpROMByteWrite( &NvConfiguration->Checksum3[2],
(UCHAR)((Checksum3 >> 16) & 0xFF)) != ESUCCESS) ||
(HalpROMByteWrite( &NvConfiguration->Checksum3[3],
(UCHAR)(Checksum3 >> 24)) != ESUCCESS)) {
return EIO;
} else {
return ESUCCESS;
}
}
VOID
HalpInitializePromTimer(
IN OUT PPROMTIMER PrmTimer,
IN PVOID FunctionContext
)
/*++
Routine Description:
This routine will initialize the timer needed for waits on prom updates
Arguments:
None.
Return Value:
None.
--*/
{
//
// Initialize the signaling event
//
KeInitializeEvent(
&PromEvent,
NotificationEvent,
FALSE
);
//
// Initialize the timer
//
KeInitializeTimer(
&(PrmTimer->Timer)
);
//
// Setup the DPC that will signal the event
//
KeInitializeDpc(
&(PrmTimer->Dpc),
(PKDEFERRED_ROUTINE)HalpPromDpcHandler,
FunctionContext
);
}
VOID
HalpSetPromTimer(
IN PPROMTIMER PrmTimer,
IN ULONG MillisecondsToDelay
)
/*++
Routine Description:
This routine will initialize the timer needed for waits on prom updates
Arguments:
None.
Return Value:
None.
--*/
{
LARGE_INTEGER FireUpTime;
if (MillisecondsToDelay == 0 ) {
MillisecondsToDelay = 1;
}
FireUpTime.LowPart = -10000 * MillisecondsToDelay;
FireUpTime.HighPart = -1;
//
// Set the timer
//
KeSetTimer(
&PrmTimer->Timer,
FireUpTime,
&PrmTimer->Dpc
);
}
VOID
HalpPromDpcHandler(
IN PVOID SystemSpecific,
IN PVOID Context,
IN PVOID SystemArgument1,
IN PVOID SystemArgument2
)
/*++
Routine Description:
This routine is the DPC handler for the prom timer
Arguments:
None.
Return Value:
None.
--*/
{
UNREFERENCED_PARAMETER(SystemSpecific);
UNREFERENCED_PARAMETER(SystemArgument1);
UNREFERENCED_PARAMETER(SystemArgument2);
//
// Set the event so the waiting thread will continue.
//
KeSetEvent(
&PromEvent,
0L,
FALSE
);
return;
}
VOID
HalpPromDelay(
IN ULONG Milliseconds
)
/*++
Routine Description:
This routine calls the timer and waits for it to fire
Arguments:
None.
Return Value:
None.
--*/
{
LARGE_INTEGER TimeOut;
NTSTATUS status;
TimeOut.LowPart = -10000 * (Milliseconds * 2);
TimeOut.HighPart = -1;
//
// Start the timer
//
HalpSetPromTimer(&PromTimer, Milliseconds);
//
// Wait for the event to be signaled
//
status =
KeWaitForSingleObject(
&PromEvent,
Executive,
KernelMode,
FALSE,
&TimeOut
);
//
// Reset the event
//
KeResetEvent(
&PromEvent
);
return;
}