Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenid_badblock.cpp
Go to the documentation of this file.
00001 /*++ 00002 00003 Copyright (C) 2006 VorontSOFT 00004 00005 Module Name: 00006 id_badblock.cpp 00007 00008 Abstract: 00009 This is the artificial badblock simulation part of the 00010 miniport driver for ATA/ATAPI IDE controllers with Busmaster DMA support 00011 00012 Author: 00013 Nikolai Vorontsov (NickViz) 00014 00015 Environment: 00016 kernel mode only 00017 00018 Notes: 00019 00020 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 00021 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 00022 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 00023 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 00024 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 00025 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 00026 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 00027 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00028 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 00029 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00030 00031 Revision History: 00032 2006/08/03 Initial implementation. 00033 2006/08/06 Added registry work. 00034 2007/03/27 Added device serial to registry value name instead of LUN. 00035 00036 --*/ 00037 00038 #include "stdafx.h" 00039 00040 //#define MAX_BADBLOCKS_ITEMS 512 00041 00042 00043 00044 //SBadBlockRange arrBadBlocks[MAX_BADBLOCKS_ITEMS]; 00045 //ULONG nBadBlocks = 0; 00046 00047 LIST_ENTRY BBList; 00048 BOOLEAN BBListInited = FALSE; 00049 00050 // RtlQueryRegistryValues callback function 00051 static NTSTATUS __stdcall 00052 BadBlockQueryRoutine( 00053 IN PWSTR ValueName, 00054 IN ULONG ValueType, 00055 IN PVOID ValueData, 00056 IN ULONG ValueLength, 00057 IN PVOID Context, 00058 IN PVOID EntryContext 00059 ) 00060 { 00061 PSBadBlockListItem cur; 00062 PLIST_ENTRY link; 00063 ULONG i; 00064 // The ValueType should be REG_SZ 00065 // The ValueData is UNICODE string of the following format: 00066 // "badblocks_start_from_lba badblocks_end_at_lba" 00067 00068 KdPrint(( "BadBlockQueryRoutine: S/N:%S\n type %#x, len %#x\n", ValueName, ValueType, ValueLength)); 00069 00070 if(!BBListInited) 00071 return STATUS_SUCCESS; 00072 00073 if((ValueType == REG_BINARY) && // STRING 00074 ValueLength && // At least "0 0 0" 00075 !(ValueLength % sizeof(SBadBlockRange))) // There is free space for the record 00076 { 00077 cur = NULL; 00078 link = BBList.Flink; 00079 while(link != &BBList) { 00080 cur = CONTAINING_RECORD( link, SBadBlockListItem, List); 00081 link = link->Flink; 00082 if(!wcscmp(cur->SerNumStr, ValueName)) { 00083 KdPrint(( "already loaded\n")); 00084 if(cur->LunExt) { 00085 cur->LunExt->nBadBlocks = 0; 00086 cur->LunExt->arrBadBlocks = NULL; 00087 cur->LunExt->bbListDescr = NULL; 00088 cur->LunExt = NULL; 00089 } 00090 break; 00091 } 00092 } 00093 00094 if(!cur) { 00095 cur = (PSBadBlockListItem)ExAllocatePool(NonPagedPool, sizeof(SBadBlockListItem)); 00096 if(!cur) 00097 return STATUS_SUCCESS; 00098 } else { 00099 if(cur->arrBadBlocks) { 00100 ExFreePool(cur->arrBadBlocks); 00101 cur->arrBadBlocks = NULL; 00102 } 00103 } 00104 cur->arrBadBlocks = (SBadBlockRange*)ExAllocatePool(NonPagedPool, ValueLength); 00105 if(!cur->arrBadBlocks) { 00106 ExFreePool(cur); 00107 return STATUS_SUCCESS; 00108 } 00109 RtlCopyMemory(cur->arrBadBlocks, ValueData, ValueLength); 00110 wcsncpy(cur->SerNumStr, ValueName, 127); 00111 cur->SerNumStr[127] = 0; 00112 cur->nBadBlocks = ValueLength/sizeof(SBadBlockRange); 00113 cur->LunExt = NULL; 00114 InitializeListHead(&cur->List); 00115 InsertTailList(&BBList, &(cur->List)); 00116 for(i=0; i<cur->nBadBlocks; i++) { 00117 KdPrint(( "BB: %I64x - %I64x\n", cur->arrBadBlocks[i].m_lbaStart, cur->arrBadBlocks[i].m_lbaEnd-1)); 00118 } 00119 } 00120 return STATUS_SUCCESS; 00121 } // end BadBlockQueryRoutine() 00122 00123 00124 void 00125 NTAPI 00126 InitBadBlocks( 00127 IN PHW_LU_EXTENSION LunExt 00128 ) 00129 { 00130 RTL_QUERY_REGISTRY_TABLE QueryTable[2]; // Main record and zero filled end of array marker 00131 WCHAR DevSerial[128]; 00132 #ifdef _DEBUG 00133 UCHAR cDevSerial[128]; 00134 ULONG i; 00135 #endif 00136 ULONG Length; 00137 PLIST_ENTRY link; 00138 PSBadBlockListItem cur; 00139 // Read from the registry necessary badblock pairs and fill in arrBadBlocks array 00140 // HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\UniATA\Parameters\BadBlocks 00141 00142 if(!LunExt) { 00143 // init 00144 KdPrint(( "InitBadBlocks general\n")); 00145 if(!BBListInited) { 00146 InitializeListHead(&BBList); 00147 BBListInited = TRUE; 00148 } 00149 00150 QueryTable[0].QueryRoutine = BadBlockQueryRoutine; 00151 QueryTable[0].Flags = RTL_QUERY_REGISTRY_REQUIRED; 00152 QueryTable[0].Name = NULL; // If Name is NULL, the QueryRoutine function 00153 // specified for this table entry is called 00154 // for all values associated with the current 00155 // registry key. 00156 QueryTable[0].EntryContext = NULL; 00157 QueryTable[0].DefaultType = REG_NONE; 00158 QueryTable[0].DefaultData = 0; 00159 QueryTable[0].DefaultLength = 0; 00160 00161 RtlZeroMemory(QueryTable + 1, sizeof(RTL_QUERY_REGISTRY_TABLE)); // EOF 00162 00163 NTSTATUS status = RtlQueryRegistryValues(RTL_REGISTRY_SERVICES, 00164 L"UniATA\\Parameters\\BadBlocks", 00165 QueryTable, 0, 0); 00166 00167 #ifdef _DEBUG 00168 KdPrint(( "InitBadBlocks returned: %#x\n", status)); 00169 #else 00170 UNREFERENCED_PARAMETER(status); 00171 #endif 00172 } else { 00173 00174 KdPrint(( "InitBadBlocks local\n")); 00175 Length = EncodeVendorStr(DevSerial, (PUCHAR)LunExt->IdentifyData.ModelNumber, sizeof(LunExt->IdentifyData.ModelNumber)); 00176 DevSerial[Length] = '-'; 00177 Length++; 00178 Length += EncodeVendorStr(DevSerial+Length, LunExt->IdentifyData.SerialNumber, sizeof(LunExt->IdentifyData.SerialNumber)); 00179 00180 #ifdef _DEBUG 00181 KdPrint(( "LunExt %#x\n", LunExt)); 00182 for(i=0; i<Length; i++) { 00183 cDevSerial[i] = (UCHAR)(DevSerial[i]); 00184 } 00185 KdPrint(( "S/N:%s\n", cDevSerial)); 00186 #endif 00187 00188 LunExt->nBadBlocks = 0; 00189 LunExt->arrBadBlocks = NULL; 00190 00191 link = BBList.Flink; 00192 while(link != &BBList) { 00193 cur = CONTAINING_RECORD( link, SBadBlockListItem, List); 00194 link = link->Flink; 00195 if(cur->LunExt == LunExt) { 00196 KdPrint(( " deassociate BB list (by LunExt)\n")); 00197 cur->LunExt->nBadBlocks = 0; 00198 cur->LunExt->arrBadBlocks = NULL; 00199 cur->LunExt->bbListDescr = NULL; 00200 cur->LunExt = NULL; 00201 } else 00202 if(!wcscmp(cur->SerNumStr, DevSerial)) { 00203 KdPrint(( " deassociate BB list (by Serial)\n")); 00204 if(cur->LunExt) { 00205 cur->LunExt->nBadBlocks = 0; 00206 cur->LunExt->arrBadBlocks = NULL; 00207 cur->LunExt->bbListDescr = NULL; 00208 cur->LunExt = NULL; 00209 } 00210 } 00211 } 00212 00213 if(!(LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE)) { 00214 00215 link = BBList.Flink; 00216 while(link != &BBList) { 00217 cur = CONTAINING_RECORD( link, SBadBlockListItem, List); 00218 link = link->Flink; 00219 if(!wcscmp(cur->SerNumStr, DevSerial)) { 00220 KdPrint(( "found BB:List\n")); 00221 cur->LunExt = LunExt; 00222 LunExt->arrBadBlocks = cur->arrBadBlocks; 00223 LunExt->nBadBlocks = cur->nBadBlocks; 00224 LunExt->bbListDescr = cur; 00225 return; 00226 } 00227 } 00228 } 00229 } 00230 return; 00231 } // end InitBadBlocks() 00232 00233 00234 void 00235 NTAPI 00236 ForgetBadBlocks( 00237 IN PHW_LU_EXTENSION LunExt 00238 ) 00239 { 00240 if(LunExt->bbListDescr) { 00241 LunExt->bbListDescr->LunExt = NULL; 00242 LunExt->nBadBlocks = 0; 00243 LunExt->arrBadBlocks = NULL; 00244 LunExt->bbListDescr = NULL; 00245 } 00246 } // end ForgetBadBlocks() 00247 00248 bool 00249 NTAPI 00250 CheckIfBadBlock( 00251 IN PHW_LU_EXTENSION LunExt, 00252 // IN UCHAR command, 00253 IN ULONGLONG lba, 00254 IN ULONG count 00255 ) 00256 { 00257 if (LunExt->nBadBlocks == 0) 00258 return false; 00259 /* 00260 // this is checked by caller 00261 if(!(AtaCommandFlags[command] & ATA_CMD_FLAG_LBAsupp)) { 00262 return false; 00263 */ 00264 ULONG nBadBlocks = LunExt->nBadBlocks; 00265 SBadBlockRange* arrBadBlocks = LunExt->arrBadBlocks; 00266 00267 // back transform for possibly CHS'ed LBA 00268 lba = UniAtaCalculateLBARegsBack(LunExt, lba); 00269 00270 for (ULONG i = 0; i < nBadBlocks; i++) 00271 { 00272 if (lba + count > arrBadBlocks->m_lbaStart && 00273 lba < arrBadBlocks->m_lbaEnd) { 00274 KdPrint(( "listed BB @ %I64x\n", lba)); 00275 return true; 00276 } 00277 arrBadBlocks++; 00278 } 00279 00280 return false; 00281 00282 } // end CheckIfBadBlock() Generated on Sat May 26 2012 04:26:56 for ReactOS by
1.7.6.1
|