I'm trying to understand/learn how to track down the details of a blocked session.
So I created the following setup:
Now I connect to the database twice from two different clients.
The first session issues:
I explicitly do not commit there in order to keep the locks.
In the second session I issue the same statement and of course that one waits due to locking. Now I'm trying to use the different queries floating around in order to see that session 2 is waiting for the
foo
table. Piano roll fl studio 20.sp_who2
shows the following (I removed some columns to only show the important information):This is expected, session 54 is blocked by the un-committed changes from session 52.
Querying
sys.dm_os_waiting_tasks
also shows this. The statement:returns:
Again this is expected.
My problem is, that I can't figure out how to find the actual object name that session 54 is waiting for.
I have found several queries that are joining
sys.dm_tran_locks
and sys.dm_os_waiting_tasks
like this:But in my above test scenario this join does not return anything. So either that join is wrong or
dm_tran_locks
doesn't actually contain the information I'm looking for.So what I am looking for is a query that returns something like:
'session 54 is waiting for a lock in table
'session 54 is waiting for a lock in table
foo
'.Some background info:
The real life problem I'm trying to solve is a bit more complicated, but boils down to the question 'on which table is session 54 waiting for'. The problem in question involves a largish stored procedure that updates several tables and a select from a view that accesses some of those tables. The
select
statement is blocked even though we have snapshot isolation and read committed snapshot enabled. Figuring out why the select is blocked (which I thought would not be possible if snapshot isolation is enabled) will be the next step. As a first step I'd like to find out on what that session is waiting.
Dec 03, 2013 You can test this by going to the folder that you moved the mods to (S:Civ5modsMODS in my case), creating a new text file (contents don't matter, just name it 'test'), and then going to the default location (My GamesSid Meier's Civilization 5MODS) and seeing if. Oct 26, 2016 That will probably be added when they release the actual modding programs. For now we can edit the base game manually but do save the original files before doing that in case something goes wrong so you can restore it. Civ 5 mods file locations. Recommended Civ V Mods; AI Bias Value Chart - Values vary by up to ± 2 each game. I can't find the Mod folder. Submitted 4 years ago. Everything was going fine until where he says to drop the mod files into the mod folder. I cannot find the mod folder anywhere. Is this video outdated? Has anyone had and resolved this problem? WHoward's Pick'N'Mix Mods. Maps - Rotate Start Position. Permits the player's starting position to be changed. Compatibility: Permits the player's starting position to be rotated among those available. Sid Meier's Civilization V, Civ, Civilization, 2K Games, Firaxis Games.
a_horse_with_no_namea_horse_with_no_name43.9k88 gold badges8686 silver badges119119 bronze badges
2 Answers
Max VernonBad Block Table Bbt0 Found At Pages
54.2k1313 gold badges118118 silver badges244244 bronze badges
James AndersonJames Anderson5,07922 gold badges1818 silver badges3939 bronze badges
Community♦
Amin AttarzadehAmin Attarzadeh
Not the answer you're looking for? Browse other questions tagged sql-server-2012locking or ask your own question.
PermalinkJoin GitHub today
GitHub is home to over 36 million developers working together to host and review code, manage projects, and build software together.
Sign up Find file Copy path
Cannot retrieve contributors at this time
/****************************************************************************** |
* |
* Copyright (C) 2015 - 2018 Xilinx, Inc. All rights reserved. |
* |
* Permission is hereby granted, free of charge, to any person obtaining a copy |
* of this software and associated documentation files (the 'Software'), to deal |
* in the Software without restriction, including without limitation the rights |
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
* copies of the Software, and to permit persons to whom the Software is |
* furnished to do so, subject to the following conditions: |
* |
* The above copyright notice and this permission notice shall be included in |
* all copies or substantial portions of the Software. |
* |
* THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, |
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF |
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
* SOFTWARE. |
* |
* Except as contained in this notice, the name of the Xilinx shall not be used |
* in advertising or otherwise to promote the sale, use or other dealings in |
* this Software without prior written authorization from Xilinx. |
* |
******************************************************************************/ |
/*****************************************************************************/ |
/** |
* |
* @file xnandpsu_bbm.c |
* @addtogroup nandpsu_v1_3 |
* @{ |
* |
* This file implements the Bad Block Management (BBM) functionality. |
* See xnandpsu_bbm.h for more details. |
* |
* @note None |
* |
* <pre> |
* MODIFICATION HISTORY: |
* |
* Ver Who Date Changes |
* ----- ---- ---------- ----------------------------------------------- |
* 1.0 nm 05/06/2014 First release |
* 2.0 sb 01/12/2015 Added support for writing BBT signature and version |
* in page section by enabling XNANDPSU_BBT_NO_OOB. |
* Modified Bbt Signature and Version Offset value for |
* Oob and No-Oob region. |
* 1.1 nsk 11/07/16 Change memcpy to Xil_MemCpy to handle word aligned |
* data access. |
* 1.4 nsk 04/10/18 Added ICCARM compiler support. |
* </pre> |
* |
******************************************************************************/ |
/***************************** Include Files *********************************/ |
#include<string.h>/**< For Xil_MemCpy and memset */ |
#include'xil_types.h' |
#include'xnandpsu.h' |
#include'xnandpsu_bbm.h' |
#include'xil_mem.h' |
/************************** Constant Definitions *****************************/ |
/**************************** Type Definitions *******************************/ |
/***************** Macros (Inline Functions) Definitions *********************/ |
/************************** Function Prototypes ******************************/ |
static s32 XNandPsu_ReadBbt(XNandPsu *InstancePtr, u32 Target); |
static s32 XNandPsu_SearchBbt(XNandPsu *InstancePtr, XNandPsu_BbtDesc *Desc, |
u32 Target); |
staticvoidXNandPsu_CreateBbt(XNandPsu *InstancePtr, u32 Target); |
staticvoidXNandPsu_ConvertBbt(XNandPsu *InstancePtr, u8 *Buf, u32 Target); |
static s32 XNandPsu_WriteBbt(XNandPsu *InstancePtr, XNandPsu_BbtDesc *Desc, |
XNandPsu_BbtDesc *MirrorDesc, u32 Target); |
static s32 XNandPsu_MarkBbt(XNandPsu* InstancePtr, XNandPsu_BbtDesc *Desc, |
u32 Target); |
static s32 XNandPsu_UpdateBbt(XNandPsu *InstancePtr, u32 Target); |
/************************** Variable Definitions *****************************/ |
/*****************************************************************************/ |
/** |
* This function initializes the Bad Block Table(BBT) descriptors with a |
* predefined pattern for searching Bad Block Table(BBT) in flash. |
* |
* @param InstancePtr is a pointer to the XNandPsu instance. |
* |
* @return |
* - NONE |
* |
******************************************************************************/ |
voidXNandPsu_InitBbtDesc(XNandPsu *InstancePtr) |
{ |
u32 Index; |
Xil_AssertVoid(InstancePtr != NULL); |
Xil_AssertVoid(InstancePtr->IsReady XIL_COMPONENT_IS_READY); |
/* Initialize primary Bad Block Table(BBT) */ |
for (Index = 0U; Index < XNANDPSU_MAX_TARGETS; Index++) { |
InstancePtr->BbtDesc.PageOffset[Index] = |
XNANDPSU_BBT_DESC_PAGE_OFFSET; |
} |
if (InstancePtr->EccMode XNANDPSU_ONDIE) { |
InstancePtr->BbtDesc.SigOffset = XNANDPSU_ONDIE_SIG_OFFSET; |
InstancePtr->BbtDesc.VerOffset = XNANDPSU_ONDIE_VER_OFFSET; |
} else { |
InstancePtr->BbtDesc.SigOffset = XNANDPSU_BBT_DESC_SIG_OFFSET; |
InstancePtr->BbtDesc.VerOffset = XNANDPSU_BBT_DESC_VER_OFFSET; |
} |
InstancePtr->BbtDesc.SigLength = XNANDPSU_BBT_DESC_SIG_LEN; |
InstancePtr->BbtDesc.MaxBlocks = XNANDPSU_BBT_DESC_MAX_BLOCKS; |
(void)strcpy(&InstancePtr->BbtDesc.Signature[0], 'Bbt0'); |
for (Index = 0U; Index < XNANDPSU_MAX_TARGETS; Index++) { |
InstancePtr->BbtDesc.Version[Index] = 0U; |
} |
InstancePtr->BbtDesc.Valid = 0U; |
/* Assuming that the flash device will have at least 4 blocks. */ |
if (InstancePtr->Geometry.NumTargetBlocks <= InstancePtr-> |
BbtDesc.MaxBlocks){ |
InstancePtr->BbtDesc.MaxBlocks = 4U; |
} |
/* Initialize mirror Bad Block Table(BBT) */ |
for (Index = 0U; Index < XNANDPSU_MAX_TARGETS; Index++) { |
InstancePtr->BbtMirrorDesc.PageOffset[Index] = |
XNANDPSU_BBT_DESC_PAGE_OFFSET; |
} |
if (InstancePtr->EccMode XNANDPSU_ONDIE) { |
InstancePtr->BbtMirrorDesc.SigOffset = |
XNANDPSU_ONDIE_SIG_OFFSET; |
InstancePtr->BbtMirrorDesc.VerOffset = |
XNANDPSU_ONDIE_VER_OFFSET; |
} else { |
InstancePtr->BbtMirrorDesc.SigOffset = |
XNANDPSU_BBT_DESC_SIG_OFFSET; |
InstancePtr->BbtMirrorDesc.VerOffset = |
XNANDPSU_BBT_DESC_VER_OFFSET; |
} |
InstancePtr->BbtMirrorDesc.SigLength = XNANDPSU_BBT_DESC_SIG_LEN; |
InstancePtr->BbtMirrorDesc.MaxBlocks = XNANDPSU_BBT_DESC_MAX_BLOCKS; |
(void)strcpy(&InstancePtr->BbtMirrorDesc.Signature[0], '1tbB'); |
for (Index = 0U; Index < XNANDPSU_MAX_TARGETS; Index++) { |
InstancePtr->BbtMirrorDesc.Version[Index] = 0U; |
} |
InstancePtr->BbtMirrorDesc.Valid = 0U; |
/* Assuming that the flash device will have at least 4 blocks. */ |
if (InstancePtr->Geometry.NumTargetBlocks <= InstancePtr-> |
BbtMirrorDesc.MaxBlocks){ |
InstancePtr->BbtMirrorDesc.MaxBlocks = 4U; |
} |
/* Initialize Bad block search pattern structure */ |
if (InstancePtr->Geometry.BytesPerPage > 512U) { |
/* For flash page size > 512 bytes */ |
InstancePtr->BbPattern.Options = XNANDPSU_BBT_SCAN_2ND_PAGE; |
InstancePtr->BbPattern.Offset = |
XNANDPSU_BB_PTRN_OFF_LARGE_PAGE; |
InstancePtr->BbPattern.Length = |
XNANDPSU_BB_PTRN_LEN_LARGE_PAGE; |
} else { |
InstancePtr->BbPattern.Options = XNANDPSU_BBT_SCAN_2ND_PAGE; |
InstancePtr->BbPattern.Offset = |
XNANDPSU_BB_PTRN_OFF_SML_PAGE; |
InstancePtr->BbPattern.Length = |
XNANDPSU_BB_PTRN_LEN_SML_PAGE; |
} |
for(Index = 0U; Index < XNANDPSU_BB_PTRN_LEN_LARGE_PAGE; Index++) { |
InstancePtr->BbPattern.Pattern[Index] = XNANDPSU_BB_PATTERN; |
} |
} |
/*****************************************************************************/ |
/** |
* This function scans the NAND flash for factory marked bad blocks and creates |
* a RAM based Bad Block Table(BBT). |
* |
* @param InstancePtr is a pointer to the XNandPsu instance. |
* |
* @return |
* - NONE |
* |
******************************************************************************/ |
staticvoidXNandPsu_CreateBbt(XNandPsu *InstancePtr, u32 Target) |
{ |
u32 BlockIndex; |
u32 PageIndex; |
u32 Length; |
u32 BlockOffset; |
u8 BlockShift; |
u32 NumPages; |
u32 Page; |
#ifdef __ICCARM__ |
#pragma pack(push, 1) |
u8 Buf[XNANDPSU_MAX_SPARE_SIZE] = {0U}; |
#pragma pack(pop) |
#else |
u8 Buf[XNANDPSU_MAX_SPARE_SIZE] __attribute__ ((aligned(64))) = {0U}; |
#endif |
u32 StartBlock = Target * InstancePtr->Geometry.NumTargetBlocks; |
u32 NumBlocks = InstancePtr->Geometry.NumTargetBlocks; |
s32 Status; |
/* Number of pages to search for bad block pattern */ |
if ((InstancePtr->BbPattern.Options & XNANDPSU_BBT_SCAN_2ND_PAGE) != 0U) |
{ |
NumPages = 2U; |
} else { |
NumPages = 1U; |
} |
/* Scan all the blocks for factory marked bad blocks */ |
for(BlockIndex = StartBlock; BlockIndex < (StartBlock + NumBlocks); |
BlockIndex++) { |
/* Block offset in Bad Block Table(BBT) entry */ |
BlockOffset = BlockIndex >> XNANDPSU_BBT_BLOCK_SHIFT; |
/* Block shift value in the byte */ |
BlockShift = XNandPsu_BbtBlockShift(BlockIndex); |
Page = BlockIndex * InstancePtr->Geometry.PagesPerBlock; |
/* Search for the bad block pattern */ |
for(PageIndex = 0U; PageIndex < NumPages; PageIndex++) { |
Status = XNandPsu_ReadSpareBytes(InstancePtr, |
(Page + PageIndex), &Buf[0]); |
if (Status != XST_SUCCESS) { |
/* Marking as bad block */ |
InstancePtr->Bbt[BlockOffset] |= |
(u8)(XNANDPSU_BLOCK_FACTORY_BAD << |
BlockShift); |
break; |
} |
/* |
* Read the spare bytes to check for bad block |
* pattern |
*/ |
for(Length = 0U; Length < |
InstancePtr->BbPattern.Length; Length++) { |
if (Buf[InstancePtr->BbPattern.Offset + Length] |
!= |
InstancePtr->BbPattern.Pattern[Length]) |
{ |
/* Bad block found */ |
InstancePtr->Bbt[BlockOffset] |= |
(u8) |
(XNANDPSU_BLOCK_FACTORY_BAD << |
BlockShift); |
break; |
} |
} |
} |
} |
} |
/*****************************************************************************/ |
/** |
* This function reads the Bad Block Table(BBT) if present in flash. If not it |
* scans the flash for detecting factory marked bad blocks and creates a bad |
* block table and write the Bad Block Table(BBT) into the flash. |
* |
* @param InstancePtr is a pointer to the XNandPsu instance. |
* |
* @return |
* - XST_SUCCESS if successful. |
* - XST_FAILURE if fail. |
* |
******************************************************************************/ |
s32 XNandPsu_ScanBbt(XNandPsu *InstancePtr) |
{ |
s32 Status; |
u32 Index; |
u32 BbtLen; |
Xil_AssertNonvoid(InstancePtr != NULL); |
Xil_AssertNonvoid(InstancePtr->IsReady XIL_COMPONENT_IS_READY); |
/* Zero the RAM based Bad Block Table(BBT) entries */ |
BbtLen = InstancePtr->Geometry.NumBlocks >> |
XNANDPSU_BBT_BLOCK_SHIFT; |
(void)memset(&InstancePtr->Bbt[0], 0, BbtLen); |
for (Index = 0U; Index < InstancePtr->Geometry.NumTargets; Index++) { |
if (XNandPsu_ReadBbt(InstancePtr, Index) != XST_SUCCESS) { |
/* Create memory based Bad Block Table(BBT) */ |
XNandPsu_CreateBbt(InstancePtr, Index); |
/* Write the Bad Block Table(BBT) to the flash */ |
Status = XNandPsu_WriteBbt(InstancePtr, |
&InstancePtr->BbtDesc, |
&InstancePtr->BbtMirrorDesc, Index); |
if (Status != XST_SUCCESS) { |
goto Out; |
} |
/* Write the Mirror Bad Block Table(BBT) to the flash */ |
Status = XNandPsu_WriteBbt(InstancePtr, |
&InstancePtr->BbtMirrorDesc, |
&InstancePtr->BbtDesc, Index); |
if (Status != XST_SUCCESS) { |
goto Out; |
} |
/* |
* Mark the blocks containing Bad Block Table |
* (BBT) as Reserved |
*/ |
Status = XNandPsu_MarkBbt(InstancePtr, |
&InstancePtr->BbtDesc, |
Index); |
if (Status != XST_SUCCESS) { |
goto Out; |
} |
Status = XNandPsu_MarkBbt(InstancePtr, |
&InstancePtr->BbtMirrorDesc, |
Index); |
if (Status != XST_SUCCESS) { |
goto Out; |
} |
} |
} |
Status = XST_SUCCESS; |
Out: |
return Status; |
} |
/*****************************************************************************/ |
/** |
* This function converts the Bad Block Table(BBT) read from the flash to the |
* RAM based Bad Block Table(BBT). |
* |
* @param InstancePtr is a pointer to the XNandPsu instance. |
* @param Buf is the buffer which contains BBT read from flash. |
* |
* @return |
* - NONE. |
* |
******************************************************************************/ |
staticvoidXNandPsu_ConvertBbt(XNandPsu *InstancePtr, u8 *Buf, u32 Target) |
{ |
u32 BlockOffset; |
u8 BlockShift; |
u32 Data; |
u8 BlockType; |
u32 BlockIndex; |
u32 BbtLen = InstancePtr->Geometry.NumTargetBlocks >> |
XNANDPSU_BBT_BLOCK_SHIFT; |
u32 StartBlock = Target * InstancePtr->Geometry.NumTargetBlocks; |
for(BlockOffset = StartBlock; BlockOffset < (StartBlock + BbtLen); |
BlockOffset++) { |
Data = *(Buf + BlockOffset); |
/* Clear the RAM based Bad Block Table(BBT) contents */ |
InstancePtr->Bbt[BlockOffset] = 0x0U; |
/* Loop through the every 4 blocks in the bitmap */ |
for(BlockIndex = 0U; BlockIndex < XNANDPSU_BBT_ENTRY_NUM_BLOCKS; |
BlockIndex++) { |
BlockShift = XNandPsu_BbtBlockShift(BlockIndex); |
BlockType = (u8) ((Data >> BlockShift) & |
XNANDPSU_BLOCK_TYPE_MASK); |
switch(BlockType) { |
case XNANDPSU_FLASH_BLOCK_FAC_BAD: |
/* Factory bad block */ |
InstancePtr->Bbt[BlockOffset] |= |
(u8) |
(XNANDPSU_BLOCK_FACTORY_BAD << |
BlockShift); |
break; |
case XNANDPSU_FLASH_BLOCK_RESERVED: |
/* Reserved block */ |
InstancePtr->Bbt[BlockOffset] |= |
(u8) |
(XNANDPSU_BLOCK_RESERVED << |
BlockShift); |
break; |
case XNANDPSU_FLASH_BLOCK_BAD: |
/* Bad block due to wear */ |
InstancePtr->Bbt[BlockOffset] |= |
(u8)(XNANDPSU_BLOCK_BAD << |
BlockShift); |
break; |
default: |
/* Good block */ |
/* The BBT entry already defaults to |
* zero */ |
break; |
} |
} |
} |
} |
/*****************************************************************************/ |
/** |
* This function searches the Bad Bloock Table(BBT) in flash and loads into the |
* memory based Bad Block Table(BBT). |
* |
* @param InstancePtr is the pointer to the XNandPsu instance. |
* @return |
* - XST_SUCCESS if successful. |
* - XST_FAILURE if fail. |
* |
******************************************************************************/ |
static s32 XNandPsu_ReadBbt(XNandPsu *InstancePtr, u32 Target) |
{ |
u64 Offset; |
#ifdef __ICCARM__ |
#pragma pack(push, 1) |
u8 Buf[XNANDPSU_BBT_BUF_LENGTH]= {0U}; |
#pragma pack(pop) |
#else |
u8 Buf[XNANDPSU_BBT_BUF_LENGTH] __attribute__ ((aligned(64))) = {0U}; |
#endif |
s32 Status1; |
s32 Status2; |
s32 Status; |
u32 BufLen; |
XNandPsu_BbtDesc *Desc = &InstancePtr->BbtDesc; |
XNandPsu_BbtDesc *MirrorDesc = &InstancePtr->BbtMirrorDesc; |
BufLen = InstancePtr->Geometry.NumBlocks >> |
XNANDPSU_BBT_BLOCK_SHIFT; |
/* Search the Bad Block Table(BBT) in flash */ |
Status1 = XNandPsu_SearchBbt(InstancePtr, Desc, Target); |
Status2 = XNandPsu_SearchBbt(InstancePtr, MirrorDesc, Target); |
if ((Status1 != XST_SUCCESS) && (Status2 != XST_SUCCESS)) { |
#ifdef XNANDPSU_DEBUG |
xil_printf('%s: Bad block table not foundrn',__func__); |
#endif |
Status = XST_FAILURE; |
goto Out; |
} |
#ifdef XNANDPSU_DEBUG |
xil_printf('%s: Bad block table foundrn',__func__); |
#endif |
/* Bad Block Table found */ |
if ((Desc->Valid != 0U) && (MirrorDesc->Valid != 0U)) { |
/* Valid BBT & Mirror BBT found */ |
if (Desc->Version[Target] > MirrorDesc->Version[Target]) { |
Offset = (u64)Desc->PageOffset[Target] * |
(u64)InstancePtr->Geometry.BytesPerPage; |
Status = XNandPsu_Read(InstancePtr, Offset, BufLen, |
&Buf[0]); |
if (Status != XST_SUCCESS) { |
goto Out; |
} |
/* Convert flash BBT to memory based BBT */ |
XNandPsu_ConvertBbt(InstancePtr, &Buf[0], Target); |
MirrorDesc->Version[Target] = Desc->Version[Target]; |
/* Write the BBT to Mirror BBT location in flash */ |
Status = XNandPsu_WriteBbt(InstancePtr, MirrorDesc, |
Desc, Target); |
if (Status != XST_SUCCESS) { |
goto Out; |
} |
} elseif (Desc->Version[Target] < |
MirrorDesc->Version[Target]) { |
Offset = (u64)MirrorDesc->PageOffset[Target] * |
(u64)InstancePtr->Geometry.BytesPerPage; |
Status = XNandPsu_Read(InstancePtr, Offset, BufLen, |
&Buf[0]); |
if (Status != XST_SUCCESS) { |
goto Out; |
} |
/* Convert flash BBT to memory based BBT */ |
XNandPsu_ConvertBbt(InstancePtr, &Buf[0], Target); |
Desc->Version[Target] = MirrorDesc->Version[Target]; |
/* Write the Mirror BBT to BBT location in flash */ |
Status = XNandPsu_WriteBbt(InstancePtr, Desc, |
MirrorDesc, Target); |
if (Status != XST_SUCCESS) { |
goto Out; |
} |
} else { |
/* Both are up-to-date */ |
Offset = (u64)Desc->PageOffset[Target] * |
(u64)InstancePtr->Geometry.BytesPerPage; |
Status = XNandPsu_Read(InstancePtr, Offset, BufLen, |
&Buf[0]); |
if (Status != XST_SUCCESS) { |
goto Out; |
} |
/* Convert flash BBT to memory based BBT */ |
XNandPsu_ConvertBbt(InstancePtr, &Buf[0], Target); |
} |
} elseif (Desc->Valid != 0U) { |
/* Valid Primary BBT found */ |
Offset = (u64)Desc->PageOffset[Target] * |
(u64)InstancePtr->Geometry.BytesPerPage; |
Status = XNandPsu_Read(InstancePtr, Offset, BufLen, &Buf[0]); |
if (Status != XST_SUCCESS) { |
goto Out; |
} |
/* Convert flash BBT to memory based BBT */ |
XNandPsu_ConvertBbt(InstancePtr, &Buf[0], Target); |
MirrorDesc->Version[Target] = Desc->Version[Target]; |
/* Write the BBT to Mirror BBT location in flash */ |
Status = XNandPsu_WriteBbt(InstancePtr, MirrorDesc, Desc, |
Target); |
if (Status != XST_SUCCESS) { |
goto Out; |
} |
} else { |
/* Valid Mirror BBT found */ |
Offset = (u64)MirrorDesc->PageOffset[Target] * |
(u64)InstancePtr->Geometry.BytesPerPage; |
Status = XNandPsu_Read(InstancePtr, Offset, BufLen, &Buf[0]); |
if (Status != XST_SUCCESS) { |
goto Out; |
} |
/* Convert flash BBT to memory based BBT */ |
XNandPsu_ConvertBbt(InstancePtr, &Buf[0], Target); |
Desc->Version[Target] = MirrorDesc->Version[Target]; |
/* Write the Mirror BBT to BBT location in flash */ |
Status = XNandPsu_WriteBbt(InstancePtr, Desc, MirrorDesc, |
Target); |
if (Status != XST_SUCCESS) { |
goto Out; |
} |
} |
Status = XST_SUCCESS; |
Out: |
return Status; |
} |
/*****************************************************************************/ |
/** |
* This function searches the BBT in flash. |
* |
* @param InstancePtr is the pointer to the XNandPsu instance. |
* @param Desc is the BBT descriptor pattern to search. |
* |
* @return |
* - XST_SUCCESS if successful. |
* - XST_FAILURE if fail. |
* |
******************************************************************************/ |
static s32 XNandPsu_SearchBbt(XNandPsu *InstancePtr, XNandPsu_BbtDesc *Desc, |
u32 Target) |
{ |
u32 StartBlock; |
u32 SigOffset; |
u32 VerOffset; |
u32 MaxBlocks; |
u32 PageOff; |
u32 SigLength; |
#ifdef __ICCARM__ |
#pragma pack(push, 1) |
u8 Buf[XNANDPSU_MAX_SPARE_SIZE] = {0U}; |
#pragma pack(pop) |
#else |
u8 Buf[XNANDPSU_MAX_SPARE_SIZE] __attribute__ ((aligned(64))) = {0U}; |
#endif |
u32 Block; |
u32 Offset; |
s32 Status; |
StartBlock = ((Target + (u32)1) * |
InstancePtr->Geometry.NumTargetBlocks) - (u32)1; |
SigOffset = Desc->SigOffset; |
VerOffset = Desc->VerOffset; |
MaxBlocks = Desc->MaxBlocks; |
SigLength = Desc->SigLength; |
/* Read the last 4 blocks for Bad Block Table(BBT) signature */ |
for(Block = 0U; Block < MaxBlocks; Block++) { |
PageOff = (StartBlock - Block) * |
InstancePtr->Geometry.PagesPerBlock; |
Status = XNandPsu_ReadSpareBytes(InstancePtr, PageOff, &Buf[0]); |
if (Status != XST_SUCCESS) { |
continue; |
} |
/* Check the Bad Block Table(BBT) signature */ |
for(Offset = 0U; Offset < SigLength; Offset++) { |
if (Buf[Offset + SigOffset] != |
(u8)(Desc->Signature[Offset])) |
{ |
break; /* Check the next blocks */ |
} |
} |
if (Offset >= SigLength) { |
/* Bad Block Table(BBT) found */ |
Desc->PageOffset[Target] = PageOff; |
Desc->Version[Target] = Buf[VerOffset]; |
Desc->Valid = 1U; |
Status = XST_SUCCESS; |
goto Out; |
} |
} |
/* Bad Block Table(BBT) not found */ |
Status = XST_FAILURE; |
Out: |
return Status; |
} |
/*****************************************************************************/ |
/** |
* This function writes Bad Block Table(BBT) from RAM to flash. |
* |
* @param InstancePtr is the pointer to the XNandPsu instance. |
* @param Desc is the BBT descriptor to be written to flash. |
* @param MirrorDesc is the mirror BBT descriptor. |
* |
* @return |
* - XST_SUCCESS if successful. |
* - XST_FAILURE if fail. |
* |
******************************************************************************/ |
static s32 XNandPsu_WriteBbt(XNandPsu *InstancePtr, XNandPsu_BbtDesc *Desc, |
XNandPsu_BbtDesc *MirrorDesc, u32 Target) |
{ |
u64 Offset; |
u32 Block = {0U}; |
u32 EndBlock = ((Target + (u32)1) * |
InstancePtr->Geometry.NumTargetBlocks) - (u32)1; |
#ifdef __ICCARM__ |
#pragma pack(push, 1) |
u8 Buf[XNANDPSU_BBT_BUF_LENGTH]= {0U}; |
u8 SpareBuf[XNANDPSU_MAX_SPARE_SIZE]= {0U}; |
#pragma pack(pop) |
#else |
u8 Buf[XNANDPSU_BBT_BUF_LENGTH] __attribute__ ((aligned(64))) = {0U}; |
u8 SpareBuf[XNANDPSU_MAX_SPARE_SIZE] __attribute__ ((aligned(64))) = {0U}; |
#endif |
u8 Mask[4] = {0x00U, 0x01U, 0x02U, 0x03U}; |
u8 Data; |
u32 BlockOffset; |
u8 BlockShift; |
s32 Status; |
u32 BlockIndex; |
u32 Index; |
u8 BlockType; |
u32 BbtLen = InstancePtr->Geometry.NumBlocks >> |
XNANDPSU_BBT_BLOCK_SHIFT; |
/* Find a valid block to write the Bad Block Table(BBT) */ |
if ((!Desc->Valid) != 0U) { |
for(Index = 0U; Index < Desc->MaxBlocks; Index++) { |
Block = (EndBlock - Index); |
BlockOffset = Block >> XNANDPSU_BBT_BLOCK_SHIFT; |
BlockShift = XNandPsu_BbtBlockShift(Block); |
BlockType = (InstancePtr->Bbt[BlockOffset] >> |
BlockShift) & XNANDPSU_BLOCK_TYPE_MASK; |
switch(BlockType) |
{ |
case XNANDPSU_BLOCK_BAD: |
case XNANDPSU_BLOCK_FACTORY_BAD: |
continue; |
default: |
/* Good Block */ |
break; |
} |
Desc->PageOffset[Target] = Block * |
InstancePtr->Geometry.PagesPerBlock; |
if (Desc->PageOffset[Target] != |
MirrorDesc->PageOffset[Target]) { |
/* Free block found */ |
Desc->Valid = 1U; |
break; |
} |
} |
/* Block not found for writing Bad Block Table(BBT) */ |
if (Index >= Desc->MaxBlocks) { |
#ifdef XNANDPSU_DEBUG |
xil_printf('%s: Blocks unavailable for writing BBTrn', |
__func__); |
#endif |
Status = XST_FAILURE; |
goto Out; |
} |
} else { |
Block = Desc->PageOffset[Target] / |
InstancePtr->Geometry.PagesPerBlock; |
} |
/* Convert the memory based BBT to flash based table */ |
(void)memset(Buf, 0xff, BbtLen); |
/* Loop through the number of blocks */ |
for(BlockOffset = 0U; BlockOffset < BbtLen; BlockOffset++) { |
Data = InstancePtr->Bbt[BlockOffset]; |
/* Calculate the bit mask for 4 blocks at a time in loop */ |
for(BlockIndex = 0U; BlockIndex < XNANDPSU_BBT_ENTRY_NUM_BLOCKS; |
BlockIndex++) { |
BlockShift = XNandPsu_BbtBlockShift(BlockIndex); |
Buf[BlockOffset] &= ~(Mask[Data & |
XNANDPSU_BLOCK_TYPE_MASK] << |
BlockShift); |
Data >>= XNANDPSU_BBT_BLOCK_SHIFT; |
} |
} |
/* Write the Bad Block Table(BBT) to flash */ |
Status = XNandPsu_EraseBlock(InstancePtr, 0U, Block); |
if (Status != XST_SUCCESS) { |
goto Out; |
} |
/* Write the BBT to page offset */ |
Offset = (u64)Desc->PageOffset[Target] * |
(u64)InstancePtr->Geometry.BytesPerPage; |
Status = XNandPsu_Write(InstancePtr, Offset, BbtLen, &Buf[0]); |
if (Status != XST_SUCCESS) { |
goto Out; |
} |
/* Write the signature and version in the spare data area */ |
(void)memset(SpareBuf, 0xff, InstancePtr->Geometry.SpareBytesPerPage); |
Status = XNandPsu_ReadSpareBytes(InstancePtr, Desc->PageOffset[Target], |
&SpareBuf[0]); |
if (Status != XST_SUCCESS) { |
goto Out; |
} |
(void)Xil_MemCpy(SpareBuf + Desc->SigOffset, &Desc->Signature[0], |
Desc->SigLength); |
(void)memcpy(SpareBuf + Desc->VerOffset, &Desc->Version[Target], 1U); |
Status = XNandPsu_WriteSpareBytes(InstancePtr, |
Desc->PageOffset[Target], &SpareBuf[0]); |
if (Status != XST_SUCCESS) { |
goto Out; |
} |
Status = XST_SUCCESS; |
Out: |
return Status; |
} |
/*****************************************************************************/ |
/** |
* This function updates the primary and mirror Bad Block Table(BBT) in the |
* flash. |
* |
* @param InstancePtr is the pointer to the XNandPsu instance. |
* @return |
* - XST_SUCCESS if successful. |
* - XST_FAILURE if fail. |
* |
******************************************************************************/ |
static s32 XNandPsu_UpdateBbt(XNandPsu *InstancePtr, u32 Target) |
{ |
s32 Status; |
u8 Version; |
/* Update the version number */ |
Version = InstancePtr->BbtDesc.Version[Target]; |
InstancePtr->BbtDesc.Version[Target] = (u8)(((u16)Version + |
(u16)1) % (u16)256U); |
Version = InstancePtr->BbtMirrorDesc.Version[Target]; |
InstancePtr->BbtMirrorDesc.Version[Target] = (u8)(((u16)Version + |
(u16)1) % (u16)256); |
/* Update the primary Bad Block Table(BBT) in flash */ |
Status = XNandPsu_WriteBbt(InstancePtr, &InstancePtr->BbtDesc, |
&InstancePtr->BbtMirrorDesc, |
Target); |
if (Status != XST_SUCCESS) { |
goto Out; |
} |
/* Update the mirrored Bad Block Table(BBT) in flash */ |
Status = XNandPsu_WriteBbt(InstancePtr, &InstancePtr->BbtMirrorDesc, |
&InstancePtr->BbtDesc, |
Target); |
if (Status != XST_SUCCESS) { |
goto Out; |
} |
Status = XST_SUCCESS; |
Out: |
return Status; |
} |
/*****************************************************************************/ |
/** |
* This function marks the block containing Bad Block Table as reserved |
* and updates the BBT. |
* |
* @param InstancePtr is the pointer to the XNandPsu instance. |
* @param Desc is the BBT descriptor pointer. |
* @return |
* - XST_SUCCESS if successful. |
* - XST_FAILURE if fail. |
* |
******************************************************************************/ |
static s32 XNandPsu_MarkBbt(XNandPsu* InstancePtr, XNandPsu_BbtDesc *Desc, |
u32 Target) |
{ |
u32 BlockIndex; |
u32 BlockOffset; |
u8 BlockShift; |
u8 OldVal; |
u8 NewVal; |
s32 Status; |
u32 UpdateBbt = 0U; |
u32 Index; |
/* Mark the last four blocks as Reserved */ |
BlockIndex = ((Target + (u32)1) * InstancePtr->Geometry.NumTargetBlocks) - |
Desc->MaxBlocks - (u32)1; |
for(Index = 0U; Index < Desc->MaxBlocks; Index++) { |
BlockOffset = BlockIndex >> XNANDPSU_BBT_BLOCK_SHIFT; |
BlockShift = XNandPsu_BbtBlockShift(BlockIndex); |
OldVal = InstancePtr->Bbt[BlockOffset]; |
NewVal = (u8) (OldVal | (XNANDPSU_BLOCK_RESERVED << |
BlockShift)); |
InstancePtr->Bbt[BlockOffset] = NewVal; |
if (OldVal != NewVal) { |
UpdateBbt = 1U; |
} |
BlockIndex++; |
} |
/* Update the BBT to flash */ |
if (UpdateBbt != 0U) { |
Status = XNandPsu_UpdateBbt(InstancePtr, Target); |
if (Status != XST_SUCCESS) { |
goto Out; |
} |
} |
Status = XST_SUCCESS; |
Out: |
return Status; |
} |
/*****************************************************************************/ |
/** |
* |
* This function checks whether a block is bad or not. |
* |
* @param InstancePtr is the pointer to the XNandPsu instance. |
* |
* @param Block is the block number. |
* |
* @return |
* - XST_SUCCESS if successful. |
* - XST_FAILURE if fail. |
* |
******************************************************************************/ |
s32 XNandPsu_IsBlockBad(XNandPsu *InstancePtr, u32 Block) |
{ |
u8 Data; |
u8 BlockShift; |
u8 BlockType; |
u32 BlockOffset; |
s32 Status; |
Xil_AssertNonvoid(InstancePtr != NULL); |
Xil_AssertNonvoid(InstancePtr->IsReady XIL_COMPONENT_IS_READY); |
Xil_AssertNonvoid(Block < InstancePtr->Geometry.NumBlocks); |
BlockOffset = Block >> XNANDPSU_BBT_BLOCK_SHIFT; |
BlockShift = XNandPsu_BbtBlockShift(Block); |
Data = InstancePtr->Bbt[BlockOffset]; /* Block information in BBT */ |
BlockType = (Data >> BlockShift) & XNANDPSU_BLOCK_TYPE_MASK; |
if ((BlockType != XNANDPSU_BLOCK_GOOD) && |
(BlockType != XNANDPSU_BLOCK_RESERVED)) { |
Status = XST_SUCCESS; |
} |
else { |
Status = XST_FAILURE; |
} |
return Status; |
} |
/*****************************************************************************/ |
/** |
* This function marks a block as bad in the RAM based Bad Block Table(BBT). It |
* also updates the Bad Block Table(BBT) in the flash. |
* |
* @param InstancePtr is the pointer to the XNandPsu instance. |
* @param Block is the block number. |
* |
* @return |
* - XST_SUCCESS if successful. |
* - XST_FAILURE if fail. |
* |
******************************************************************************/ |
s32 XNandPsu_MarkBlockBad(XNandPsu *InstancePtr, u32 Block) |
{ |
u8 Data; |
u8 BlockShift; |
u32 BlockOffset; |
u8 OldVal; |
u8 NewVal; |
s32 Status; |
u32 Target; |
Xil_AssertNonvoid(InstancePtr != NULL); |
Xil_AssertNonvoid(InstancePtr->IsReady XIL_COMPONENT_IS_READY); |
Xil_AssertNonvoid(Block < InstancePtr->Geometry.NumBlocks); |
Target = Block / InstancePtr->Geometry.NumTargetBlocks; |
BlockOffset = Block >> XNANDPSU_BBT_BLOCK_SHIFT; |
BlockShift = XNandPsu_BbtBlockShift(Block); |
Data = InstancePtr->Bbt[BlockOffset]; /* Block information in BBT */ |
/* Mark the block as bad in the RAM based Bad Block Table */ |
OldVal = Data; |
Data &= ~(XNANDPSU_BLOCK_TYPE_MASK << BlockShift); |
Data |= (XNANDPSU_BLOCK_BAD << BlockShift); |
NewVal = Data; |
InstancePtr->Bbt[BlockOffset] = Data; |
/* Update the Bad Block Table(BBT) in flash */ |
if (OldVal != NewVal) { |
Status = XNandPsu_UpdateBbt(InstancePtr, Target); |
if (Status != XST_SUCCESS) { |
goto Out; |
} |
} |
Status = XST_SUCCESS; |
Out: |
return Status; |
} |
/** @} */ |
Copy lines Copy permalink
Seagate HDD with one partition (NTFS), no O/S only data is returning the error 'Corrupt Master File Table'. I've CHKDSK /F on the drive, but no progress indicator is displayed even after 13+ hours.
Running Seatools there were 73 Bad Sectors identified and 'repaired'. I've tried a Linux Live CD but the drive cannot be mounted due to missing MFT. Ghost and Redo backup did not work either.
I tried GetDataBack, but the application scans for less than a second and only displays 7.5GB of approximate 150GB of files the 400GB drive. One odd thing I noticed with this app is if I scan FAT32 it takes 1.5 hours and discovers 80k files, but displays nothing to be recovered.
Right now I'm running HDD Regenerator in hopes to fix bad sectors.
Can anyone suggest a method for recovering the data or MFT so I can at least get a copy?
Running Seatools there were 73 Bad Sectors identified and 'repaired'. I've tried a Linux Live CD but the drive cannot be mounted due to missing MFT. Ghost and Redo backup did not work either.
I tried GetDataBack, but the application scans for less than a second and only displays 7.5GB of approximate 150GB of files the 400GB drive. One odd thing I noticed with this app is if I scan FAT32 it takes 1.5 hours and discovers 80k files, but displays nothing to be recovered.
Right now I'm running HDD Regenerator in hopes to fix bad sectors.
Can anyone suggest a method for recovering the data or MFT so I can at least get a copy?