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

mmc.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 doxygen 1.7.6.1

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