summaryrefslogblamecommitdiffstats
path: root/private/ntos/nthals/halalpha/flash8k.c
blob: 96d1988454910ee8973613a7d9a8203edb80a75a (plain) (tree)


































































































































































































































































































































                                                                                
/*++

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;
}