diff options
author | Adam <you@example.com> | 2020-05-17 05:51:50 +0200 |
---|---|---|
committer | Adam <you@example.com> | 2020-05-17 05:51:50 +0200 |
commit | e611b132f9b8abe35b362e5870b74bce94a1e58e (patch) | |
tree | a5781d2ec0e085eeca33cf350cf878f2efea6fe5 /private/ntos/nthals/halalpha/28f008sa.c | |
download | NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.gz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.bz2 NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.lz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.xz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.zst NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.zip |
Diffstat (limited to 'private/ntos/nthals/halalpha/28f008sa.c')
-rw-r--r-- | private/ntos/nthals/halalpha/28f008sa.c | 317 |
1 files changed, 317 insertions, 0 deletions
diff --git a/private/ntos/nthals/halalpha/28f008sa.c b/private/ntos/nthals/halalpha/28f008sa.c new file mode 100644 index 000000000..487a908d8 --- /dev/null +++ b/private/ntos/nthals/halalpha/28f008sa.c @@ -0,0 +1,317 @@ +#include "halp.h" +#include "arccodes.h" +#include "flash8k.h" + +#define I28F008SA_DEVICE_SIZE 0x100000 + +#define SET_READ_ARRAY 0xff +#define SET_BYTE_WRITE 0x40 +#define SET_ERASE_BLOCK 0x20 +#define CONFIRM_ERASE_BLOCK 0xd0 +#define READ_STATUS 0x70 +#define RESET_STATUS 0x50 +#define ID_REQUEST 0x90 + +#define MANUFACTURER_ID 0x89 +#define DEVICE_ID 0xa2 + +#define BLOCK_SIZE 0x10000 +#define BLANK_DATA 0xff + +#define TIMEOUT_VALUE 5000000 + +#define STATUS_READY 0x80 +#define STATUS_ERASE_SUSP 0x40 +#define STATUS_ERASE_ERR 0x20 +#define STATUS_WRITE_ERR 0x10 +#define STATUS_VPP_LOW 0x08 +#define STATUS_CMD_SEQ_ERR (STATUS_WRITE_ERR | STATUS_READ_ERR) + +// +// Local function prototypes +// +PFLASH_DRIVER +I28F008SA_Initialize( + IN PUCHAR NvRamPtr + ); + +ARC_STATUS +I28F008SA_SetReadMode( + IN PUCHAR Address + ); + +ARC_STATUS +I28F008SA_WriteByte( + IN PUCHAR Address, + IN UCHAR Data + ); + +ARC_STATUS +I28F008SA_EraseBlock( + IN PUCHAR Address + ); + +ARC_STATUS +I28F008SA_CheckStatus( + IN PUCHAR Address, + FLASH_OPERATIONS Operation + ); + +PUCHAR +I28F008SA_BlockAlign( + IN PUCHAR Address + ); + +UCHAR +I28F008SA_ReadByte( + IN PUCHAR Address + ); + +BOOLEAN +I28F008SA_OverwriteCheck( + IN UCHAR OldData, + IN UCHAR NewData + ); + +ULONG +I28F008SA_BlockSize( + IN PUCHAR Address + ); + +ULONG +I28F008SA_GetLastError( + VOID + ); + +static +VOID +I28F008SA_SetLastError( + ULONG FlashStatus + ); + +FLASH_DRIVER I28F008SA_DriverInformation = { + "Intel 28F008SA", + I28F008SA_SetReadMode, // SetReadModeFunction + I28F008SA_WriteByte, // WriteByteFunction + I28F008SA_EraseBlock, // EraseBlockFunction + I28F008SA_BlockAlign, // AlignBlockFunction + I28F008SA_ReadByte, // ReadByteFunction + I28F008SA_OverwriteCheck, // OverwriteCheckFunction + I28F008SA_BlockSize, // BlockSizeFunction + I28F008SA_GetLastError, // GetLastErrorFunction + I28F008SA_DEVICE_SIZE, // DeviceSize + BLANK_DATA // ErasedData + }; + +static ULONG I28F008SA_LastError; + +PFLASH_DRIVER +I28F008SA_Initialize( + IN PUCHAR NvRamPtr + ) +{ + PFLASH_DRIVER ReturnDriver = NULL; + UCHAR ManufacturerID; + UCHAR DeviceID; + + NvRamPtr = I28F008SA_BlockAlign(NvRamPtr); + + WRITE_CONFIG_RAM_DATA(NvRamPtr, ID_REQUEST); + + ManufacturerID = READ_CONFIG_RAM_DATA(NvRamPtr); + DeviceID = READ_CONFIG_RAM_DATA((PUCHAR)((ULONG)NvRamPtr + 1)); + + if ((ManufacturerID == MANUFACTURER_ID) && (DeviceID == DEVICE_ID)) { + I28F008SA_LastError = 0; + I28F008SA_SetReadMode(NvRamPtr); + ReturnDriver = &I28F008SA_DriverInformation; + } + + return ReturnDriver; +} + +ARC_STATUS +I28F008SA_SetReadMode( + IN PUCHAR NvRamPtr + ) +{ + WRITE_CONFIG_RAM_DATA(NvRamPtr, SET_READ_ARRAY); + HalpMb(); + + return ESUCCESS; +} + +ARC_STATUS +I28F008SA_WriteByte( + IN PUCHAR NvRamPtr, + IN UCHAR Data + ) +{ + ARC_STATUS ReturnStatus; + + I28F008SA_SetReadMode(NvRamPtr); + + WRITE_CONFIG_RAM_DATA(NvRamPtr, SET_BYTE_WRITE); + WRITE_CONFIG_RAM_DATA(NvRamPtr, Data); + + ReturnStatus = I28F008SA_CheckStatus(NvRamPtr, FlashByteWrite); + + I28F008SA_SetReadMode(NvRamPtr); + + return ReturnStatus; +} + +ARC_STATUS +I28F008SA_EraseBlock ( + IN PUCHAR NvRamPtr + ) +{ + ARC_STATUS ReturnStatus; + + WRITE_CONFIG_RAM_DATA(NvRamPtr, SET_ERASE_BLOCK); + WRITE_CONFIG_RAM_DATA(NvRamPtr, CONFIRM_ERASE_BLOCK); + + ReturnStatus = I28F008SA_CheckStatus(NvRamPtr, FlashEraseBlock); + + I28F008SA_SetReadMode(NvRamPtr); + + return ReturnStatus; +} + +ARC_STATUS +I28F008SA_CheckStatus ( + IN PUCHAR NvRamPtr, + IN FLASH_OPERATIONS Operation + ) +{ + ARC_STATUS ReturnStatus = EIO; + ULONG Timeout; + UCHAR FlashStatus; + + // + // Keep reading the status until the device is done with its + // current operation. + // + Timeout = TIMEOUT_VALUE; + do { + WRITE_CONFIG_RAM_DATA(NvRamPtr, READ_STATUS); + FlashStatus = READ_CONFIG_RAM_DATA(NvRamPtr); + KeStallExecutionProcessor(1); + Timeout--; + } while (((FlashStatus & 0x80) == 0) && (Timeout > 0)); + + // + // Check the status for the operation requested. + // + switch(Operation) { + case FlashByteWrite: + if ((FlashStatus & 0x18) == 0) { + ReturnStatus = ESUCCESS; + } else { + I28F008SA_SetLastError(FlashStatus & 0x18); + } + break; + case FlashEraseBlock: + if (((FlashStatus & 0x28) == 0) && ((FlashStatus & 0x30) != 0x30)) { + ReturnStatus = ESUCCESS; + } else { + I28F008SA_SetLastError(FlashStatus & 0x28); + } + break; + } + if ((FlashStatus & 0x80) == 0) { + ReturnStatus = EIO; + I28F008SA_SetLastError(0); + } + + // + // Clear the flash status register + // This is a silent operation. The status that gets returned is the + // status of the real operation as determined above. + // + WRITE_CONFIG_RAM_DATA(NvRamPtr, RESET_STATUS); + Timeout = TIMEOUT_VALUE; + do { + WRITE_CONFIG_RAM_DATA(NvRamPtr, READ_STATUS); + FlashStatus = READ_CONFIG_RAM_DATA(NvRamPtr); + KeStallExecutionProcessor(1); + Timeout--; + } while (((FlashStatus & 0x80) == 0) && (Timeout > 0)); + + return ReturnStatus; +} + +PUCHAR +I28F008SA_BlockAlign( + IN PUCHAR Address + ) +{ + return (PUCHAR)((ULONG)Address & ~(BLOCK_SIZE-1)); +} + +UCHAR +I28F008SA_ReadByte( + IN PUCHAR Address + ) +{ + return READ_CONFIG_RAM_DATA(Address); +} + +BOOLEAN +I28F008SA_OverwriteCheck( + IN UCHAR OldData, + IN UCHAR NewData + ) +/*++ + +Return Value: + + Zero if OldData can be overwritten with NewData. + Non-zero if device must be erased to write NewData. + +--*/ +{ + return (~OldData & NewData) ? FALSE : TRUE; +} + +ULONG +I28F008SA_BlockSize( + IN PUCHAR Address + ) +/*++ + +Return Value: + + The block size of the device. This is a constant because all + blocks in the 28f008sa are the same size. + +--*/ +{ + return BLOCK_SIZE; +} + +ULONG +I28F008SA_GetLastError( + VOID + ) +{ + return I28F008SA_LastError; +} + +static +VOID +I28F008SA_SetLastError( + ULONG FlashStatus + ) +{ + I28F008SA_LastError = ERROR_UNKNOWN; + if (FlashStatus == 0) + I28F008SA_LastError = ERROR_TIMEOUT; + if (FlashStatus & STATUS_WRITE_ERR) + I28F008SA_LastError = ERROR_WRITE_ERROR; + if (FlashStatus & STATUS_ERASE_ERR) + I28F008SA_LastError = ERROR_ERASE_ERROR; + if (FlashStatus & STATUS_VPP_LOW) + I28F008SA_LastError = ERROR_VPP_LOW; +} + |