/******************************************************************************* NAME nvsramDiag.c SUMMARY NVSRAM function diagnostics VERSION %version: 1 % UPDATE DATE %date_modified: May 7 10:10 2009 % PROGRAMMER %created_by: Jim Tu % Copyright 2009 Quanta Corporation. All Rights Reserved. DESCRIPTION: This file has code to test NVSRAM NOTES: REFERENCE: *******************************************************************************/ #include #include #include #include #include #include #include #include #include #include #include #include "fpgaNvsramLockDiag.h" #include "fpgaNvsram.h" #include "fpgaRegLib.h" #include "fpgaCmdLib.h" #define NVSRAM_DATALINES_PATTERNS_NUMBER 4 #define NVSRAM_BYTE_PATTERNS_NUMBER 7 unsigned char gNvsramDataLinesPatternsCnt = NVSRAM_DATALINES_PATTERNS_NUMBER; unsigned char gNvsramBytePatternsCnt = NVSRAM_BYTE_PATTERNS_NUMBER; /*NVSRAM Data Line Diagnostics Pattern*/ unsigned char gNvsramDataLinesPatterns[NVSRAM_DATALINES_PATTERNS_NUMBER] = { 0xFF, //inverse: 0x00 0xAA, //inverse: 0x55 0xCC, //inverse: 0x33 0xF0 //inverse: 0x0F }; /*NVSRAM Byte Pattern Diagnostics Pattern*/ unsigned char gNvsramBytePatterns[NVSRAM_BYTE_PATTERNS_NUMBER] = { 0x00, //inverse: 0xFF 0x7F, //inverse: 0x80 0xAA, //inverse: 0x55 0xFF, //inverse: 0x00 0xCC, //inverse: 0x33 0xF0, //inverse: 0x0F 0x55 //inverse: 0xAA }; /******************************************************************************* * PROCEDURE * * NAME: nvsramBackup * * SUMMARY: NVSRAM backup process * * SCOPE: private * * DESCRIPTION: backup NVSRAM content into memory before NVSRAM diagnostics * * RESTRICTIONS: * * RETURNS: */ void nvsramBackup ( void* startAddrVirtualP, //test start physical address unsigned int backupLength, //test memory size in byte void* originalDataBackupP //test memory original content backup start address ) { //Unlock NVSRAM fpgaNvsramUnlockAll(); //allocate virtual memory and backup buffer memset(originalDataBackupP, 0, backupLength); //copy original content in NVSRAM to memory buffer memcpy(originalDataBackupP, startAddrVirtualP, backupLength); } /******************************************************************************* * PROCEDURE * * NAME: nvsramRestore * * SUMMARY: NVSRAM restore process * * SCOPE: private * * DESCRIPTION: restore NVSRAM content from memory after NVSRAM diagnostics * * RESTRICTIONS: * * RETURNS: */ void nvsramRestore ( void* startAddrVirtualP, //test start physical address unsigned int backupLength, //test memory size in byte void* originalDataBackupP //test memory original content backup start address ) { //Unlock NVSRAM fpgaNvsramUnlockAll(); //copy original content in NVSRAM from memory buffer memcpy(startAddrVirtualP, originalDataBackupP, backupLength); } /******************************************************************************* * PROCEDURE * * NAME: nvsramDataLinesTest * * SUMMARY: NVSRAM data line test * * SCOPE: private * * DESCRIPTION: use the data line test method to verify * if the NVSRAM data lines are functional * * RESTRICTIONS: * * RETURNS: TRUE: Pass * FALSE: Fail */ int nvsramDataLinesTest ( void* startAddrVirtualP, //test start virtual address unsigned int nvsramLength //test memory size in byte ) { int result = TRUE; void* originalDataBackupP = NULL; volatile unsigned char *addr; unsigned char pattern; unsigned char observedValue; int i; //The pointer shall not point to any buffer, anyway, free it before alloc! if(originalDataBackupP) { kfree(originalDataBackupP); originalDataBackupP = NULL; } //alloc the buffer to be the container originalDataBackupP = (unsigned char*)kmalloc(nvsramLength, GFP_KERNEL); if(originalDataBackupP == NULL) { printk("[NVSRAM] Backup space is not ready.\n"); commReportError(MEC_NVSRAM, MEM_DIAG_ITEM_CODE_DATALINES, MEM_DIAG_ERROR_CODE_BAD_DL, MEM_DIAG_ERROR_MSG_BAD_DL, 0, 0, 0, 0); } //printk("[NVSRAM] originalDataBackupP = 0x%08X %08X.\n", (unsigned int)(((UINT64)originalDataBackupP) >> 32), (unsigned int)(UINT64)originalDataBackupP); //since success to get the buffer, back up the current data into the buffer if(originalDataBackupP) { //backup NVSRAM content nvsramBackup(startAddrVirtualP, nvsramLength, originalDataBackupP); //assign test address addr = startAddrVirtualP; /*************************/ /* Start Data Lines Test */ /*************************/ //write the pattern into tested region for(i = 0; i < (gNvsramDataLinesPatternsCnt * 2); i++) { //get a pattern pattern = gNvsramDataLinesPatterns[i/2]; if(i%2) { pattern = ~pattern; } //write the pattern *addr++ = (unsigned char)pattern; } addr = startAddrVirtualP; //verify the content from the test region for(i = 0; i < (gNvsramDataLinesPatternsCnt * 2); i++) { //get a pattern pattern = gNvsramDataLinesPatterns[i/2]; if(i%2) { pattern = ~pattern; } observedValue = *(addr + i); if(observedValue != pattern) { //Report error commReportError(MEC_NVSRAM, MEM_DIAG_ITEM_CODE_DATALINES, MEM_DIAG_ERROR_CODE_BAD_DL, MEM_DIAG_ERROR_MSG_BAD_DL, (u64)(startAddrVirtualP + i * sizeof(unsigned char)), (u64)observedValue, (u64)pattern, DG_MEMORY_BYTE_FORMAT); result = FALSE; } } //restore NVSRAM nvsramRestore(startAddrVirtualP, nvsramLength, originalDataBackupP); } //free backup buffer kfree(originalDataBackupP); originalDataBackupP = NULL; return result; } /******************************************************************************* * PROCEDURE * * NAME: nvsramAddressLinesTest * * SUMMARY: NVSRAM address line test * * SCOPE: private * * DESCRIPTION: use the address line test method to verify * if the NVSRAM address lines are functional * * RESTRICTIONS: * * RETURNS: TRUE: Pass * FALSE: Fail */ int nvsramAddressLinesTest ( void* startAddrVirtualP, //test start virtual address unsigned int nvsramLength //test memory size in byte ) { int result = TRUE; void* originalDataBackupP = NULL; unsigned int sizeTemp; unsigned char testBitsNumber = 0; volatile unsigned char *addr; unsigned int addrOffset; unsigned int data; int i; //The pointer shall not point to any buffer, anyway, free it before alloc! if(originalDataBackupP) { kfree(originalDataBackupP); originalDataBackupP = NULL; } //alloc the buffer to be the container originalDataBackupP = (unsigned char*)kmalloc(nvsramLength, GFP_KERNEL); if(originalDataBackupP == NULL) { printk("[NVSRAM] Backup space is not ready.\n"); commReportError(MEC_NVSRAM, MEM_DIAG_ITEM_CODE_ADDRESSLINES, MEM_DIAG_ERROR_CODE_BAD_AL, MEM_DIAG_ERROR_MSG_BAD_AL, 0, 0, 0, 0); } //printk("[NVSRAM] originalDataBackupP = 0x%08X %08X.\n", (unsigned int)(((UINT64)originalDataBackupP) >> 32), (unsigned int)(UINT64)originalDataBackupP); //since success to get the buffer, back up the current data into the buffer if(originalDataBackupP) { //backup NVSRAM content nvsramBackup(startAddrVirtualP, nvsramLength, originalDataBackupP); //get bit number should be test sizeTemp = nvsramLength; while(sizeTemp) { testBitsNumber++; sizeTemp >>= 1; } /****************************/ /* Address Lines Test Write */ /****************************/ addrOffset = 0; data = 0; // Write 0 in addr:0x00000000 // Write 1 in addr:0x00000001 // Write 2 in addr:0x00000002 // Write 3 in addr:0x00000004 and so on for(i = 0; i < testBitsNumber; i++) { //Get the virtual start address addr = startAddrVirtualP + addrOffset; *addr = data++; //shift address bit addrOffset = 1 << i; } /***********************************/ /* Address Lines Test Verification */ /***********************************/ //Verify the content from specific address for expected value addrOffset = 0; data = 0; for(i = 0; i < testBitsNumber; i++) { //Get the virtual start address addr = startAddrVirtualP + addrOffset; if(*addr != data++) { //Report error commReportError(MEC_NVSRAM, MEM_DIAG_ITEM_CODE_ADDRESSLINES, MEM_DIAG_ERROR_CODE_BAD_AL, MEM_DIAG_ERROR_MSG_BAD_AL, (u64)startAddrVirtualP, (u64)*addr, (u64)data, DG_MEMORY_BYTE_FORMAT); result = FALSE; } //shift address bit addrOffset = 1 << i; } //restore NVSRAM nvsramRestore(startAddrVirtualP, nvsramLength, originalDataBackupP); } else { } //free backup buffer kfree(originalDataBackupP); originalDataBackupP = NULL; return result; } /******************************************************************************* * PROCEDURE * * NAME: nvsramWordPatternTest * * SUMMARY: NVSRAM word pattern test * * SCOPE: private * * DESCRIPTION: use the word pattern test method to verify * if the NVSRAM are functional * * RESTRICTIONS: * * RETURNS: TRUE: Pass * FALSE: Fail */ int nvsramWordPatternTest ( void* startAddrVirtualP, //test start virtual address unsigned int nvsramLength //test memory size in byte ) { int result = TRUE; void* originalDataBackupP = NULL; unsigned char pattern, observedValue; unsigned int i; unsigned int j; unsigned int numberOfPtrn; //The pointer shall not point to any buffer, anyway, free it before alloc! if(originalDataBackupP) { kfree(originalDataBackupP); originalDataBackupP = NULL; } //alloc the buffer to be the container originalDataBackupP = (unsigned char*)kmalloc(nvsramLength, GFP_KERNEL); if(originalDataBackupP == NULL) { printk("[NVSRAM] Backup space is not ready.\n"); commReportError(MEC_NVSRAM, MEM_DIAG_ITEM_CODE_EXTENDPATTERNS, MEM_DIAG_ERROR_CODE_DATA_VERIFY_ERR, MEM_DIAG_ERROR_MSG_DATA_VERIFY_ERR, 0, 0, 0, 0); } //since success to get the buffer, back up the current data into the buffer if(originalDataBackupP != NULL) { //backup NVSRAM content nvsramBackup(startAddrVirtualP, nvsramLength, originalDataBackupP); //get the number of patterns numberOfPtrn = gNvsramBytePatternsCnt; //start test pattern for(i = 0; i < numberOfPtrn; i++) { //specify the pattern pattern = gNvsramBytePatterns[i]; //write pattern into NVSRAM //for(j = 0; j < 10; j++) for(j = 0; j < nvsramLength; j++) { *(volatile unsigned char*)(startAddrVirtualP + j) = pattern; } //verify for(j = 0; j < 10; j++) //for(j = 0; j < nvsramLength; j++) { observedValue = *(volatile unsigned char*)(startAddrVirtualP + j); if(observedValue != pattern) { //Report error commReportError(MEC_NVSRAM, MEM_DIAG_ITEM_CODE_EXTENDPATTERNS, MEM_DIAG_ERROR_CODE_DATA_VERIFY_ERR, MEM_DIAG_ERROR_MSG_DATA_VERIFY_ERR, (u64)(startAddrVirtualP + j), (u64)observedValue, (u64)pattern, DG_MEMORY_BYTE_FORMAT); result = FALSE; } } commPostProgress("[NVSRAM] Word Pattern Test Progress", (i * 2) + 1, numberOfPtrn * 2); //inverse pattern pattern = ~gNvsramBytePatterns[i]; //write pattern into NVSRAM for(j = 0; j < nvsramLength; j++) { *(volatile unsigned char*)(startAddrVirtualP + j) = pattern; } //verify for(j = 0; j < nvsramLength; j++) { observedValue = *(volatile unsigned char*)(startAddrVirtualP + j); if(observedValue != pattern) { //Report error commReportError(MEC_NVSRAM, MEM_DIAG_ITEM_CODE_EXTENDPATTERNS, MEM_DIAG_ERROR_CODE_DATA_VERIFY_ERR, MEM_DIAG_ERROR_MSG_DATA_VERIFY_ERR, (u64)(startAddrVirtualP + j), (u64)observedValue, (u64)pattern, DG_MEMORY_BYTE_FORMAT); result = FALSE; } } commPostProgress("[NVSRAM] Word Pattern Test Progress", (i * 2) + 2, numberOfPtrn * 2); } //restore NVSRAM nvsramRestore(startAddrVirtualP, nvsramLength, originalDataBackupP); } //free backup buffer kfree(originalDataBackupP); originalDataBackupP = NULL; return result; } void nvsramDataLinesDiag( void ) { nvsramDataLinesTest(gFpgaBar2VirtualP + NVSRAM_ADDRESS_BASE, NVSRAM_TOTAL_SIZE); } void nvsramAddressLinesDiag( void ) { nvsramAddressLinesTest(gFpgaBar2VirtualP + NVSRAM_ADDRESS_BASE, NVSRAM_TOTAL_SIZE); } void nvsramWordPatternDiagnostic( void ) { nvsramWordPatternTest(gFpgaBar2VirtualP + NVSRAM_ADDRESS_BASE, NVSRAM_TOTAL_SIZE); } MODULE_AUTHOR( "will.lee@netapp.com" ); MODULE_DESCRIPTION( "NetApp NVSRAM Diag Code" ); MODULE_LICENSE( "GPL" ); MODULE_VERSION( "0.1" );