NT4/private/ntos/nthals/halalpha/flash8k.c

324 lines
8.0 KiB
C
Raw Normal View History

2001-01-01 00:00:00 +01:00
/*++
Copyright (c) 1994 Digital Equipment Corporation
Module Name:
flash8k.c
Abstract:
This module implements the flash-specific, device-independent routines
necessary to Read and Write the flash ROM containing the system environment
variables. The routines implemented here are:
HalpReadNVRamBuffer() - copy data from Flash into memory
HalpWriteNVRamBuffer() - write memory data to Flash
HalpCopyNVRamBuffer() - stubbed for compatibility with NVRAM
Author:
Steve Brooks 5-Oct 93
Revision History:
--*/
#include "halp.h"
#include "flash8k.h"
#include "arccodes.h"
//
// Variables:
//
// PFLASH_DRIVER HalpFlashDriver
// Pointer to the device-specific flash driver.
//
PFLASH_DRIVER HalpFlashDriver = NULL;
//
// Flash Drivers
//
// Each platform which uses this module must define FlashDriverList as an
// array of pointers to the initialize functions of any flash drivers for
// which the flash device might be used for the environment in the system.
//
extern PFLASH_DRIVER (*FlashDriverList[])(PUCHAR);
#ifdef AXP_FIRMWARE
#pragma alloc_text(DISTEXT, HalpReadNVRamBuffer )
#pragma alloc_text(DISTEXT, HalpWriteNVRamBuffer )
#pragma alloc_text(DISTEXT, HalpCopyNVRamBuffer )
#pragma alloc_text(DISTEXT, HalpInitializeFlashDriver )
#endif
ARC_STATUS HalpReadNVRamBuffer (
OUT PCHAR DataPtr,
IN PCHAR NvRamPtr,
IN ULONG Length )
/*++
Routine Description:
This routine Reads data from the NVRam into main memory
Arguments:
DataPtr - Pointer to memory location to receive data
NvRamPtr - Pointer (qva) to NVRam location to read data from
Length - Number of bytes of data to transfer
Return Value:
ESUCCESS if the operation succeeds.
ENODEV if no flash driver is loaded
--*/
{
//
// If there is no flash driver, return an error.
//
if ((HalpFlashDriver == NULL) &&
((HalpFlashDriver = HalpInitializeFlashDriver(NvRamPtr)) == NULL)) {
return ENODEV;
}
//
// Read from the flash.
//
while(Length--) {
*DataPtr = HalpFlash8kReadByte(NvRamPtr);
DataPtr++;
NvRamPtr++;
}
return ESUCCESS;
}
//
//
//
ARC_STATUS
HalpWriteNVRamBuffer (
IN PCHAR NvRamPtr,
IN PCHAR DataPtr,
IN ULONG Length )
/*++
Routine Description:
This routine Writes data from memory into the NVRam
Arguments:
NvRamPtr - Pointer (qva) to NVRam location to write data into
DataPtr - Pointer to memory location of data to be written
Length - Number of bytes of data to transfer
Return Value:
ESUCCESS if the operation succeeds.
ENODEV if no flash driver is loaded
EIO if a device error was detected
--*/
{
ARC_STATUS ReturnStatus = ESUCCESS;
UCHAR NeedToErase = FALSE;
UCHAR Byte;
ULONG Index;
ULONG Address;
//
// If there is no flash driver, return an error.
//
if ((HalpFlashDriver == NULL) &&
((HalpFlashDriver = HalpInitializeFlashDriver(NvRamPtr)) == NULL)) {
return ENODEV;
}
//
// Try to do the udate without erasing the flash block if possible.
// We don't write bytes which agree with the current contents of the
// flash. If the byte to be written is not the same as what is already
// in the flash, write it if the new byte can overwrite the old byte.
// On the first byte that cannot be overwritten, abort this loop with
// NeedToErase == TRUE and fall through to the failsafe case below.
//
NeedToErase = FALSE;
for(Index = Length;
!NeedToErase && (ReturnStatus == ESUCCESS) && Index--;) {
Address = (ULONG)NvRamPtr + Index;
if (((Byte = HalpFlash8kReadByte((PUCHAR)Address)) !=
(UCHAR)DataPtr[Index])) {
if (HalpFlash8kOverwriteCheck(Byte, (UCHAR)DataPtr[Index])) {
ReturnStatus = HalpFlash8kWriteByte(Address, DataPtr[Index]);
} else {
#if defined(ALPHA_FW_KDHOOKS) || defined(HALDBG)
DbgPrint("Need to erase flash because byte at %08x (%02x) ",
Address, Byte);
DbgPrint("Cannot be written with %02x\r\n",
(UCHAR)DataPtr[Index]);
#endif
NeedToErase = TRUE;
}
}
}
if (NeedToErase) {
ULONG BlockSize;
ULONG BlockBase;
ULONG DataBase;
PUCHAR pShadow = NULL;
//
// We need to erase the flash block in order to write some of the
// requested data. We take the safe approach of copy the entire
// flash block into memory (we don't know what else is there), modify
// the copy in memory, erase the flash block, and write the entire
// block.
//
DataBase = (ULONG)NvRamPtr & ~(ULONG)HalpCMOSRamBase;
BlockBase = (ULONG)HalpFlash8kBlockAlign(NvRamPtr);
BlockSize = HalpFlash8kBlockSize(BlockBase);
pShadow = ExAllocatePool(NonPagedPool, BlockSize);
if (pShadow != NULL) {
for(Index = 0; Index < BlockSize; Index++) {
pShadow[Index] = HalpFlash8kReadByte(BlockBase + Index);
}
for(Index = 0; Index < Length; Index++) {
pShadow[DataBase + Index] = DataPtr[Index];
}
ReturnStatus = HalpFlash8kEraseBlock(BlockBase);
for(Index = 0;
(Index < BlockSize) && (ReturnStatus == ESUCCESS);
Index++) {
if (pShadow[Index] != HalpFlashDriver->ErasedData) {
ReturnStatus = HalpFlash8kWriteByte(BlockBase + Index,
pShadow[Index]);
}
}
ExFreePool(pShadow);
} else {
#if defined(ALPHA_KDHOOKS) || defined(HALDBG)
DbgPrint("HalpWriteNVRamBuffer: Could not allocate shadow...\r\n");
#endif
ReturnStatus = ENOMEM;
}
}
HalpFlash8kSetReadMode(NvRamPtr);
return ReturnStatus;
}
//
//
//
ARC_STATUS HalpCopyNVRamBuffer (
IN PCHAR NvDestPtr,
IN PCHAR NvSrcPtr,
IN ULONG Length )
/*++
Routine Description:
This routine is not supported.
Arguments:
NvDestPtr - Pointer (qva) to NVRam location to write data into
NvSrcPtr - Pointer (qva) to NVRam location of data to copy
Length - Number of bytes of data to transfer
Return Value:
ENODEV if no flash driver is loaded
EIO if a flash driver is loaded
--*/
{
//
// If there is no flash driver, return an error.
//
if (HalpFlashDriver == NULL) {
return ENODEV;
}
return EIO;
}
PFLASH_DRIVER
HalpInitializeFlashDriver(
IN PCHAR NvRamPtr
)
/*++
Routine Description:
This routine attempts to recognize the flash device present in the
system by calling each known flash driver's Initialize() function
with the address passed in. The Initialize() functions will each
return NULL if they do not recognize the flash device at the specified
address and a pointer to a FLASH_DRIVER structure if the device is
recognized. This routine looks until it either recognizes a flash device
or runs out of known flash devices.
Arguments:
NvRamPtr - a pointer to an address within the flash device
Return Value:
A pointer to the FLASH_DRIVER structure of the driver which corresponds
to the flash device in the system. NULL if no known flash device was
recognized.
--*/
{
PFLASH_DRIVER FlashDriver = NULL;
ULONG DriverNumber;
for(DriverNumber=0; FlashDriverList[DriverNumber] != NULL; DriverNumber++) {
FlashDriver = FlashDriverList[DriverNumber](NvRamPtr);
if (FlashDriver != NULL) {
break;
}
}
#ifdef ALPHA_FW_SERDEB
if (FlashDriver != NULL) {
SerFwPrint("Flash device found at %08x: %s\r\n",
NvRamPtr,
FlashDriver->DeviceName);
} else {
SerFwPrint("ERROR: No flash device found at %08x\r\n", NvRamPtr);
}
#endif
return FlashDriver;
}