diff options
Diffstat (limited to 'private/ntos/nthals/hallx3/alpha/flash8k.c')
-rw-r--r-- | private/ntos/nthals/hallx3/alpha/flash8k.c | 518 |
1 files changed, 518 insertions, 0 deletions
diff --git a/private/ntos/nthals/hallx3/alpha/flash8k.c b/private/ntos/nthals/hallx3/alpha/flash8k.c new file mode 100644 index 000000000..193b2b9fc --- /dev/null +++ b/private/ntos/nthals/hallx3/alpha/flash8k.c @@ -0,0 +1,518 @@ +/*++ + +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: + + Wim Colgate 1-May-1995 + + Added LX3 specfic code for Bankset 8 mumbo-jumbo for the LX3 specific + 'Flash Bus'. + + +--*/ + + +#include "halp.h" +#include "pflash.h" +#include "flash8k.h" + +#include "arccodes.h" + +// +// To access the flash bus, one needs to enable the bankset 8 in +// the APECS chipset. +// + +#define BANKSET8_CONFIGURATION_REGISTER HAL_MAKE_QVA( 0x180000B00 ) +#define BANKSET8_ENABLE 0x1 + +#define STALL_VALUE 16 + +// +// This variable tells us which bank of 8K 'nvram' are we using +// The LX3 nvram is actually two separate 8K sections of the FLASH ROM. +// One living at 0x4000, the other at 0x8000. +// +// This 'base' is not a QVA as in other platforms -- rather it is a base +// index off of the FLASH ROM device (0-512K). + +extern ULONG Am29F400NVRAMBase; + +// +// 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[])(ULONG); + +// +// Local function prototypes. +// + +ARC_STATUS +HalpReadNVRamBuffer ( + OUT PCHAR DataPtr, + IN PCHAR NvRamOffset, + IN ULONG Length + ); + +ARC_STATUS +HalpWriteNVRamBuffer ( + IN PCHAR NvRamOffset, + IN PCHAR DataPtr, + IN ULONG Length + ); + +ARC_STATUS +HalpCopyNVRamBuffer ( + IN PCHAR NvDestPtr, + IN PCHAR NvSrcPtr, + IN ULONG Length + ); + +PFLASH_DRIVER +HalpInitializeFlashDriver( + IN ULONG NvRamOffset + ); + +#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 NvRamOffset, + IN ULONG Length ) + +/*++ + +Routine Description: + + This routine Reads data from the NVRam into main memory + +Arguments: + + DataPtr - Pointer to memory location to receive data + NvRamOffset- NVRam offset 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 + E2BIG if we attempt to read beyond the end of the NVRAM location + +--*/ +{ + ULONG CsrMask; + +#if defined(ALPHA_FW_KDHOOKS) || defined(HALDBG) + DbgPrint("HalpReadNVRamBuffer(%08x, %08x, %d)\r\n",(ULONG)DataPtr, + NvRamOffset, Length); +#endif + + // + // If there is no flash driver, return an error. + // + + if ((HalpFlashDriver == NULL) && + ((HalpFlashDriver = + HalpInitializeFlashDriver((ULONG)NvRamOffset)) == NULL)) { + + return ENODEV; + } + + // + // Check to see if we will read beyond the bounds... + // (normalize offset - base + length) + // + + if (NvRamOffset - Am29F400NVRAMBase + Length > (PUCHAR)NVRAM1_SECTOR_SIZE) { + return E2BIG; + } + + // + // Adjust the offset by the NVRAM Base -- The NVRAM Offset is going + // to be 0-8K. The Base is where in the FLASH ROM the NVRAM is located. + // Since these routines are going to call the lower FLASH ROM routines, + // (which spans 0-512K), we need to adjust the NVRAM offset appropriately. + // + + // + // Enable Bankset 8 + // + + CsrMask = READ_COMANCHE_REGISTER( BANKSET8_CONFIGURATION_REGISTER ); + WRITE_COMANCHE_REGISTER( BANKSET8_CONFIGURATION_REGISTER, + CsrMask | BANKSET8_ENABLE ); + + // + // Read from the flash. + // + + HalpFlash8kSetReadMode(NvRamOffset); + while(Length--) { + *DataPtr = HalpFlash8kReadByte(NvRamOffset); + DataPtr++; + NvRamOffset++; + } + + // + // Disable Bankset 8 (Restore original state) + // + + WRITE_COMANCHE_REGISTER( BANKSET8_CONFIGURATION_REGISTER, CsrMask ); + + return ESUCCESS; +} + +ARC_STATUS +HalpWriteNVRamBuffer ( + IN PCHAR NvRamOffset, + IN PCHAR DataPtr, + IN ULONG Length ) + +/*++ + +Routine Description: + + This routine Writes data from memory into the NVRam + +Arguments: + + NvRamOffset- NVRam Offset 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 + E2BIG if we attempt to write beyond the end of the NVRAM location + +--*/ +{ + ARC_STATUS ReturnStatus = ESUCCESS; + UCHAR NeedToErase = FALSE; + UCHAR Byte; + ULONG Index; + ULONG Offset; + ULONG CsrMask; + PUCHAR FlashBuffer; + + ULONG SectorSize; + ULONG SectorBase; + +#if defined(ALPHA_FW_KDHOOKS) || defined(HALDBG) + DbgPrint("HalpWriteNVRamBuffer(%08x, %08x, %d)\r\n", NvRamOffset, + (ULONG)DataPtr, Length); +#endif + + // + // If there is no flash driver, return an error. + // + + if ((HalpFlashDriver == NULL) && + ((HalpFlashDriver = + HalpInitializeFlashDriver((ULONG)NvRamOffset)) == NULL)) { + + return ENODEV; + } + + // + // Check to see if we will write beyond the bounds... + // (normalize offset - base + length) + // + + if (NvRamOffset - Am29F400NVRAMBase + Length > (PUCHAR)NVRAM1_SECTOR_SIZE) { + return E2BIG; + } + + // + // Enable Bankset 8 + // + + CsrMask = READ_COMANCHE_REGISTER( BANKSET8_CONFIGURATION_REGISTER ); + WRITE_COMANCHE_REGISTER( BANKSET8_CONFIGURATION_REGISTER, + CsrMask | BANKSET8_ENABLE ); + + // + // Read the whole bloody Physical NVRAM into a temporary buffer for + // comparisons + // + + SectorBase = (ULONG)HalpFlash8kSectorAlign(NvRamOffset); + SectorSize = HalpFlash8kSectorSize(SectorBase); + + FlashBuffer = ExAllocatePool(NonPagedPool, SectorSize); + if (FlashBuffer == NULL) { +#if defined(ALPHA_FW_KDHOOKS) || defined(HALDBG) + DbgPrint("HalpWriteNVRamBuffer: Could not allocate shadow\r\n"); +#endif + return ENOMEM; + } + + ReturnStatus = HalpReadNVRamBuffer(FlashBuffer, + (PUCHAR)SectorBase, + SectorSize); + + // + // Check to see if we can write the data as is. Since we're dealing with + // a flash ROM device, we can only program 1-->1 and 1-->0, but not 0-->1. + // + + Offset = (ULONG)NvRamOffset; + for (Index = 0; (Index < Length) && !NeedToErase; Index++, Offset++) { + + Byte = FlashBuffer[Offset - SectorBase]; + + if (!HalpFlash8kOverwriteCheck(Byte, (UCHAR)DataPtr[Index])) { + NeedToErase = TRUE; + +#if defined(ALPHA_FW_KDHOOKS) || defined(HALDBG) + DbgPrint("Need to erase flash because byte at %08x (%02x) ", + Offset, Byte); + DbgPrint("Cannot be written with %02x\r\n", (UCHAR)DataPtr[Index]); +#endif + + } + + } + + // + // We can either program directly, or we must erase first. + // split this path here. + // + + if (!NeedToErase) { +#if defined(ALPHA_FW_KDHOOKS) || defined(HALDBG) + DbgPrint("Don't need to erase -- simple overwrite\n"); +#endif + Offset = (ULONG)NvRamOffset; + for (Index = 0; Index < Length; Index++, Offset++) { + + // + // if byte is the same - don't bother writing + // + + Byte = FlashBuffer[Offset - SectorBase]; + + if (Byte != (UCHAR)DataPtr[Index]) { +#if defined(ALPHA_FW_KDHOOKS) || defined(HALDBG) + DbgPrint("Writing %02x at %x\n", (UCHAR)DataPtr[Index], Offset); +#endif + HalpStallExecution(STALL_VALUE); + ReturnStatus = HalpFlash8kWriteByte(Offset,DataPtr[Index]); + if (ReturnStatus != ESUCCESS) { +#if defined(ALPHA_FW_KDHOOKS) || defined(HALDBG) + DbgPrint("Failed to write %02x (was %02x) at %x status %x (Retrying...)\n", + (UCHAR)DataPtr[Index], Byte, Offset, ReturnStatus); +#endif + // + // Retry + // + + Index--; Offset--; + } + } + } + } else { + + // + // We need to erase the flash block in order to write some of the + // requested data. + // + + + // + // Merge our data with the existing FLASH ROM data. + // + + for(Index = 0; Index < Length; Index++) { + FlashBuffer[(ULONG)NvRamOffset - SectorBase + Index] = + DataPtr[Index]; + } + +#if defined(ALPHA_FW_KDHOOKS) || defined(HALDBG) + DbgPrint("Erasing sector\n"); +#endif + + // + // Erase the sector + // + + ReturnStatus = HalpFlash8kEraseSector(SectorBase); + +#if defined(ALPHA_FW_KDHOOKS) || defined(HALDBG) + DbgPrint("Returned from erase: %x\n", ReturnStatus); + DbgPrint("Writing %x bytes to %x\n", SectorSize, SectorBase); +#endif + + for (Index = 0; Index < SectorSize; Index++, Offset++) { + + if (FlashBuffer[Index] != HalpFlashDriver->ErasedData) { + + HalpStallExecution(STALL_VALUE); + + ReturnStatus = HalpFlash8kWriteByte(SectorBase + Index, + FlashBuffer[Index]); + if (ReturnStatus != ESUCCESS) { +#if defined(ALPHA_FW_KDHOOKS) || defined(HALDBG) + DbgPrint("Failed to write %02x at %x status %x (Retrying...)\n", + (UCHAR)FlashBuffer[Index], SectorBase + Index, ReturnStatus); +#endif + // + // Retry + // + + Index--; Offset--; + } + } + } + +#if defined(ALPHA_FW_KDHOOKS) || defined(HALDBG) + DbgPrint("\nReturned from write: %x\n", ReturnStatus); + DbgPrint("Wrote %x bytes\n", Index); +#endif + + } + + // + // Disable Bankset 8 (Restore original state) + // + + WRITE_COMANCHE_REGISTER( BANKSET8_CONFIGURATION_REGISTER, CsrMask ); + + HalpFlash8kSetReadMode(NvRamOffset); + + ExFreePool(FlashBuffer); + + return ReturnStatus; +} + +// +// +// +ARC_STATUS HalpCopyNVRamBuffer ( + IN PCHAR NvDestPtr, + IN PCHAR NvSrcPtr, + IN ULONG Length ) +/*++ + +Routine Description: + + This routine is not supported. + +Arguments: + + NvDestPtr- NVRam Offset to write data into + NvSrcPtr - NVRam Offset 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 defined(ALPHA_FW_KDHOOKS) || defined(HALDBG) + DbgPrint("HalpCopyNVRamBuffer()\r\n"); +#endif + + // + // If there is no flash driver, return an error. + // + if (HalpFlashDriver == NULL) { + return ENODEV; + } + + return EIO; +} + +PFLASH_DRIVER +HalpInitializeFlashDriver( + IN ULONG NvRamOffset + ) +/*++ + +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: + + NvRamOffset - an Offset 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](NvRamOffset); + if (FlashDriver != NULL) { + break; + } + } + +#if defined(ALPHA_FW_KDHOOKS) || defined(HALDBG) + if (FlashDriver == NULL) { + DbgPrint("ERROR: No flash device found at %08x\r\n", NvRamOffset); + } +#endif + + return FlashDriver; +} + |