324 lines
8.0 KiB
C
324 lines
8.0 KiB
C
|
/*++
|
|||
|
|
|||
|
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;
|
|||
|
}
|
|||
|
|