summaryrefslogtreecommitdiffstats
path: root/private/ntos/nthals/halalpha/28f008sa.c
diff options
context:
space:
mode:
authorAdam <you@example.com>2020-05-17 05:51:50 +0200
committerAdam <you@example.com>2020-05-17 05:51:50 +0200
commite611b132f9b8abe35b362e5870b74bce94a1e58e (patch)
treea5781d2ec0e085eeca33cf350cf878f2efea6fe5 /private/ntos/nthals/halalpha/28f008sa.c
downloadNT4.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.c317
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;
+}
+