ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

utils.c
Go to the documentation of this file.
00001 /*++
00002 
00003 Copyright (C) Microsoft Corporation, 1991 - 1999
00004 
00005 Module Name:
00006 
00007     utils.c
00008 
00009 Abstract:
00010 
00011     SCSI class driver routines
00012 
00013 Environment:
00014 
00015     kernel mode only
00016 
00017 Notes:
00018 
00019 
00020 Revision History:
00021 
00022 --*/
00023 
00024 #include "classp.h"
00025 #include "debug.h"
00026 
00027 
00028 
00029 #ifdef ALLOC_PRAGMA
00030     #pragma alloc_text(PAGE, ClassGetDeviceParameter)
00031     #pragma alloc_text(PAGE, ClassScanForSpecial)
00032     #pragma alloc_text(PAGE, ClassSetDeviceParameter)
00033 #endif
00034 
00035 
00036 
00037 // custom string match -- careful!
00038 BOOLEAN ClasspMyStringMatches(IN PCHAR StringToMatch OPTIONAL, IN PCHAR TargetString)
00039 {
00040     ULONG length;  // strlen returns an int, not size_t (!)
00041     PAGED_CODE();
00042     ASSERT(TargetString);
00043     // if no match requested, return TRUE
00044     if (StringToMatch == NULL) {
00045         return TRUE;
00046     }
00047     // cache the string length for efficiency
00048     length = strlen(StringToMatch);
00049     // ZERO-length strings may only match zero-length strings
00050     if (length == 0) {
00051         return (strlen(TargetString) == 0);
00052     }
00053     // strncmp returns zero if the strings match
00054     return (strncmp(StringToMatch, TargetString, length) == 0);
00055 }
00056 
00057 
00058 VOID ClassGetDeviceParameter(
00059     IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
00060     IN PWSTR SubkeyName OPTIONAL,
00061     IN PWSTR ParameterName,
00062     IN OUT PULONG ParameterValue  // also default value
00063     )
00064 {
00065     NTSTATUS                 status;
00066     RTL_QUERY_REGISTRY_TABLE queryTable[2];
00067     HANDLE                   deviceParameterHandle;
00068     HANDLE                   deviceSubkeyHandle;
00069     ULONG                    defaultParameterValue;
00070 
00071     PAGED_CODE();
00072 
00073     //
00074     // open the given parameter
00075     //
00076 
00077     status = IoOpenDeviceRegistryKey(FdoExtension->LowerPdo,
00078                                      PLUGPLAY_REGKEY_DEVICE,
00079                                      KEY_READ,
00080                                      &deviceParameterHandle);
00081 
00082     if (NT_SUCCESS(status) && (SubkeyName != NULL)) {
00083 
00084         UNICODE_STRING subkeyName;
00085         OBJECT_ATTRIBUTES objectAttributes;
00086 
00087         RtlInitUnicodeString(&subkeyName, SubkeyName);
00088         InitializeObjectAttributes(&objectAttributes,
00089                                    &subkeyName,
00090                                    OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
00091                                    deviceParameterHandle,
00092                                    NULL);
00093 
00094         status = ZwOpenKey(&deviceSubkeyHandle,
00095                            KEY_READ,
00096                            &objectAttributes);
00097         if (!NT_SUCCESS(status)) {
00098             ZwClose(deviceParameterHandle);
00099         }
00100 
00101     }
00102 
00103     if (NT_SUCCESS(status)) {
00104 
00105         RtlZeroMemory(queryTable, sizeof(queryTable));
00106 
00107         defaultParameterValue = *ParameterValue;
00108 
00109         queryTable->Flags         = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED;
00110         queryTable->Name          = ParameterName;
00111         queryTable->EntryContext  = ParameterValue;
00112         queryTable->DefaultType   = REG_DWORD;
00113         queryTable->DefaultData   = NULL;
00114         queryTable->DefaultLength = 0;
00115 
00116         status = RtlQueryRegistryValues(RTL_REGISTRY_HANDLE,
00117                                         (PWSTR)(SubkeyName ?
00118                                                 deviceSubkeyHandle :
00119                                                 deviceParameterHandle),
00120                                         queryTable,
00121                                         NULL,
00122                                         NULL);
00123         if (!NT_SUCCESS(status)) {
00124             *ParameterValue = defaultParameterValue; // use default value
00125         }
00126 
00127         //
00128         // close what we open
00129         //
00130 
00131         if (SubkeyName) {
00132             ZwClose(deviceSubkeyHandle);
00133         }
00134 
00135         ZwClose(deviceParameterHandle);
00136     }
00137 
00138     return;
00139 
00140 } // end ClassGetDeviceParameter()
00141 
00142 
00143 NTSTATUS ClassSetDeviceParameter(
00144     IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
00145     IN PWSTR SubkeyName OPTIONAL,
00146     IN PWSTR ParameterName,
00147     IN ULONG ParameterValue)
00148 {
00149     NTSTATUS                 status;
00150     HANDLE                   deviceParameterHandle;
00151     HANDLE                   deviceSubkeyHandle;
00152 
00153     PAGED_CODE();
00154 
00155     //
00156     // open the given parameter
00157     //
00158 
00159     status = IoOpenDeviceRegistryKey(FdoExtension->LowerPdo,
00160                                      PLUGPLAY_REGKEY_DEVICE,
00161                                      KEY_READ | KEY_WRITE,
00162                                      &deviceParameterHandle);
00163 
00164     if (NT_SUCCESS(status) && (SubkeyName != NULL)) {
00165 
00166         UNICODE_STRING subkeyName;
00167         OBJECT_ATTRIBUTES objectAttributes;
00168 
00169         RtlInitUnicodeString(&subkeyName, SubkeyName);
00170         InitializeObjectAttributes(&objectAttributes,
00171                                    &subkeyName,
00172                                    OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
00173                                    deviceParameterHandle,
00174                                    NULL);
00175 
00176         status = ZwCreateKey(&deviceSubkeyHandle,
00177                              KEY_READ | KEY_WRITE,
00178                              &objectAttributes,
00179                              0, NULL, 0, NULL);
00180         if (!NT_SUCCESS(status)) {
00181             ZwClose(deviceParameterHandle);
00182         }
00183 
00184     }
00185 
00186     if (NT_SUCCESS(status)) {
00187 
00188         status = RtlWriteRegistryValue(
00189             RTL_REGISTRY_HANDLE,
00190             (PWSTR) (SubkeyName ?
00191                      deviceSubkeyHandle :
00192                      deviceParameterHandle),
00193             ParameterName,
00194             REG_DWORD,
00195             &ParameterValue,
00196             sizeof(ULONG));
00197 
00198         //
00199         // close what we open
00200         //
00201 
00202         if (SubkeyName) {
00203             ZwClose(deviceSubkeyHandle);
00204         }
00205 
00206         ZwClose(deviceParameterHandle);
00207     }
00208 
00209     return status;
00210 
00211 } // end ClassSetDeviceParameter()
00212 
00213 
00214 /*
00215  *  ClassScanForSpecial
00216  *
00217  *      This routine was written to simplify scanning for special
00218  *      hardware based upon id strings.  it does not check the registry.
00219  */
00220 
00221 VOID ClassScanForSpecial(
00222     IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
00223     IN CLASSPNP_SCAN_FOR_SPECIAL_INFO DeviceList[],
00224     IN PCLASS_SCAN_FOR_SPECIAL_HANDLER Function)
00225 {
00226     PSTORAGE_DEVICE_DESCRIPTOR deviceDescriptor;
00227     PUCHAR vendorId;
00228     PUCHAR productId;
00229     PUCHAR productRevision;
00230     UCHAR nullString[] = "";
00231     ULONG j;
00232 
00233     PAGED_CODE();
00234     ASSERT(DeviceList);
00235     ASSERT(Function);
00236 
00237     deviceDescriptor = FdoExtension->DeviceDescriptor;
00238 
00239     if (DeviceList == NULL) {
00240         return;
00241     }
00242     if (Function == NULL) {
00243         return;
00244     }
00245 
00246     //
00247     // SCSI sets offsets to -1, ATAPI sets to 0.  check for both.
00248     //
00249 
00250     if (deviceDescriptor->VendorIdOffset != 0 &&
00251         deviceDescriptor->VendorIdOffset != -1) {
00252         vendorId = ((PUCHAR)deviceDescriptor);
00253         vendorId += deviceDescriptor->VendorIdOffset;
00254     } else {
00255         vendorId = nullString;
00256     }
00257     if (deviceDescriptor->ProductIdOffset != 0 &&
00258         deviceDescriptor->ProductIdOffset != -1) {
00259         productId = ((PUCHAR)deviceDescriptor);
00260         productId += deviceDescriptor->ProductIdOffset;
00261     } else {
00262         productId = nullString;
00263     }
00264     if (deviceDescriptor->VendorIdOffset != 0 &&
00265         deviceDescriptor->VendorIdOffset != -1) {
00266         productRevision = ((PUCHAR)deviceDescriptor);
00267         productRevision += deviceDescriptor->ProductRevisionOffset;
00268     } else {
00269         productRevision = nullString;
00270     }
00271 
00272     //
00273     // loop while the device list is valid (not null-filled)
00274     //
00275 
00276     for (;(DeviceList->VendorId        != NULL ||
00277            DeviceList->ProductId       != NULL ||
00278            DeviceList->ProductRevision != NULL);DeviceList++) {
00279 
00280         if (ClasspMyStringMatches(DeviceList->VendorId,        vendorId) &&
00281             ClasspMyStringMatches(DeviceList->ProductId,       productId) &&
00282             ClasspMyStringMatches(DeviceList->ProductRevision, productRevision)
00283             ) {
00284 
00285             DebugPrint((1, "ClasspScanForSpecialByInquiry: Found matching "
00286                         "controller Ven: %s Prod: %s Rev: %s\n",
00287                         vendorId, productId, productRevision));
00288 
00289             //
00290             // pass the context to the call back routine and exit
00291             //
00292 
00293             (Function)(FdoExtension, DeviceList->Data);
00294 
00295             //
00296             // for CHK builds, try to prevent wierd stacks by having a debug
00297             // print here. it's a hack, but i know of no other way to prevent
00298             // the stack from being wrong.
00299             //
00300 
00301             DebugPrint((16, "ClasspScanForSpecialByInquiry: "
00302                         "completed callback\n"));
00303             return;
00304 
00305         } // else the strings did not match
00306 
00307     } // none of the devices matched.
00308 
00309     DebugPrint((1, "ClasspScanForSpecialByInquiry: no match found for %p\n",
00310                 FdoExtension->DeviceObject));
00311     return;
00312 
00313 } // end ClasspScanForSpecialByInquiry()
00314 
00315 
00316 //
00317 // In order to provide better performance without the need to reboot,
00318 // we need to implement a self-adjusting method to set and clear the
00319 // srb flags based upon current performance.
00320 //
00321 // whenever there is an error, immediately grab the spin lock.  the
00322 // MP perf hit here is acceptable, since we're in an error path.  this
00323 // is also neccessary because we are guaranteed to be modifying the
00324 // SRB flags here, setting SuccessfulIO to zero, and incrementing the
00325 // actual error count (which is always done within this spinlock).
00326 //
00327 // whenever there is no error, increment a counter.  if there have been
00328 // errors on the device, and we've enabled dynamic perf, *and* we've
00329 // just crossed the perf threshhold, then grab the spin lock and
00330 // double check that the threshhold has, indeed been hit(*). then
00331 // decrement the error count, and if it's dropped sufficiently, undo
00332 // some of the safety changes made in the SRB flags due to the errors.
00333 //
00334 // * this works in all cases.  even if lots of ios occur after the
00335 //   previous guy went in and cleared the successfulio counter, that
00336 //   just means that we've hit the threshhold again, and so it's proper
00337 //   to run the inner loop again.
00338 //
00339 
00340 VOID
00341 ClasspPerfIncrementErrorCount(
00342     IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
00343     )
00344 {
00345     PCLASS_PRIVATE_FDO_DATA fdoData = FdoExtension->PrivateFdoData;
00346     KIRQL oldIrql;
00347     ULONG errors;
00348 
00349     KeAcquireSpinLock(&fdoData->SpinLock, &oldIrql);
00350 
00351     fdoData->Perf.SuccessfulIO = 0; // implicit interlock
00352     errors = InterlockedIncrement(&FdoExtension->ErrorCount);
00353 
00354     if (errors >= CLASS_ERROR_LEVEL_1) {
00355 
00356         //
00357         // If the error count has exceeded the error limit, then disable
00358         // any tagged queuing, multiple requests per lu queueing
00359         // and sychronous data transfers.
00360         //
00361         // Clearing the no queue freeze flag prevents the port driver
00362         // from sending multiple requests per logical unit.
00363         //
00364 
00365         CLEAR_FLAG(FdoExtension->SrbFlags, SRB_FLAGS_NO_QUEUE_FREEZE);
00366         CLEAR_FLAG(FdoExtension->SrbFlags, SRB_FLAGS_QUEUE_ACTION_ENABLE);
00367 
00368         SET_FLAG(FdoExtension->SrbFlags, SRB_FLAGS_DISABLE_SYNCH_TRANSFER);
00369 
00370         DebugPrint((ClassDebugError, "ClasspPerfIncrementErrorCount: "
00371                     "Too many errors; disabling tagged queuing and "
00372                     "synchronous data tranfers.\n"));
00373 
00374     }
00375 
00376     if (errors >= CLASS_ERROR_LEVEL_2) {
00377 
00378         //
00379         // If a second threshold is reached, disable disconnects.
00380         //
00381 
00382         SET_FLAG(FdoExtension->SrbFlags, SRB_FLAGS_DISABLE_DISCONNECT);
00383         DebugPrint((ClassDebugError, "ClasspPerfIncrementErrorCount: "
00384                     "Too many errors; disabling disconnects.\n"));
00385     }
00386 
00387     KeReleaseSpinLock(&fdoData->SpinLock, oldIrql);
00388     return;
00389 }
00390 
00391 VOID
00392 ClasspPerfIncrementSuccessfulIo(
00393     IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
00394     )
00395 {
00396     PCLASS_PRIVATE_FDO_DATA fdoData = FdoExtension->PrivateFdoData;
00397     KIRQL oldIrql;
00398     ULONG errors;
00399     ULONG succeeded = 0;
00400 
00401     //
00402     // don't take a hit from the interlocked op unless we're in
00403     // a degraded state and we've got a threshold to hit.
00404     //
00405 
00406     if (FdoExtension->ErrorCount == 0) {
00407         return;
00408     }
00409 
00410     if (fdoData->Perf.ReEnableThreshhold == 0) {
00411         return;
00412     }
00413 
00414     succeeded = InterlockedIncrement(&fdoData->Perf.SuccessfulIO);
00415     if (succeeded < fdoData->Perf.ReEnableThreshhold) {
00416         return;
00417     }
00418 
00419     //
00420     // if we hit the threshold, grab the spinlock and verify we've
00421     // actually done so.  this allows us to ignore the spinlock 99%
00422     // of the time.
00423     //
00424 
00425     KeAcquireSpinLock(&fdoData->SpinLock, &oldIrql);
00426 
00427     //
00428     // re-read the value, so we don't run this multiple times
00429     // for a single threshhold being hit.  this keeps errorcount
00430     // somewhat useful.
00431     //
00432 
00433     succeeded = fdoData->Perf.SuccessfulIO;
00434 
00435     if ((FdoExtension->ErrorCount != 0) &&
00436         (fdoData->Perf.ReEnableThreshhold <= succeeded)
00437         ) {
00438 
00439         fdoData->Perf.SuccessfulIO = 0; // implicit interlock
00440 
00441         ASSERT(FdoExtension->ErrorCount > 0);
00442         errors = InterlockedDecrement(&FdoExtension->ErrorCount);
00443 
00444         //
00445         // note: do in reverse order of the sets "just in case"
00446         //
00447 
00448         if (errors < CLASS_ERROR_LEVEL_2) {
00449             if (errors == CLASS_ERROR_LEVEL_2 - 1) {
00450                 DebugPrint((ClassDebugError, "ClasspPerfIncrementSuccessfulIo: "
00451                             "Error level 2 no longer required.\n"));
00452             }
00453             if (!TEST_FLAG(fdoData->Perf.OriginalSrbFlags,
00454                            SRB_FLAGS_DISABLE_DISCONNECT)) {
00455                 CLEAR_FLAG(FdoExtension->SrbFlags,
00456                            SRB_FLAGS_DISABLE_DISCONNECT);
00457             }
00458         }
00459 
00460         if (errors < CLASS_ERROR_LEVEL_1) {
00461             if (errors == CLASS_ERROR_LEVEL_1 - 1) {
00462                 DebugPrint((ClassDebugError, "ClasspPerfIncrementSuccessfulIo: "
00463                             "Error level 1 no longer required.\n"));
00464             }
00465             if (!TEST_FLAG(fdoData->Perf.OriginalSrbFlags,
00466                            SRB_FLAGS_DISABLE_SYNCH_TRANSFER)) {
00467                 CLEAR_FLAG(FdoExtension->SrbFlags,
00468                            SRB_FLAGS_DISABLE_SYNCH_TRANSFER);
00469             }
00470             if (TEST_FLAG(fdoData->Perf.OriginalSrbFlags,
00471                           SRB_FLAGS_QUEUE_ACTION_ENABLE)) {
00472                 SET_FLAG(FdoExtension->SrbFlags,
00473                          SRB_FLAGS_QUEUE_ACTION_ENABLE);
00474             }
00475             if (TEST_FLAG(fdoData->Perf.OriginalSrbFlags,
00476                           SRB_FLAGS_NO_QUEUE_FREEZE)) {
00477                 SET_FLAG(FdoExtension->SrbFlags,
00478                          SRB_FLAGS_NO_QUEUE_FREEZE);
00479             }
00480         }
00481     } // end of threshhold definitely being hit for first time
00482 
00483     KeReleaseSpinLock(&fdoData->SpinLock, oldIrql);
00484     return;
00485 }
00486 
00487 
00488 PMDL BuildDeviceInputMdl(PVOID Buffer, ULONG BufferLen)
00489 {
00490     PMDL mdl;
00491 
00492     mdl = IoAllocateMdl(Buffer, BufferLen, FALSE, FALSE, NULL);
00493     if (mdl){
00494         _SEH2_TRY {
00495             /*
00496              *  We are reading from the device.
00497              *  Therefore, the device is WRITING to the locked memory.
00498              *  So we request IoWriteAccess.
00499              */
00500             MmProbeAndLockPages(mdl, KernelMode, IoWriteAccess);
00501 
00502         } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) {
00503             NTSTATUS status = _SEH2_GetExceptionCode();
00504 
00505             DBGWARN(("BuildReadMdl: MmProbeAndLockPages failed with %xh.", status));
00506             IoFreeMdl(mdl);
00507             mdl = NULL;
00508         } _SEH2_END;
00509     }
00510     else {
00511         DBGWARN(("BuildReadMdl: IoAllocateMdl failed"));
00512     }
00513 
00514     return mdl;
00515 }
00516 
00517 
00518 VOID FreeDeviceInputMdl(PMDL Mdl)
00519 {
00520     MmUnlockPages(Mdl);
00521     IoFreeMdl(Mdl);
00522 }
00523 
00524 
00525 #if 0
00526     VOID
00527     ClasspPerfResetCounters(
00528         IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
00529         )
00530     {
00531         PCLASS_PRIVATE_FDO_DATA fdoData = FdoExtension->PrivateFdoData;
00532         KIRQL oldIrql;
00533 
00534         KeAcquireSpinLock(&fdoData->SpinLock, &oldIrql);
00535         DebugPrint((ClassDebugError, "ClasspPerfResetCounters: "
00536                     "Resetting all perf counters.\n"));
00537         fdoData->Perf.SuccessfulIO = 0;
00538         FdoExtension->ErrorCount = 0;
00539 
00540         if (!TEST_FLAG(fdoData->Perf.OriginalSrbFlags,
00541                        SRB_FLAGS_DISABLE_DISCONNECT)) {
00542             CLEAR_FLAG(FdoExtension->SrbFlags,
00543                        SRB_FLAGS_DISABLE_DISCONNECT);
00544         }
00545         if (!TEST_FLAG(fdoData->Perf.OriginalSrbFlags,
00546                        SRB_FLAGS_DISABLE_SYNCH_TRANSFER)) {
00547             CLEAR_FLAG(FdoExtension->SrbFlags,
00548                        SRB_FLAGS_DISABLE_SYNCH_TRANSFER);
00549         }
00550         if (TEST_FLAG(fdoData->Perf.OriginalSrbFlags,
00551                       SRB_FLAGS_QUEUE_ACTION_ENABLE)) {
00552             SET_FLAG(FdoExtension->SrbFlags,
00553                      SRB_FLAGS_QUEUE_ACTION_ENABLE);
00554         }
00555         if (TEST_FLAG(fdoData->Perf.OriginalSrbFlags,
00556                       SRB_FLAGS_NO_QUEUE_FREEZE)) {
00557             SET_FLAG(FdoExtension->SrbFlags,
00558                      SRB_FLAGS_NO_QUEUE_FREEZE);
00559         }
00560         KeReleaseSpinLock(&fdoData->SpinLock, oldIrql);
00561         return;
00562     }
00563 #endif
00564 
00565 

Generated on Sun May 27 2012 04:22:17 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.