Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenmmc.c
Go to the documentation of this file.
00001 /*-- 00002 00003 Copyright (C) Microsoft Corporation, 2000 00004 00005 Module Name: 00006 00007 mmc.c 00008 00009 Abstract: 00010 00011 This file is used to extend cdrom.sys to detect and use mmc-compatible 00012 drives' capabilities more wisely. 00013 00014 Environment: 00015 00016 kernel mode only 00017 00018 Notes: 00019 00020 SCSI Tape, CDRom and Disk class drivers share common routines 00021 that can be found in the CLASS directory (..\ntos\dd\class). 00022 00023 Revision History: 00024 00025 --*/ 00026 00027 #include "ntddk.h" 00028 #include "classpnp.h" 00029 #include "cdrom.h" 00030 00031 00032 00033 NTSTATUS 00034 CdRomGetConfiguration( 00035 IN PDEVICE_OBJECT Fdo, 00036 OUT PGET_CONFIGURATION_HEADER *Buffer, 00037 OUT PULONG BytesReturned, 00038 IN FEATURE_NUMBER StartingFeature, 00039 IN ULONG RequestedType 00040 ); 00041 VOID 00042 CdRompPrintAllFeaturePages( 00043 IN PGET_CONFIGURATION_HEADER Buffer, 00044 IN ULONG Usable 00045 ); 00046 NTSTATUS 00047 CdRomUpdateMmcDriveCapabilitiesCompletion( 00048 IN PDEVICE_OBJECT Unused, 00049 IN PIRP Irp, 00050 IN PDEVICE_OBJECT Fdo 00051 ); 00052 VOID 00053 CdRomPrepareUpdateCapabilitiesIrp( 00054 PDEVICE_OBJECT Fdo 00055 ); 00056 00057 /*++ 00058 00059 NOT DOCUMENTED YET - may be called at up to DISPATCH_LEVEL 00060 if memory is non-paged 00061 PRESUMES ALL DATA IS ACCESSIBLE based on FeatureBuffer 00062 00063 --*/ 00064 VOID 00065 CdRomFindProfileInProfiles( 00066 IN PFEATURE_DATA_PROFILE_LIST ProfileHeader, 00067 IN FEATURE_PROFILE_TYPE ProfileToFind, 00068 OUT PBOOLEAN Found 00069 ) 00070 { 00071 PFEATURE_DATA_PROFILE_LIST_EX profile; 00072 ULONG numberOfProfiles; 00073 ULONG i; 00074 00075 ASSERT((ProfileHeader->Header.AdditionalLength % 4) == 0); 00076 00077 *Found = FALSE; 00078 00079 numberOfProfiles = ProfileHeader->Header.AdditionalLength / 4; 00080 profile = ProfileHeader->Profiles; // zero-sized array 00081 00082 for (i = 0; i < numberOfProfiles; i++) { 00083 00084 FEATURE_PROFILE_TYPE currentProfile; 00085 00086 currentProfile = 00087 (profile->ProfileNumber[0] << 8) | 00088 (profile->ProfileNumber[1] & 0xff); 00089 00090 if (currentProfile == ProfileToFind) { 00091 00092 *Found = TRUE; 00093 00094 } 00095 00096 profile++; 00097 } 00098 return; 00099 00100 } 00101 00102 00103 /*++ 00104 00105 NOT DOCUMENTED YET - may be called at up to DISPATCH_LEVEL 00106 if memory is non-paged 00107 00108 --*/ 00109 PVOID 00110 CdRomFindFeaturePage( 00111 IN PGET_CONFIGURATION_HEADER FeatureBuffer, 00112 IN ULONG Length, 00113 IN FEATURE_NUMBER Feature 00114 ) 00115 { 00116 PUCHAR buffer; 00117 PUCHAR limit; 00118 00119 if (Length < sizeof(GET_CONFIGURATION_HEADER) + sizeof(FEATURE_HEADER)) { 00120 return NULL; 00121 } 00122 00123 // 00124 // set limit to point to first illegal address 00125 // 00126 00127 limit = (PUCHAR)FeatureBuffer; 00128 limit += Length; 00129 00130 // 00131 // set buffer to point to first page 00132 // 00133 00134 buffer = FeatureBuffer->Data; 00135 00136 // 00137 // loop through each page until we find the requested one, or 00138 // until it's not safe to access the entire feature header 00139 // (if equal, have exactly enough for the feature header) 00140 // 00141 while (buffer + sizeof(FEATURE_HEADER) <= limit) { 00142 00143 PFEATURE_HEADER header = (PFEATURE_HEADER)buffer; 00144 FEATURE_NUMBER thisFeature; 00145 00146 thisFeature = 00147 (header->FeatureCode[0] << 8) | 00148 (header->FeatureCode[1]); 00149 00150 if (thisFeature == Feature) { 00151 00152 PUCHAR temp; 00153 00154 // 00155 // if don't have enough memory to safely access all the feature 00156 // information, return NULL 00157 // 00158 temp = buffer; 00159 temp += sizeof(FEATURE_HEADER); 00160 temp += header->AdditionalLength; 00161 00162 if (temp > limit) { 00163 00164 // 00165 // this means the transfer was cut-off, an insufficiently 00166 // small buffer was given, or other arbitrary error. since 00167 // it's not safe to view the amount of data (even though 00168 // the header is safe) in this feature, pretend it wasn't 00169 // transferred at all... 00170 // 00171 00172 KdPrintEx((DPFLTR_CDROM_ID, CdromDebugFeatures, 00173 "Feature %x exists, but not safe to access all its " 00174 "data. returning NULL\n", Feature)); 00175 return NULL; 00176 } else { 00177 return buffer; 00178 } 00179 } 00180 00181 if (header->AdditionalLength % 4) { 00182 ASSERT(!"Feature page AdditionalLength field must be integral multiple of 4!\n"); 00183 return NULL; 00184 } 00185 00186 buffer += sizeof(FEATURE_HEADER); 00187 buffer += header->AdditionalLength; 00188 00189 } 00190 return NULL; 00191 } 00192 00193 /*++ 00194 00195 Private so we can later expose to someone wanting to use a preallocated buffer 00196 00197 --*/ 00198 NTSTATUS 00199 CdRompGetConfiguration( 00200 IN PDEVICE_OBJECT Fdo, 00201 IN PGET_CONFIGURATION_HEADER Buffer, 00202 IN ULONG BufferSize, 00203 OUT PULONG ValidBytes, 00204 IN FEATURE_NUMBER StartingFeature, 00205 IN ULONG RequestedType 00206 ) 00207 { 00208 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension; 00209 PCDROM_DATA cdData; 00210 SCSI_REQUEST_BLOCK srb; 00211 PCDB cdb; 00212 ULONG_PTR returned; 00213 NTSTATUS status; 00214 00215 PAGED_CODE(); 00216 ASSERT(Buffer); 00217 ASSERT(ValidBytes); 00218 00219 *ValidBytes = 0; 00220 returned = 0; 00221 00222 RtlZeroMemory(&srb, sizeof(SCSI_REQUEST_BLOCK)); 00223 RtlZeroMemory(Buffer, BufferSize); 00224 00225 fdoExtension = Fdo->DeviceExtension; 00226 cdData = (PCDROM_DATA)(fdoExtension->CommonExtension.DriverData); 00227 00228 if (TEST_FLAG(cdData->HackFlags, CDROM_HACK_BAD_GET_CONFIG_SUPPORT)) { 00229 return STATUS_INVALID_DEVICE_REQUEST; 00230 } 00231 00232 srb.TimeOutValue = CDROM_GET_CONFIGURATION_TIMEOUT; 00233 srb.CdbLength = 10; 00234 00235 cdb = (PCDB)srb.Cdb; 00236 cdb->GET_CONFIGURATION.OperationCode = SCSIOP_GET_CONFIGURATION; 00237 cdb->GET_CONFIGURATION.RequestType = (UCHAR)RequestedType; 00238 cdb->GET_CONFIGURATION.StartingFeature[0] = (UCHAR)(StartingFeature >> 8); 00239 cdb->GET_CONFIGURATION.StartingFeature[1] = (UCHAR)(StartingFeature & 0xff); 00240 cdb->GET_CONFIGURATION.AllocationLength[0] = (UCHAR)(BufferSize >> 8); 00241 cdb->GET_CONFIGURATION.AllocationLength[1] = (UCHAR)(BufferSize & 0xff); 00242 00243 status = ClassSendSrbSynchronous(Fdo, &srb, Buffer, 00244 BufferSize, FALSE); 00245 returned = srb.DataTransferLength; 00246 00247 KdPrintEx((DPFLTR_CDROM_ID, CdromDebugFeatures, 00248 "CdromGetConfiguration: Status was %x\n", status)); 00249 00250 if (NT_SUCCESS(status) || status == STATUS_BUFFER_OVERFLOW) { 00251 00252 // 00253 // if returned more than can be stored in a ULONG, return false 00254 // 00255 00256 if (returned > (ULONG)(-1)) { 00257 return STATUS_UNSUCCESSFUL; 00258 } 00259 ASSERT(returned <= BufferSize); 00260 *ValidBytes = (ULONG)returned; 00261 return STATUS_SUCCESS; 00262 00263 } else { 00264 00265 KdPrintEx((DPFLTR_CDROM_ID, CdromDebugFeatures, 00266 "CdromGetConfiguration: failed %x\n", status)); 00267 return status; 00268 00269 } 00270 ASSERT(FALSE); 00271 return STATUS_UNSUCCESSFUL; 00272 } 00273 00274 /*++ 00275 00276 Allocates buffer with configuration info, returns STATUS_SUCCESS 00277 or an error if one occurred 00278 00279 NOTE: does not handle case where more than 65000 bytes are returned, 00280 which requires multiple calls with different starting feature 00281 numbers. 00282 00283 --*/ 00284 NTSTATUS 00285 CdRomGetConfiguration( 00286 IN PDEVICE_OBJECT Fdo, 00287 OUT PGET_CONFIGURATION_HEADER *Buffer, 00288 OUT PULONG BytesReturned, 00289 IN FEATURE_NUMBER StartingFeature, 00290 IN ULONG RequestedType 00291 ) 00292 { 00293 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension; 00294 GET_CONFIGURATION_HEADER header; // eight bytes, not a lot 00295 PGET_CONFIGURATION_HEADER buffer; 00296 ULONG returned; 00297 ULONG size; 00298 ULONG i; 00299 NTSTATUS status; 00300 00301 PAGED_CODE(); 00302 00303 00304 fdoExtension = Fdo->DeviceExtension; 00305 *Buffer = NULL; 00306 *BytesReturned = 0; 00307 00308 buffer = NULL; 00309 returned = 0; 00310 00311 // 00312 // send the first request down to just get the header 00313 // 00314 00315 status = CdRompGetConfiguration(Fdo, &header, sizeof(header), 00316 &returned, StartingFeature, RequestedType); 00317 00318 if (!NT_SUCCESS(status)) { 00319 return status; 00320 } 00321 00322 // 00323 // now try again, using information returned to allocate 00324 // just enough memory 00325 // 00326 00327 size = header.DataLength[0] << 24 | 00328 header.DataLength[1] << 16 | 00329 header.DataLength[2] << 8 | 00330 header.DataLength[3] << 0 ; 00331 00332 00333 for (i = 0; i < 4; i++) { 00334 00335 // 00336 // the datalength field is the size *following* 00337 // itself, so adjust accordingly 00338 // 00339 00340 size += 4*sizeof(UCHAR); 00341 00342 // 00343 // make sure the size is reasonable 00344 // 00345 00346 if (size <= sizeof(FEATURE_HEADER)) { 00347 KdPrintEx((DPFLTR_CDROM_ID, CdromDebugFeatures, 00348 "CdromGetConfiguration: drive reports only %x bytes?\n", 00349 size)); 00350 return STATUS_UNSUCCESSFUL; 00351 } 00352 00353 // 00354 // allocate the memory 00355 // 00356 00357 buffer = (PGET_CONFIGURATION_HEADER) 00358 ExAllocatePoolWithTag(NonPagedPoolCacheAligned, 00359 size, 00360 CDROM_TAG_FEATURE); 00361 00362 if (buffer == NULL) { 00363 return STATUS_INSUFFICIENT_RESOURCES; 00364 } 00365 00366 // 00367 // send the first request down to just get the header 00368 // 00369 00370 status = CdRompGetConfiguration(Fdo, buffer, size, &returned, 00371 StartingFeature, RequestedType); 00372 00373 if (!NT_SUCCESS(status)) { 00374 ExFreePool(buffer); 00375 return status; 00376 } 00377 00378 if (returned > size) { 00379 ExFreePool(buffer); 00380 return STATUS_INTERNAL_ERROR; 00381 } 00382 00383 returned = buffer->DataLength[0] << 24 | 00384 buffer->DataLength[1] << 16 | 00385 buffer->DataLength[2] << 8 | 00386 buffer->DataLength[3] << 0 ; 00387 returned += 4*sizeof(UCHAR); 00388 00389 if (returned <= size) { 00390 *Buffer = buffer; 00391 *BytesReturned = size; // amount of 'safe' memory 00392 return STATUS_SUCCESS; 00393 } 00394 00395 // 00396 // else retry using the new size.... 00397 // 00398 00399 size = returned; 00400 ExFreePool(buffer); 00401 buffer = NULL; 00402 00403 } 00404 00405 // 00406 // it failed after a number of attempts, so just fail. 00407 // 00408 00409 KdPrintEx((DPFLTR_CDROM_ID, CdromDebugFeatures, 00410 "CdRomGetConfiguration: Failed %d attempts to get all feature " 00411 "information\n", i)); 00412 return STATUS_IO_DEVICE_ERROR; 00413 } 00414 00415 VOID 00416 CdRomIsDeviceMmcDevice( 00417 IN PDEVICE_OBJECT Fdo, 00418 OUT PBOOLEAN IsMmc 00419 ) 00420 { 00421 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = Fdo->DeviceExtension; 00422 PCOMMON_DEVICE_EXTENSION commonExtension = Fdo->DeviceExtension; 00423 PCDROM_DATA cdData = commonExtension->DriverData; 00424 GET_CONFIGURATION_HEADER localHeader; 00425 NTSTATUS status; 00426 ULONG usable; 00427 ULONG size; 00428 ULONG previouslyFailed; 00429 00430 PAGED_CODE(); 00431 ASSERT( commonExtension->IsFdo ); 00432 00433 *IsMmc = FALSE; 00434 00435 // 00436 // read the registry in case the drive failed previously, 00437 // and a timeout is occurring. 00438 // 00439 00440 previouslyFailed = FALSE; 00441 ClassGetDeviceParameter(fdoExtension, 00442 CDROM_SUBKEY_NAME, 00443 CDROM_NON_MMC_DRIVE_NAME, 00444 &previouslyFailed 00445 ); 00446 00447 if (previouslyFailed) { 00448 SET_FLAG(cdData->HackFlags, CDROM_HACK_BAD_GET_CONFIG_SUPPORT); 00449 } 00450 00451 // 00452 // check for the following profiles: 00453 // 00454 // ProfileList 00455 // 00456 00457 status = CdRompGetConfiguration(Fdo, 00458 &localHeader, 00459 sizeof(localHeader), 00460 &usable, 00461 FeatureProfileList, 00462 SCSI_GET_CONFIGURATION_REQUEST_TYPE_ALL); 00463 00464 if (status == STATUS_INVALID_DEVICE_REQUEST || 00465 status == STATUS_NO_MEDIA_IN_DEVICE || 00466 status == STATUS_IO_DEVICE_ERROR || 00467 status == STATUS_IO_TIMEOUT) { 00468 00469 KdPrintEx((DPFLTR_CDROM_ID, CdromDebugFeatures, 00470 "GetConfiguration Failed (%x), device %p not mmc-compliant\n", 00471 status, Fdo 00472 )); 00473 previouslyFailed = TRUE; 00474 ClassSetDeviceParameter(fdoExtension, 00475 CDROM_SUBKEY_NAME, 00476 CDROM_NON_MMC_DRIVE_NAME, 00477 previouslyFailed 00478 ); 00479 return; 00480 00481 } else if (!NT_SUCCESS(status)) { 00482 00483 KdPrintEx((DPFLTR_CDROM_ID, CdromDebugError, 00484 "GetConfiguration Failed, status %x -- defaulting to -ROM\n", 00485 status)); 00486 return; 00487 00488 } else if (usable < sizeof(GET_CONFIGURATION_HEADER)) { 00489 00490 KdPrintEx((DPFLTR_CDROM_ID, CdromDebugFeatures, 00491 "GetConfiguration Failed, returned only %x bytes!\n", usable)); 00492 previouslyFailed = TRUE; 00493 ClassSetDeviceParameter(fdoExtension, 00494 CDROM_SUBKEY_NAME, 00495 CDROM_NON_MMC_DRIVE_NAME, 00496 previouslyFailed 00497 ); 00498 return; 00499 00500 } 00501 00502 size = (localHeader.DataLength[0] << 24) | 00503 (localHeader.DataLength[1] << 16) | 00504 (localHeader.DataLength[2] << 8) | 00505 (localHeader.DataLength[3] << 0); 00506 00507 if(size <= 4) { 00508 KdPrintEx((DPFLTR_CDROM_ID, CdromDebugFeatures, 00509 "GetConfiguration Failed, claims MMC support but doesn't " 00510 "correctly return config length!\n")); 00511 return; 00512 } 00513 00514 size += 4; // sizeof the datalength fields 00515 00516 #if DBG 00517 { 00518 PGET_CONFIGURATION_HEADER dbgBuffer; 00519 NTSTATUS dbgStatus; 00520 00521 dbgBuffer = ExAllocatePoolWithTag(NonPagedPoolCacheAligned, 00522 (SIZE_T)size, 00523 CDROM_TAG_FEATURE); 00524 if (dbgBuffer != NULL) { 00525 RtlZeroMemory(dbgBuffer, size); 00526 00527 dbgStatus = CdRompGetConfiguration(Fdo, dbgBuffer, size, 00528 &size, FeatureProfileList, 00529 SCSI_GET_CONFIGURATION_REQUEST_TYPE_ALL); 00530 00531 if (NT_SUCCESS(dbgStatus)) { 00532 CdRompPrintAllFeaturePages(dbgBuffer, usable); 00533 } 00534 ExFreePool(dbgBuffer); 00535 } 00536 } 00537 #endif // DBG 00538 00539 *IsMmc = TRUE; 00540 return; 00541 } 00542 00543 VOID 00544 CdRompPrintAllFeaturePages( 00545 IN PGET_CONFIGURATION_HEADER Buffer, 00546 IN ULONG Usable 00547 ) 00548 { 00549 PFEATURE_HEADER header; 00550 00552 // items expected to ALWAYS be current 00554 header = CdRomFindFeaturePage(Buffer, Usable, FeatureProfileList); 00555 if (header != NULL) { 00556 KdPrintEx((DPFLTR_CDROM_ID, CdromDebugFeatures, 00557 "CdromGetConfiguration: CurrentProfile %x " 00558 "with %x bytes of data at %p\n", 00559 Buffer->CurrentProfile[0] << 8 | 00560 Buffer->CurrentProfile[1], 00561 Usable, Buffer)); 00562 } 00563 00564 header = CdRomFindFeaturePage(Buffer, Usable, FeatureCore); 00565 if (header) { 00566 KdPrintEx((DPFLTR_CDROM_ID, CdromDebugFeatures, 00567 "CdromGetConfiguration: %s %s\n", 00568 (header->Current ? 00569 "Currently supports" : "Is able to support"), 00570 "CORE Features" 00571 )); 00572 } 00573 00574 header = CdRomFindFeaturePage(Buffer, Usable, FeatureMorphing); 00575 if (header) { 00576 KdPrintEx((DPFLTR_CDROM_ID, CdromDebugFeatures, 00577 "CdromGetConfiguration: %s %s\n", 00578 (header->Current ? 00579 "Currently supports" : "Is able to support"), 00580 "Morphing" 00581 )); 00582 } 00583 00584 header = CdRomFindFeaturePage(Buffer, Usable, FeatureMultiRead); 00585 if (header) { 00586 KdPrintEx((DPFLTR_CDROM_ID, CdromDebugFeatures, 00587 "CdromGetConfiguration: %s %s\n", 00588 (header->Current ? 00589 "Currently supports" : "Is able to support"), 00590 "Multi-Read" 00591 )); 00592 } 00593 header = CdRomFindFeaturePage(Buffer, Usable, FeatureRemovableMedium); 00594 if (header) { 00595 KdPrintEx((DPFLTR_CDROM_ID, CdromDebugFeatures, 00596 "CdromGetConfiguration: %s %s\n", 00597 (header->Current ? 00598 "Currently supports" : "Is able to support"), 00599 "Removable Medium" 00600 )); 00601 } 00602 00603 header = CdRomFindFeaturePage(Buffer, Usable, FeatureTimeout); 00604 if (header) { 00605 KdPrintEx((DPFLTR_CDROM_ID, CdromDebugFeatures, 00606 "CdromGetConfiguration: %s %s\n", 00607 (header->Current ? 00608 "Currently supports" : "Is able to support"), 00609 "Timeouts" 00610 )); 00611 } 00612 00613 header = CdRomFindFeaturePage(Buffer, Usable, FeaturePowerManagement); 00614 if (header) { 00615 KdPrintEx((DPFLTR_CDROM_ID, CdromDebugFeatures, 00616 "CdromGetConfiguration: %s %s\n", 00617 (header->Current ? 00618 "Currently supports" : "Is able to support"), 00619 "Power Management" 00620 )); 00621 } 00622 00623 header = CdRomFindFeaturePage(Buffer, Usable, FeatureEmbeddedChanger); 00624 if (header) { 00625 KdPrintEx((DPFLTR_CDROM_ID, CdromDebugFeatures, 00626 "CdromGetConfiguration: %s %s\n", 00627 (header->Current ? 00628 "Currently supports" : "Is able to support"), 00629 "Embedded Changer" 00630 )); 00631 } 00632 00633 header = CdRomFindFeaturePage(Buffer, Usable, FeatureLogicalUnitSerialNumber); 00634 if (header) { 00635 KdPrintEx((DPFLTR_CDROM_ID, CdromDebugFeatures, 00636 "CdromGetConfiguration: %s %s\n", 00637 (header->Current ? 00638 "Currently supports" : "Is able to support"), 00639 "LUN Serial Number" 00640 )); 00641 } 00642 00643 00644 header = CdRomFindFeaturePage(Buffer, Usable, FeatureMicrocodeUpgrade); 00645 if (header) { 00646 KdPrintEx((DPFLTR_CDROM_ID, CdromDebugFeatures, 00647 "CdromGetConfiguration: %s %s\n", 00648 (header->Current ? 00649 "Currently supports" : "Is able to support"), 00650 "Microcode Update" 00651 )); 00652 } 00653 00655 // items expected not to always be current 00657 header = CdRomFindFeaturePage(Buffer, Usable, FeatureCDAudioAnalogPlay); 00658 if (header) { 00659 KdPrintEx((DPFLTR_CDROM_ID, CdromDebugFeatures, 00660 "CdromGetConfiguration: %s %s\n", 00661 (header->Current ? 00662 "Currently supports" : "Is able to support"), 00663 "Analogue CD Audio Operations" 00664 )); 00665 } 00666 00667 header = CdRomFindFeaturePage(Buffer, Usable, FeatureCdRead); 00668 if (header) { 00669 KdPrintEx((DPFLTR_CDROM_ID, CdromDebugFeatures, 00670 "CdromGetConfiguration: %s %s\n", 00671 (header->Current ? 00672 "Currently supports" : "Is able to support"), 00673 "reading from CD-ROM/R/RW" 00674 )); 00675 } 00676 00677 header = CdRomFindFeaturePage(Buffer, Usable, FeatureCdMastering); 00678 if (header) { 00679 KdPrintEx((DPFLTR_CDROM_ID, CdromDebugFeatures, 00680 "CdromGetConfiguration: %s %s\n", 00681 (header->Current ? 00682 "Currently supports" : "Is able to support"), 00683 "CD Recording (Mastering)" 00684 )); 00685 } 00686 00687 header = CdRomFindFeaturePage(Buffer, Usable, FeatureCdTrackAtOnce); 00688 if (header) { 00689 KdPrintEx((DPFLTR_CDROM_ID, CdromDebugFeatures, 00690 "CdromGetConfiguration: %s %s\n", 00691 (header->Current ? 00692 "Currently supports" : "Is able to support"), 00693 "CD Recording (Track At Once)" 00694 )); 00695 } 00696 00697 header = CdRomFindFeaturePage(Buffer, Usable, FeatureDvdCSS); 00698 if (header) { 00699 KdPrintEx((DPFLTR_CDROM_ID, CdromDebugFeatures, 00700 "CdromGetConfiguration: %s %s\n", 00701 (header->Current ? 00702 "Currently supports" : "Is able to support"), 00703 "DVD CSS" 00704 )); 00705 } 00706 00707 header = CdRomFindFeaturePage(Buffer, Usable, FeatureDvdRead); 00708 if (header) { 00709 KdPrintEx((DPFLTR_CDROM_ID, CdromDebugFeatures, 00710 "CdromGetConfiguration: %s %s\n", 00711 (header->Current ? 00712 "Currently supports" : "Is able to support"), 00713 "DVD Structure Reads" 00714 )); 00715 } 00716 00717 header = CdRomFindFeaturePage(Buffer, Usable, FeatureDvdRecordableWrite); 00718 if (header) { 00719 KdPrintEx((DPFLTR_CDROM_ID, CdromDebugFeatures, 00720 "CdromGetConfiguration: %s %s\n", 00721 (header->Current ? 00722 "Currently supports" : "Is able to support"), 00723 "DVD Recording (Mastering)" 00724 )); 00725 } 00726 00727 header = CdRomFindFeaturePage(Buffer, Usable, FeatureDiscControlBlocks); 00728 if (header) { 00729 KdPrintEx((DPFLTR_CDROM_ID, CdromDebugFeatures, 00730 "CdromGetConfiguration: %s %s\n", 00731 (header->Current ? 00732 "Currently supports" : "Is able to support"), 00733 "DVD Disc Control Blocks" 00734 )); 00735 } 00736 00737 header = CdRomFindFeaturePage(Buffer, Usable, FeatureFormattable); 00738 if (header) { 00739 KdPrintEx((DPFLTR_CDROM_ID, CdromDebugFeatures, 00740 "CdromGetConfiguration: %s %s\n", 00741 (header->Current ? 00742 "Currently supports" : "Is able to support"), 00743 "Formatting" 00744 )); 00745 } 00746 00747 header = CdRomFindFeaturePage(Buffer, Usable, FeatureRandomReadable); 00748 if (header) { 00749 KdPrintEx((DPFLTR_CDROM_ID, CdromDebugFeatures, 00750 "CdromGetConfiguration: %s %s\n", 00751 (header->Current ? 00752 "Currently supports" : "Is able to support"), 00753 "Random Reads" 00754 )); 00755 } 00756 00757 header = CdRomFindFeaturePage(Buffer, Usable, FeatureRandomWritable); 00758 if (header) { 00759 KdPrintEx((DPFLTR_CDROM_ID, CdromDebugFeatures, 00760 "CdromGetConfiguration: %s %s\n", 00761 (header->Current ? 00762 "Currently supports" : "Is able to support"), 00763 "Random Writes" 00764 )); 00765 } 00766 00767 header = CdRomFindFeaturePage(Buffer, Usable, FeatureRestrictedOverwrite); 00768 if (header) { 00769 KdPrintEx((DPFLTR_CDROM_ID, CdromDebugFeatures, 00770 "CdromGetConfiguration: %s %s\n", 00771 (header->Current ? 00772 "Currently supports" : "Is able to support"), 00773 "Restricted Overwrites." 00774 )); 00775 } 00776 00777 header = CdRomFindFeaturePage(Buffer, Usable, FeatureWriteOnce); 00778 if (header) { 00779 KdPrintEx((DPFLTR_CDROM_ID, CdromDebugFeatures, 00780 "CdromGetConfiguration: %s %s\n", 00781 (header->Current ? 00782 "Currently supports" : "Is able to support"), 00783 "Write Once Media" 00784 )); 00785 } 00786 00787 header = CdRomFindFeaturePage(Buffer, Usable, FeatureSectorErasable); 00788 if (header) { 00789 KdPrintEx((DPFLTR_CDROM_ID, CdromDebugFeatures, 00790 "CdromGetConfiguration: %s %s\n", 00791 (header->Current ? 00792 "Currently supports" : "Is able to support"), 00793 "Sector Erasable Media" 00794 )); 00795 } 00796 00797 header = CdRomFindFeaturePage(Buffer, Usable, FeatureIncrementalStreamingWritable); 00798 if (header) { 00799 KdPrintEx((DPFLTR_CDROM_ID, CdromDebugFeatures, 00800 "CdromGetConfiguration: %s %s\n", 00801 (header->Current ? 00802 "Currently supports" : "Is able to support"), 00803 "Incremental Streaming Writing" 00804 )); 00805 } 00806 00807 header = CdRomFindFeaturePage(Buffer, Usable, FeatureRealTimeStreaming); 00808 if (header) { 00809 KdPrintEx((DPFLTR_CDROM_ID, CdromDebugFeatures, 00810 "CdromGetConfiguration: %s %s\n", 00811 (header->Current ? 00812 "Currently supports" : "Is able to support"), 00813 "Real-time Streaming Reads" 00814 )); 00815 } 00816 00817 header = CdRomFindFeaturePage(Buffer, Usable, FeatureSMART); 00818 if (header) { 00819 KdPrintEx((DPFLTR_CDROM_ID, CdromDebugFeatures, 00820 "CdromGetConfiguration: %s %s\n", 00821 (header->Current ? 00822 "Currently supports" : "Is able to support"), 00823 "S.M.A.R.T." 00824 )); 00825 } 00826 00827 header = CdRomFindFeaturePage(Buffer, Usable, FeatureDefectManagement); 00828 if (header) { 00829 KdPrintEx((DPFLTR_CDROM_ID, CdromDebugFeatures, 00830 "CdromGetConfiguration: %s %s\n", 00831 (header->Current ? 00832 "Currently supports" : "Is able to support"), 00833 "defect management" 00834 )); 00835 } 00836 return; 00837 } 00838 00839 NTSTATUS 00840 NTAPI 00841 CdRomUpdateMmcDriveCapabilitiesCompletion( 00842 IN PDEVICE_OBJECT Unused, 00843 IN PIRP Irp, 00844 IN PDEVICE_OBJECT Fdo 00845 ) 00846 { 00847 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = Fdo->DeviceExtension; 00848 PCOMMON_DEVICE_EXTENSION commonExtension = Fdo->DeviceExtension; 00849 PCDROM_DATA cdData = fdoExtension->CommonExtension.DriverData; 00850 PCDROM_MMC_EXTENSION mmcData = &(cdData->Mmc); 00851 PSCSI_REQUEST_BLOCK srb = &(mmcData->CapabilitiesSrb); 00852 PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp); 00853 NTSTATUS status = STATUS_UNSUCCESSFUL; 00854 PIRP delayedIrp; 00855 ULONG retryCount; 00856 LARGE_INTEGER delay; 00857 00858 00859 // completion routine should retry as neccessary. 00860 // when success, clear the flag to allow startio to proceed. 00861 // else fail original request when retries are exhausted. 00862 00863 ASSERT(mmcData->CapabilitiesIrp == Irp); 00864 00865 // for now, if succeeded, just print the new pages. 00866 00867 if (SRB_STATUS(srb->SrbStatus) != SRB_STATUS_SUCCESS) { 00868 00869 // 00870 // ISSUE-2000/4/20-henrygab - should we try to reallocate if size 00871 // available became larger than what we 00872 // originally allocated? otherwise, it 00873 // is possible (not probable) that we 00874 // would miss the feature. can check 00875 // that by finding out what the last 00876 // feature is in the current group. 00877 // 00878 00879 BOOLEAN retry; 00880 ULONG retryInterval; 00881 00882 // 00883 // Release the queue if it is frozen. 00884 // 00885 00886 if (srb->SrbStatus & SRB_STATUS_QUEUE_FROZEN) { 00887 ClassReleaseQueue(Fdo); 00888 } 00889 00890 retry = ClassInterpretSenseInfo( 00891 Fdo, 00892 srb, 00893 irpStack->MajorFunction, 00894 0, 00895 MAXIMUM_RETRIES - ((ULONG)(ULONG_PTR)irpStack->Parameters.Others.Argument4), 00896 &status, 00897 &retryInterval); 00898 00899 // 00900 // DATA_OVERRUN is not an error in this case.... 00901 // 00902 00903 if (status == STATUS_DATA_OVERRUN) { 00904 status = STATUS_SUCCESS; 00905 } 00906 00907 // 00908 // override verify_volume based on original irp's settings 00909 // 00910 00911 if (TEST_FLAG(irpStack->Flags, SL_OVERRIDE_VERIFY_VOLUME) && 00912 status == STATUS_VERIFY_REQUIRED) { 00913 status = STATUS_IO_DEVICE_ERROR; 00914 retry = TRUE; 00915 } 00916 00917 // 00918 // get current retry count 00919 // 00920 retryCount = PtrToUlong(irpStack->Parameters.Others.Argument1); 00921 00922 if (retry && retryCount) { 00923 00924 // 00925 // update retry count 00926 // 00927 irpStack->Parameters.Others.Argument1 = UlongToPtr(retryCount-1); 00928 00929 00930 delay.QuadPart = retryInterval; 00931 delay.QuadPart *= (LONGLONG)1000 * 1000 * 10; 00932 00933 // 00934 // retry the request 00935 // 00936 00937 KdPrintEx((DPFLTR_CDROM_ID, CdromDebugError, 00938 "Not using ClassRetryRequest Yet\n")); 00939 KdPrintEx((DPFLTR_CDROM_ID, CdromDebugFeatures, 00940 "Retry update capabilities %p\n", Irp)); 00941 CdRomPrepareUpdateCapabilitiesIrp(Fdo); 00942 00943 CdRomRetryRequest(fdoExtension, Irp, retryInterval, TRUE); 00944 00945 // 00946 // ClassRetryRequest(Fdo, Irp, delay); 00947 // 00948 00949 return STATUS_MORE_PROCESSING_REQUIRED; 00950 00951 } 00952 00953 } else { 00954 00955 status = STATUS_SUCCESS; 00956 00957 } 00958 00959 Irp->IoStatus.Status = status; 00960 00961 KeSetEvent(&mmcData->CapabilitiesEvent, IO_CD_ROM_INCREMENT, FALSE); 00962 00963 00964 return STATUS_MORE_PROCESSING_REQUIRED; 00965 } 00966 00967 00968 VOID 00969 CdRomPrepareUpdateCapabilitiesIrp( 00970 PDEVICE_OBJECT Fdo 00971 ) 00972 { 00973 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = Fdo->DeviceExtension; 00974 PCOMMON_DEVICE_EXTENSION commonExtension = Fdo->DeviceExtension; 00975 PCDROM_DATA cdData = fdoExtension->CommonExtension.DriverData; 00976 PCDROM_MMC_EXTENSION mmcData = &(cdData->Mmc); 00977 PIO_STACK_LOCATION nextStack; 00978 PSCSI_REQUEST_BLOCK srb; 00979 PCDB cdb; 00980 ULONG bufferSize; 00981 PIRP irp; 00982 00983 ASSERT(mmcData->UpdateState); 00984 ASSERT(ExQueryDepthSList(&(mmcData->DelayedIrps)) != 0); 00985 ASSERT(mmcData->CapabilitiesIrp != NULL); 00986 ASSERT(mmcData->CapabilitiesMdl != NULL); 00987 ASSERT(mmcData->CapabilitiesBuffer); 00988 ASSERT(mmcData->CapabilitiesBufferSize != 0); 00989 ASSERT(fdoExtension->SenseData); 00990 00991 // 00992 // do *NOT* call IoReuseIrp(), since it would zero out our 00993 // current irp stack location, which we really don't want 00994 // to happen. it would also set the current irp stack location 00995 // to one greater than currently exists (to give max irp usage), 00996 // but we don't want that either, since we use the top irp stack. 00997 // 00998 // IoReuseIrp(mmcData->CapabilitiesIrp, STATUS_UNSUCCESSFUL); 00999 // 01000 01001 irp = mmcData->CapabilitiesIrp; 01002 srb = &(mmcData->CapabilitiesSrb); 01003 cdb = (PCDB)(srb->Cdb); 01004 bufferSize = mmcData->CapabilitiesBufferSize; 01005 01006 // 01007 // zero stuff out 01008 // 01009 01010 RtlZeroMemory(srb, sizeof(SCSI_REQUEST_BLOCK)); 01011 RtlZeroMemory(fdoExtension->SenseData, sizeof(SENSE_DATA)); 01012 RtlZeroMemory(mmcData->CapabilitiesBuffer, bufferSize); 01013 01014 // 01015 // setup the srb 01016 // 01017 01018 srb->TimeOutValue = CDROM_GET_CONFIGURATION_TIMEOUT; 01019 srb->Length = SCSI_REQUEST_BLOCK_SIZE; 01020 srb->Function = SRB_FUNCTION_EXECUTE_SCSI; 01021 srb->SenseInfoBufferLength = SENSE_BUFFER_SIZE; 01022 srb->SenseInfoBuffer = fdoExtension->SenseData; 01023 srb->DataBuffer = mmcData->CapabilitiesBuffer; 01024 srb->QueueAction = SRB_SIMPLE_TAG_REQUEST; 01025 srb->DataTransferLength = mmcData->CapabilitiesBufferSize; 01026 srb->ScsiStatus = 0; 01027 srb->SrbStatus = 0; 01028 srb->NextSrb = NULL; 01029 srb->OriginalRequest = irp; 01030 srb->SrbFlags = fdoExtension->SrbFlags; 01031 srb->CdbLength = 10; 01032 SET_FLAG(srb->SrbFlags, SRB_FLAGS_DATA_IN); 01033 SET_FLAG(srb->SrbFlags, SRB_FLAGS_NO_QUEUE_FREEZE); 01034 01035 // 01036 // setup the cdb 01037 // 01038 01039 cdb->GET_CONFIGURATION.OperationCode = SCSIOP_GET_CONFIGURATION; 01040 cdb->GET_CONFIGURATION.RequestType = SCSI_GET_CONFIGURATION_REQUEST_TYPE_CURRENT; 01041 cdb->GET_CONFIGURATION.StartingFeature[0] = 0; 01042 cdb->GET_CONFIGURATION.StartingFeature[1] = 0; 01043 cdb->GET_CONFIGURATION.AllocationLength[0] = (UCHAR)(bufferSize >> 8); 01044 cdb->GET_CONFIGURATION.AllocationLength[1] = (UCHAR)(bufferSize & 0xff); 01045 01046 // 01047 // setup the irp 01048 // 01049 01050 nextStack = IoGetNextIrpStackLocation(irp); 01051 nextStack->MajorFunction = IRP_MJ_SCSI; 01052 nextStack->Parameters.Scsi.Srb = srb; 01053 irp->MdlAddress = mmcData->CapabilitiesMdl; 01054 irp->AssociatedIrp.SystemBuffer = mmcData->CapabilitiesBuffer; 01055 IoSetCompletionRoutine(irp, (PIO_COMPLETION_ROUTINE)CdRomUpdateMmcDriveCapabilitiesCompletion, Fdo, 01056 TRUE, TRUE, TRUE); 01057 01058 return; 01059 01060 } 01061 01062 VOID 01063 CdRomUpdateMmcDriveCapabilities( 01064 IN PDEVICE_OBJECT Fdo, 01065 IN PVOID Context 01066 ) 01067 { 01068 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = Fdo->DeviceExtension; 01069 PCOMMON_DEVICE_EXTENSION commonExtension = Fdo->DeviceExtension; 01070 PCDROM_DATA cdData = fdoExtension->CommonExtension.DriverData; 01071 PCDROM_MMC_EXTENSION mmcData = &(cdData->Mmc); 01072 PIO_STACK_LOCATION thisStack = IoGetCurrentIrpStackLocation(mmcData->CapabilitiesIrp); 01073 PSCSI_REQUEST_BLOCK srb = &(mmcData->CapabilitiesSrb); 01074 NTSTATUS status; 01075 01076 01077 ASSERT(Context == NULL); 01078 01079 // 01080 // NOTE: a remove lock is unneccessary, since the delayed irp 01081 // will have said lock held for itself, preventing a remove. 01082 // 01083 CdRomPrepareUpdateCapabilitiesIrp(Fdo); 01084 01085 ASSERT(thisStack->Parameters.Others.Argument1 == Fdo); 01086 ASSERT(thisStack->Parameters.Others.Argument2 == mmcData->CapabilitiesBuffer); 01087 ASSERT(thisStack->Parameters.Others.Argument3 == &(mmcData->CapabilitiesSrb)); 01088 01089 mmcData->WriteAllowed = FALSE; // default to read-only 01090 01091 // 01092 // set max retries, and also allow volume verify override based on 01093 // original (delayed) irp 01094 // 01095 01096 thisStack->Parameters.Others.Argument4 = (PVOID)MAXIMUM_RETRIES; 01097 01098 // 01099 // send to self... note that SL_OVERRIDE_VERIFY_VOLUME is not required, 01100 // as this is IRP_MJ_INTERNAL_DEVICE_CONTROL 01101 // 01102 01103 IoCallDriver(commonExtension->LowerDeviceObject, mmcData->CapabilitiesIrp); 01104 01105 KeWaitForSingleObject(&mmcData->CapabilitiesEvent, 01106 Executive, KernelMode, FALSE, NULL); 01107 01108 status = mmcData->CapabilitiesIrp->IoStatus.Status; 01109 01110 if (!NT_SUCCESS(status)) { 01111 01112 goto FinishDriveUpdate; 01113 01114 } 01115 01116 // 01117 // we've updated the feature set, so update whether or not reads and writes 01118 // are allowed or not. 01119 // 01120 01121 KdPrintEx((DPFLTR_CDROM_ID, CdromDebugFeatures, 01122 "CdRomUpdateMmc => Succeeded " 01123 "--------------------" 01124 "--------------------\n")); 01125 01126 /*++ 01127 01128 NOTE: It is important to only use srb->DataTransferLength worth 01129 of data at this point, since the bufferSize is what is 01130 *available* to use, not what was *actually* used. 01131 01132 --*/ 01133 01134 #if DBG 01135 CdRompPrintAllFeaturePages(mmcData->CapabilitiesBuffer, 01136 srb->DataTransferLength); 01137 #endif // DBG 01138 01139 // 01140 // update whether or not writes are allowed. this is currently defined 01141 // as requiring TargetDefectManagement and RandomWritable features 01142 // 01143 { 01144 PFEATURE_HEADER defectHeader; 01145 PFEATURE_HEADER writableHeader; 01146 01147 defectHeader = CdRomFindFeaturePage(mmcData->CapabilitiesBuffer, 01148 srb->DataTransferLength, 01149 FeatureDefectManagement); 01150 writableHeader = CdRomFindFeaturePage(mmcData->CapabilitiesBuffer, 01151 srb->DataTransferLength, 01152 FeatureRandomWritable); 01153 01154 if ((defectHeader != NULL) && (writableHeader != NULL) && 01155 (defectHeader->Current) && (writableHeader->Current)) { 01156 01157 // 01158 // this should be the *ONLY* place writes are set to allowed 01159 // 01160 01161 KdPrintEx((DPFLTR_CDROM_ID, CdromDebugFeatures, 01162 "CdRomUpdateMmc => Writes *allowed*\n")); 01163 mmcData->WriteAllowed = TRUE; 01164 01165 } else { 01166 01167 if (defectHeader == NULL) { 01168 KdPrintEx((DPFLTR_CDROM_ID, CdromDebugFeatures, 01169 "CdRomUpdateMmc => No writes - %s = %s\n", 01170 "defect management", "DNE")); 01171 } else { 01172 KdPrintEx((DPFLTR_CDROM_ID, CdromDebugFeatures, 01173 "CdRomUpdateMmc => No writes - %s = %s\n", 01174 "defect management", "Not Current")); 01175 } 01176 if (writableHeader == NULL) { 01177 KdPrintEx((DPFLTR_CDROM_ID, CdromDebugFeatures, 01178 "CdRomUpdateMmc => No writes - %s = %s\n", 01179 "sector writable", "DNE")); 01180 } else { 01181 KdPrintEx((DPFLTR_CDROM_ID, CdromDebugFeatures, 01182 "CdRomUpdateMmc => No writes - %s = %s\n", 01183 "sector writable", "Not Current")); 01184 } 01185 } // end of feature checking 01186 } // end of check for writability 01187 01188 // 01189 // update the cached partition table information 01190 // 01191 // NOTE: THIS WILL CURRENTLY CAUSE A DEADLOCK! 01192 // 01193 // ISSUE-2000/06/20-henrygab - partition support not implemented 01194 // IoReadPartitionTable must be done 01195 // at PASSIVE level, requiring a thread 01196 // or worker item or other such method. 01197 // 01198 #if 0 01199 status = IoReadPartitionTable(Fdo, 1 << fdoExtension->SectorShift, 01200 TRUE, &mmcData->PartitionList); 01201 if (!NT_SUCCESS(status)) { 01202 01203 goto FinishDriveUpdate; 01204 01205 } 01206 #endif 01207 01208 status = STATUS_SUCCESS; 01209 01210 FinishDriveUpdate: 01211 01212 CdRompFlushDelayedList(Fdo, mmcData, status, TRUE); 01213 01214 return; 01215 } 01216 01217 01218 VOID 01219 CdRompFlushDelayedList( 01220 IN PDEVICE_OBJECT Fdo, 01221 IN PCDROM_MMC_EXTENSION MmcData, 01222 IN NTSTATUS Status, 01223 IN BOOLEAN CalledFromWorkItem 01224 ) 01225 { 01226 PSINGLE_LIST_ENTRY list; 01227 PIRP irp; 01228 01229 // NOTE - REF #0002 01230 // 01231 // need to set the new state first to prevent deadlocks. 01232 // this is only done from the workitem, to prevent any 01233 // edge cases where we'd "lose" the UpdateRequired 01234 // 01235 // then, must ignore the state, since it's not guaranteed to 01236 // be the same any longer. the only thing left is to handle 01237 // all the delayed irps by flushing the queue and sending them 01238 // back onto the StartIo queue for the device. 01239 // 01240 01241 if (CalledFromWorkItem) { 01242 01243 LONG oldState; 01244 LONG newState; 01245 01246 if (NT_SUCCESS(Status)) { 01247 newState = CdromMmcUpdateComplete; 01248 } else { 01249 newState = CdromMmcUpdateRequired; 01250 } 01251 01252 oldState = InterlockedCompareExchange(&MmcData->UpdateState, 01253 newState, 01254 CdromMmcUpdateStarted); 01255 ASSERT(oldState == CdromMmcUpdateStarted); 01256 01257 } else { 01258 01259 // 01260 // just flushing the queue if not called from the workitem, 01261 // and we don't want to ever fail the queue in those cases. 01262 // 01263 01264 ASSERT(NT_SUCCESS(Status)); 01265 01266 } 01267 01268 list = ExInterlockedFlushSList(&MmcData->DelayedIrps); 01269 01270 // if this assert fires, it means that we have started 01271 // a workitem when the previous workitem took the delayed 01272 // irp. if this happens, then the logic in HACKHACK #0002 01273 // is either flawed or the rules set within are not being 01274 // followed. this would require investigation. 01275 01276 ASSERT(list != NULL); 01277 01278 // 01279 // now either succeed or fail all the delayed irps, according 01280 // to the update status. 01281 // 01282 01283 while (list != NULL) { 01284 01285 irp = (PIRP)( ((PUCHAR)list) - 01286 FIELD_OFFSET(IRP, Tail.Overlay.DriverContext[0]) 01287 ); 01288 list = list->Next; 01289 irp->Tail.Overlay.DriverContext[0] = 0; 01290 irp->Tail.Overlay.DriverContext[1] = 0; 01291 irp->Tail.Overlay.DriverContext[2] = 0; 01292 irp->Tail.Overlay.DriverContext[3] = 0; 01293 01294 if (NT_SUCCESS(Status)) { 01295 01296 KdPrintEx((DPFLTR_CDROM_ID, CdromDebugFeatures, 01297 "CdRomUpdateMmc => Re-sending delayed irp %p\n", 01298 irp)); 01299 IoStartPacket(Fdo, irp, NULL, NULL); 01300 01301 } else { 01302 01303 KdPrintEx((DPFLTR_CDROM_ID, CdromDebugFeatures, 01304 "CdRomUpdateMmc => Failing delayed irp %p with " 01305 " status %x\n", irp, Status)); 01306 irp->IoStatus.Information = 0; 01307 irp->IoStatus.Status = Status; 01308 ClassReleaseRemoveLock(Fdo, irp); 01309 IoCompleteRequest(irp, IO_CD_ROM_INCREMENT); 01310 01311 } 01312 01313 } // while (list) 01314 01315 return; 01316 01317 } 01318 01319 VOID 01320 CdRomDeAllocateMmcResources( 01321 IN PDEVICE_OBJECT Fdo 01322 ) 01323 { 01324 PCOMMON_DEVICE_EXTENSION commonExtension = Fdo->DeviceExtension; 01325 PCDROM_DATA cddata = commonExtension->DriverData; 01326 PCDROM_MMC_EXTENSION mmcData = &cddata->Mmc; 01327 NTSTATUS status; 01328 01329 if (mmcData->CapabilitiesWorkItem) { 01330 IoFreeWorkItem(mmcData->CapabilitiesWorkItem); 01331 mmcData->CapabilitiesWorkItem = NULL; 01332 } 01333 if (mmcData->CapabilitiesIrp) { 01334 IoFreeIrp(mmcData->CapabilitiesIrp); 01335 mmcData->CapabilitiesIrp = NULL; 01336 } 01337 if (mmcData->CapabilitiesMdl) { 01338 IoFreeMdl(mmcData->CapabilitiesMdl); 01339 mmcData->CapabilitiesMdl = NULL; 01340 } 01341 if (mmcData->CapabilitiesBuffer) { 01342 ExFreePool(mmcData->CapabilitiesBuffer); 01343 mmcData->CapabilitiesBuffer = NULL; 01344 } 01345 mmcData->CapabilitiesBuffer = 0; 01346 mmcData->IsMmc = FALSE; 01347 mmcData->WriteAllowed = FALSE; 01348 01349 return; 01350 } 01351 01352 NTSTATUS 01353 CdRomAllocateMmcResources( 01354 IN PDEVICE_OBJECT Fdo 01355 ) 01356 { 01357 PCOMMON_DEVICE_EXTENSION commonExtension = Fdo->DeviceExtension; 01358 PCDROM_DATA cddata = commonExtension->DriverData; 01359 PCDROM_MMC_EXTENSION mmcData = &cddata->Mmc; 01360 PIO_STACK_LOCATION irpStack; 01361 NTSTATUS status; 01362 01363 ASSERT(mmcData->CapabilitiesWorkItem == NULL); 01364 ASSERT(mmcData->CapabilitiesIrp == NULL); 01365 ASSERT(mmcData->CapabilitiesMdl == NULL); 01366 ASSERT(mmcData->CapabilitiesBuffer == NULL); 01367 ASSERT(mmcData->CapabilitiesBufferSize == 0); 01368 01369 status = CdRomGetConfiguration(Fdo, 01370 &mmcData->CapabilitiesBuffer, 01371 &mmcData->CapabilitiesBufferSize, 01372 FeatureProfileList, 01373 SCSI_GET_CONFIGURATION_REQUEST_TYPE_ALL); 01374 if (!NT_SUCCESS(status)) { 01375 ASSERT(mmcData->CapabilitiesBuffer == NULL); 01376 ASSERT(mmcData->CapabilitiesBufferSize == 0); 01377 return status; 01378 } 01379 ASSERT(mmcData->CapabilitiesBuffer != NULL); 01380 ASSERT(mmcData->CapabilitiesBufferSize != 0); 01381 01382 mmcData->CapabilitiesMdl = IoAllocateMdl(mmcData->CapabilitiesBuffer, 01383 mmcData->CapabilitiesBufferSize, 01384 FALSE, FALSE, NULL); 01385 if (mmcData->CapabilitiesMdl == NULL) { 01386 ExFreePool(mmcData->CapabilitiesBuffer); 01387 mmcData->CapabilitiesBufferSize = 0; 01388 return STATUS_INSUFFICIENT_RESOURCES; 01389 } 01390 01391 01392 mmcData->CapabilitiesIrp = IoAllocateIrp(Fdo->StackSize + 2, FALSE); 01393 if (mmcData->CapabilitiesIrp == NULL) { 01394 IoFreeMdl(mmcData->CapabilitiesMdl); 01395 ExFreePool(mmcData->CapabilitiesBuffer); 01396 mmcData->CapabilitiesBufferSize = 0; 01397 return STATUS_INSUFFICIENT_RESOURCES; 01398 } 01399 01400 mmcData->CapabilitiesWorkItem = IoAllocateWorkItem(Fdo); 01401 if (mmcData->CapabilitiesWorkItem == NULL) { 01402 IoFreeIrp(mmcData->CapabilitiesIrp); 01403 IoFreeMdl(mmcData->CapabilitiesMdl); 01404 ExFreePool(mmcData->CapabilitiesBuffer); 01405 mmcData->CapabilitiesBufferSize = 0; 01406 return STATUS_INSUFFICIENT_RESOURCES; 01407 } 01408 01409 // 01410 // everything has been allocated, so now prepare it all.... 01411 // 01412 01413 MmBuildMdlForNonPagedPool(mmcData->CapabilitiesMdl); 01414 ExInitializeSListHead(&mmcData->DelayedIrps); 01415 KeInitializeSpinLock(&mmcData->DelayedLock); 01416 01417 // 01418 // use the extra stack for internal bookkeeping 01419 // 01420 IoSetNextIrpStackLocation(mmcData->CapabilitiesIrp); 01421 irpStack = IoGetCurrentIrpStackLocation(mmcData->CapabilitiesIrp); 01422 irpStack->Parameters.Others.Argument1 = Fdo; 01423 irpStack->Parameters.Others.Argument2 = mmcData->CapabilitiesBuffer; 01424 irpStack->Parameters.Others.Argument3 = &(mmcData->CapabilitiesSrb); 01425 // arg 4 is the retry count 01426 01427 // 01428 // set the completion event to FALSE for now 01429 // 01430 01431 KeInitializeEvent(&mmcData->CapabilitiesEvent, 01432 SynchronizationEvent, FALSE); 01433 return STATUS_SUCCESS; 01434 01435 } 01436 Generated on Sun May 27 2012 04:16:56 for ReactOS by
1.7.6.1
|