1 /* 2 * PROJECT: ReactOS Storage Stack 3 * LICENSE: DDK - see license.txt in the root dir 4 * FILE: drivers/storage/cdrom/cdrom.c 5 * PURPOSE: CDROM driver 6 * PROGRAMMERS: Based on a source code sample from Microsoft NT4 DDK 7 */ 8 9 #include "precomp.h" 10 11 #include <ntddk.h> 12 #include <scsi.h> 13 #include <ntdddisk.h> 14 #include <ntddcdrm.h> 15 #include <include/class2.h> 16 #include <stdio.h> 17 18 //#define NDEBUG 19 #include <debug.h> 20 21 #define CDB12GENERIC_LENGTH 12 22 23 typedef struct _XA_CONTEXT { 24 25 // 26 // Pointer to the device object. 27 // 28 29 PDEVICE_OBJECT DeviceObject; 30 31 // 32 // Pointer to the original request when 33 // a mode select must be sent. 34 // 35 36 PIRP OriginalRequest; 37 38 // 39 // Pointer to the mode select srb. 40 // 41 42 PSCSI_REQUEST_BLOCK Srb; 43 } XA_CONTEXT, *PXA_CONTEXT; 44 45 typedef struct _ERROR_RECOVERY_DATA { 46 MODE_PARAMETER_HEADER Header; 47 MODE_PARAMETER_BLOCK BlockDescriptor; 48 MODE_READ_RECOVERY_PAGE ReadRecoveryPage; 49 } ERROR_RECOVERY_DATA, *PERROR_RECOVERY_DATA; 50 51 typedef struct _ERROR_RECOVERY_DATA10 { 52 MODE_PARAMETER_HEADER10 Header10; 53 MODE_PARAMETER_BLOCK BlockDescriptor10; 54 MODE_READ_RECOVERY_PAGE ReadRecoveryPage10; 55 } ERROR_RECOVERY_DATA10, *PERROR_RECOVERY_DATA10; 56 57 // 58 // CdRom specific addition to device extension. 59 // 60 61 typedef struct _CDROM_DATA { 62 63 // 64 // Indicates whether an audio play operation 65 // is currently being performed. 66 // 67 68 BOOLEAN PlayActive; 69 70 // 71 // Indicates whether the blocksize used for user data 72 // is 2048 or 2352. 73 // 74 75 BOOLEAN RawAccess; 76 77 // 78 // Indicates whether 6 or 10 byte mode sense/select 79 // should be used. 80 // 81 82 USHORT XAFlags; 83 84 // 85 // Storage for the error recovery page. This is used 86 // as an easy method to switch block sizes. 87 // 88 89 union { 90 ERROR_RECOVERY_DATA u1; 91 ERROR_RECOVERY_DATA10 u2; 92 }; 93 94 95 // 96 // Pointer to the original irp for the raw read. 97 // 98 99 PIRP SavedReadIrp; 100 101 // 102 // Used to protect accesses to the RawAccess flag. 103 // 104 105 KSPIN_LOCK FormSpinLock; 106 107 // 108 // Even if media change support is requested, there are some devices 109 // that are not supported. This flag will indicate that such a device 110 // is present when it is FALSE. 111 // 112 113 BOOLEAN MediaChangeSupported; 114 115 // 116 // The media change event is being supported. The media change timer 117 // should be running whenever this is true. 118 // 119 120 BOOLEAN MediaChange; 121 122 // 123 // The timer value to support media change events. This is a countdown 124 // value used to determine when to poll the device for a media change. 125 // The max value for the timer is 255 seconds. 126 // 127 128 UCHAR MediaChangeCountDown; 129 130 #if DBG 131 // 132 // Second timer to keep track of how long the media change IRP has been 133 // in use. If this value exceeds the timeout (#defined) then we should 134 // print out a message to the user and set the MediaChangeIrpLost flag 135 // 136 137 SHORT MediaChangeIrpTimeInUse; 138 139 // 140 // Set by CdRomTickHandler when we determine that the media change irp has 141 // been lost 142 // 143 144 BOOLEAN MediaChangeIrpLost; 145 #endif 146 147 UCHAR PadReserve; // use this for new flags. 148 149 // 150 // An IRP is allocated and kept for the duration that media change 151 // detection is in effect. If this is NULL and MediaChange is TRUE, 152 // the detection is in progress. This should always be NULL when 153 // MediaChange is FALSE. 154 // 155 156 PIRP MediaChangeIrp; 157 158 // 159 // The timer work list is a collection of IRPS that are prepared for 160 // submission, but need to allow some time to pass before they are 161 // run. 162 // 163 164 LIST_ENTRY TimerIrpList; 165 KSPIN_LOCK TimerIrpSpinLock; 166 167 } CDROM_DATA, *PCDROM_DATA; 168 169 #define DEVICE_EXTENSION_SIZE sizeof(DEVICE_EXTENSION) + sizeof(CDROM_DATA) 170 #define SCSI_CDROM_TIMEOUT 10 171 #define SCSI_CHANGER_BONUS_TIMEOUT 10 172 #define HITACHI_MODE_DATA_SIZE 12 173 #define MODE_DATA_SIZE 64 174 #define RAW_SECTOR_SIZE 2352 175 #define COOKED_SECTOR_SIZE 2048 176 #define MEDIA_CHANGE_DEFAULT_TIME 4 177 #define CDROM_SRB_LIST_SIZE 4 178 179 180 #if DBG 181 182 // 183 // Used to detect the loss of the autorun irp. The driver prints out a message 184 // (debug level 0) if this timeout ever occurs 185 // 186 #define MEDIA_CHANGE_TIMEOUT_TIME 300 187 188 #endif 189 190 #define PLAY_ACTIVE(DeviceExtension) (((PCDROM_DATA)(DeviceExtension + 1))->PlayActive) 191 192 #define MSF_TO_LBA(Minutes,Seconds,Frames) \ 193 (ULONG)((60 * 75 * (Minutes)) + (75 * (Seconds)) + ((Frames) - 150)) 194 195 #define LBA_TO_MSF(Lba,Minutes,Seconds,Frames) \ 196 { \ 197 (Minutes) = (UCHAR)(Lba / (60 * 75)); \ 198 (Seconds) = (UCHAR)((Lba % (60 * 75)) / 75); \ 199 (Frames) = (UCHAR)((Lba % (60 * 75)) % 75); \ 200 } 201 202 #define DEC_TO_BCD(x) (((x / 10) << 4) + (x % 10)) 203 204 // 205 // Define flags for XA, CDDA, and Mode Select/Sense 206 // 207 208 #define XA_USE_6_BYTE 0x01 209 #define XA_USE_10_BYTE 0x02 210 #define XA_USE_READ_CD 0x04 211 #define XA_NOT_SUPPORTED 0x08 212 213 #define PLEXTOR_CDDA 0x10 214 #define NEC_CDDA 0x20 215 216 // 217 // Sector types for READ_CD 218 // 219 220 #define ANY_SECTOR 0 221 #define CD_DA_SECTOR 1 222 #define YELLOW_MODE1_SECTOR 2 223 #define YELLOW_MODE2_SECTOR 3 224 #define FORM2_MODE1_SECTOR 4 225 #define FORM2_MODE2_SECTOR 5 226 227 228 #ifdef POOL_TAGGING 229 #ifdef ExAllocatePool 230 #undef ExAllocatePool 231 #endif 232 #define ExAllocatePool(a,b) ExAllocatePoolWithTag(a,b,'CscS') 233 #endif 234 235 NTSTATUS 236 NTAPI 237 DriverEntry( 238 IN PDRIVER_OBJECT DriverObject, 239 IN PUNICODE_STRING RegistryPath 240 ); 241 242 BOOLEAN 243 NTAPI 244 ScsiCdRomFindDevices( 245 IN PDRIVER_OBJECT DriverObject, 246 IN PUNICODE_STRING RegistryPath, 247 IN PCLASS_INIT_DATA InitializationData, 248 IN PDEVICE_OBJECT PortDeviceObject, 249 IN ULONG PortNumber 250 ); 251 252 NTSTATUS 253 NTAPI 254 ScsiCdRomOpenClose( 255 IN PDEVICE_OBJECT DeviceObject, 256 IN PIRP Irp 257 ); 258 259 NTSTATUS 260 NTAPI 261 ScsiCdRomReadVerification( 262 IN PDEVICE_OBJECT DeviceObject, 263 IN PIRP Irp 264 ); 265 266 NTSTATUS 267 NTAPI 268 ScsiCdRomSwitchMode( 269 IN PDEVICE_OBJECT DeviceObject, 270 IN ULONG SectorSize, 271 IN PIRP OriginalRequest 272 ); 273 274 NTSTATUS 275 NTAPI 276 CdRomDeviceControl( 277 IN PDEVICE_OBJECT DeviceObject, 278 IN PIRP Irp 279 ); 280 281 IO_COMPLETION_ROUTINE CdRomDeviceControlCompletion; 282 NTSTATUS 283 NTAPI 284 CdRomDeviceControlCompletion( 285 IN PDEVICE_OBJECT DeviceObject, 286 IN PIRP Irp, 287 IN PVOID Context 288 ); 289 290 IO_COMPLETION_ROUTINE CdRomSetVolumeIntermediateCompletion; 291 NTSTATUS 292 NTAPI 293 CdRomSetVolumeIntermediateCompletion( 294 IN PDEVICE_OBJECT DeviceObject, 295 IN PIRP Irp, 296 IN PVOID Context 297 ); 298 299 IO_COMPLETION_ROUTINE CdRomSwitchModeCompletion; 300 NTSTATUS 301 NTAPI 302 CdRomSwitchModeCompletion( 303 IN PDEVICE_OBJECT DeviceObject, 304 IN PIRP Irp, 305 IN PVOID Context 306 ); 307 308 IO_COMPLETION_ROUTINE CdRomXACompletion; 309 NTSTATUS 310 NTAPI 311 CdRomXACompletion( 312 IN PDEVICE_OBJECT DeviceObject, 313 IN PIRP Irp, 314 IN PVOID Context 315 ); 316 317 IO_COMPLETION_ROUTINE CdRomClassIoctlCompletion; 318 NTSTATUS 319 NTAPI 320 CdRomClassIoctlCompletion( 321 IN PDEVICE_OBJECT DeviceObject, 322 IN PIRP Irp, 323 IN PVOID Context 324 ); 325 326 VOID 327 NTAPI 328 ScsiCdRomStartIo( 329 IN PDEVICE_OBJECT DeviceObject, 330 IN PIRP Irp 331 ); 332 333 VOID 334 NTAPI 335 CdRomTickHandler( 336 IN PDEVICE_OBJECT DeviceObject, 337 IN PVOID Context 338 ); 339 340 BOOLEAN 341 NTAPI 342 CdRomCheckRegistryForMediaChangeValue( 343 IN PUNICODE_STRING RegistryPath, 344 IN ULONG DeviceNumber 345 ); 346 347 NTSTATUS 348 NTAPI 349 CdRomUpdateCapacity( 350 IN PDEVICE_EXTENSION DeviceExtension, 351 IN PIRP IrpToComplete, 352 IN OPTIONAL PKEVENT IoctlEvent 353 ); 354 355 NTSTATUS 356 NTAPI 357 CreateCdRomDeviceObject( 358 IN PDRIVER_OBJECT DriverObject, 359 IN PDEVICE_OBJECT PortDeviceObject, 360 IN ULONG PortNumber, 361 IN PULONG DeviceCount, 362 PIO_SCSI_CAPABILITIES PortCapabilities, 363 IN PSCSI_INQUIRY_DATA LunInfo, 364 IN PCLASS_INIT_DATA InitializationData, 365 IN PUNICODE_STRING RegistryPath 366 ); 367 368 VOID 369 NTAPI 370 ScanForSpecial( 371 PDEVICE_OBJECT DeviceObject, 372 PINQUIRYDATA InquiryData, 373 PIO_SCSI_CAPABILITIES PortCapabilities 374 ); 375 376 BOOLEAN 377 NTAPI 378 CdRomIsPlayActive( 379 IN PDEVICE_OBJECT DeviceObject 380 ); 381 382 VOID 383 NTAPI 384 HitachProcessError( 385 PDEVICE_OBJECT DeviceObject, 386 PSCSI_REQUEST_BLOCK Srb, 387 NTSTATUS *Status, 388 BOOLEAN *Retry 389 ); 390 391 IO_COMPLETION_ROUTINE ToshibaProcessErrorCompletion; 392 VOID 393 NTAPI 394 ToshibaProcessError( 395 PDEVICE_OBJECT DeviceObject, 396 PSCSI_REQUEST_BLOCK Srb, 397 NTSTATUS *Status, 398 BOOLEAN *Retry 399 ); 400 401 BOOLEAN 402 NTAPI 403 IsThisAnAtapiChanger( 404 IN PDEVICE_OBJECT DeviceObject, 405 OUT PULONG DiscsPresent 406 ); 407 408 BOOLEAN 409 NTAPI 410 IsThisASanyo( 411 IN PDEVICE_OBJECT DeviceObject, 412 IN UCHAR PathId, 413 IN UCHAR TargetId 414 ); 415 416 BOOLEAN 417 NTAPI 418 IsThisAMultiLunDevice( 419 IN PDEVICE_OBJECT DeviceObject, 420 IN PDEVICE_OBJECT PortDeviceObject 421 ); 422 423 VOID 424 NTAPI 425 CdRomCreateNamedEvent( 426 IN PDEVICE_EXTENSION DeviceExtension, 427 IN ULONG DeviceNumber 428 ); 429 430 #ifdef _PPC_ 431 NTSTATUS 432 FindScsiAdapter ( 433 IN HANDLE KeyHandle, 434 IN UNICODE_STRING ScsiUnicodeString[], 435 OUT PUCHAR IntermediateController 436 ); 437 #endif 438 439 #ifdef ALLOC_PRAGMA 440 #pragma alloc_text(PAGE, DriverEntry) 441 #pragma alloc_text(PAGE, ScsiCdRomFindDevices) 442 #pragma alloc_text(PAGE, CreateCdRomDeviceObject) 443 #pragma alloc_text(PAGE, ScanForSpecial) 444 //#pragma alloc_text(PAGE, CdRomDeviceControl) 445 #pragma alloc_text(PAGE, HitachProcessError) 446 #pragma alloc_text(PAGE, CdRomIsPlayActive) 447 #pragma alloc_text(PAGE, ScsiCdRomReadVerification) 448 #pragma alloc_text(INIT, CdRomCheckRegistryForMediaChangeValue) 449 #pragma alloc_text(INIT, IsThisAnAtapiChanger) 450 #pragma alloc_text(INIT, IsThisASanyo) 451 #pragma alloc_text(INIT, IsThisAMultiLunDevice) 452 #pragma alloc_text(INIT, CdRomCreateNamedEvent) 453 #ifdef _PPC_ 454 #pragma alloc_text(PAGE, FindScsiAdapter) 455 #endif 456 #endif 457 458 ULONG NoLoad = 0; 459 460 NTSTATUS 461 NTAPI 462 DriverEntry( 463 IN PDRIVER_OBJECT DriverObject, 464 IN PUNICODE_STRING RegistryPath 465 ) 466 467 /*++ 468 469 Routine Description: 470 471 This routine initializes the cdrom class driver. 472 473 Arguments: 474 475 DriverObject - Pointer to driver object created by system. 476 477 RegistryPath - Pointer to the name of the services node for this driver. 478 479 Return Value: 480 481 The function value is the final status from the initialization operation. 482 483 --*/ 484 485 { 486 CLASS_INIT_DATA InitializationData; 487 488 if(NoLoad) { 489 return STATUS_NO_SUCH_DEVICE; 490 } 491 492 // 493 // Zero InitData 494 // 495 496 RtlZeroMemory (&InitializationData, sizeof(CLASS_INIT_DATA)); 497 498 // 499 // Set sizes 500 // 501 502 InitializationData.InitializationDataSize = sizeof(CLASS_INIT_DATA); 503 InitializationData.DeviceExtensionSize = DEVICE_EXTENSION_SIZE; 504 505 InitializationData.DeviceType = FILE_DEVICE_CD_ROM; 506 InitializationData.DeviceCharacteristics = FILE_REMOVABLE_MEDIA | FILE_READ_ONLY_DEVICE; 507 508 // 509 // Set entry points 510 // 511 512 InitializationData.ClassReadWriteVerification = ScsiCdRomReadVerification; 513 InitializationData.ClassDeviceControl = CdRomDeviceControl; 514 InitializationData.ClassFindDevices = ScsiCdRomFindDevices; 515 InitializationData.ClassShutdownFlush = NULL; 516 InitializationData.ClassCreateClose = NULL; 517 InitializationData.ClassStartIo = ScsiCdRomStartIo; 518 519 // 520 // Call the class init routine 521 // 522 523 return ScsiClassInitialize( DriverObject, RegistryPath, &InitializationData); 524 525 } // end DriverEntry() 526 527 BOOLEAN 528 NTAPI 529 ScsiCdRomFindDevices( 530 IN PDRIVER_OBJECT DriverObject, 531 IN PUNICODE_STRING RegistryPath, 532 IN PCLASS_INIT_DATA InitializationData, 533 IN PDEVICE_OBJECT PortDeviceObject, 534 IN ULONG PortNumber 535 ) 536 537 /*++ 538 539 Routine Description: 540 541 Connect to SCSI port driver. Get adapter capabilities and 542 SCSI bus configuration information. Search inquiry data 543 for CDROM devices to process. 544 545 Arguments: 546 547 DriverObject - CDROM class driver object. 548 PortDeviceObject - SCSI port driver device object. 549 PortNumber - The system ordinal for this scsi adapter. 550 551 Return Value: 552 553 TRUE if CDROM device present on this SCSI adapter. 554 555 --*/ 556 557 { 558 PIO_SCSI_CAPABILITIES portCapabilities; 559 PULONG cdRomCount; 560 PCHAR buffer; 561 PSCSI_INQUIRY_DATA lunInfo; 562 PSCSI_ADAPTER_BUS_INFO adapterInfo; 563 PINQUIRYDATA inquiryData; 564 ULONG scsiBus; 565 NTSTATUS status; 566 BOOLEAN foundDevice = FALSE; 567 568 // 569 // Call port driver to get adapter capabilities. 570 // 571 572 status = ScsiClassGetCapabilities(PortDeviceObject, &portCapabilities); 573 574 if (!NT_SUCCESS(status)) { 575 DebugPrint((1,"FindScsiDevices: ScsiClassGetCapabilities failed\n")); 576 return foundDevice; 577 } 578 579 // 580 // Call port driver to get inquiry information to find cdroms. 581 // 582 583 status = ScsiClassGetInquiryData(PortDeviceObject, (PSCSI_ADAPTER_BUS_INFO *) &buffer); 584 585 if (!NT_SUCCESS(status)) { 586 DebugPrint((1,"FindScsiDevices: ScsiClassGetInquiryData failed\n")); 587 return foundDevice; 588 } 589 590 // 591 // Get the address of the count of the number of cdroms already initialized. 592 // 593 594 cdRomCount = &IoGetConfigurationInformation()->CdRomCount; 595 adapterInfo = (PVOID) buffer; 596 597 // 598 // For each SCSI bus this adapter supports ... 599 // 600 601 for (scsiBus=0; scsiBus < adapterInfo->NumberOfBuses; scsiBus++) { 602 603 // 604 // Get the SCSI bus scan data for this bus. 605 // 606 607 lunInfo = (PVOID) (buffer + adapterInfo->BusData[scsiBus].InquiryDataOffset); 608 609 // 610 // Search list for unclaimed disk devices. 611 // 612 613 while (adapterInfo->BusData[scsiBus].InquiryDataOffset) { 614 615 inquiryData = (PVOID)lunInfo->InquiryData; 616 617 if ((inquiryData->DeviceType == READ_ONLY_DIRECT_ACCESS_DEVICE) && 618 (inquiryData->DeviceTypeQualifier == 0) && 619 (!lunInfo->DeviceClaimed)) { 620 621 DebugPrint((1,"FindScsiDevices: Vendor string is %.24s\n", 622 inquiryData->VendorId)); 623 624 // 625 // Create device objects for cdrom 626 // 627 628 status = CreateCdRomDeviceObject(DriverObject, 629 PortDeviceObject, 630 PortNumber, 631 cdRomCount, 632 portCapabilities, 633 lunInfo, 634 InitializationData, 635 RegistryPath); 636 637 if (NT_SUCCESS(status)) { 638 639 // 640 // Increment system cdrom device count. 641 // 642 643 (*cdRomCount)++; 644 645 // 646 // Indicate that a cdrom device was found. 647 // 648 649 foundDevice = TRUE; 650 } 651 } 652 653 // 654 // Get next LunInfo. 655 // 656 657 if (lunInfo->NextInquiryDataOffset == 0) { 658 break; 659 } 660 661 lunInfo = (PVOID) (buffer + lunInfo->NextInquiryDataOffset); 662 } 663 } 664 665 ExFreePool(buffer); 666 667 668 return foundDevice; 669 670 } // end FindScsiCdRoms() 671 672 VOID 673 NTAPI 674 CdRomCreateNamedEvent( 675 IN PDEVICE_EXTENSION DeviceExtension, 676 IN ULONG DeviceNumber 677 ) 678 679 /*++ 680 681 Routine Description: 682 683 Create the named synchronization event for notification of media change 684 events to the system. The event is reset before this function returns. 685 686 Arguments: 687 688 DeviceExtension - the device extension pointer for storage of the event pointer. 689 690 Return Value: 691 692 None. 693 694 --*/ 695 696 { 697 UNICODE_STRING unicodeString; 698 OBJECT_ATTRIBUTES objectAttributes; 699 CCHAR eventNameBuffer[MAXIMUM_FILENAME_LENGTH]; 700 STRING eventNameString; 701 HANDLE handle; 702 NTSTATUS status; 703 704 705 sprintf(eventNameBuffer,"\\Device\\MediaChangeEvent%ld", 706 DeviceNumber); 707 708 RtlInitString(&eventNameString, 709 eventNameBuffer); 710 711 status = RtlAnsiStringToUnicodeString(&unicodeString, 712 &eventNameString, 713 TRUE); 714 715 if (!NT_SUCCESS(status)) { 716 return; 717 } 718 719 InitializeObjectAttributes(&objectAttributes, 720 &unicodeString, 721 OBJ_PERMANENT | OBJ_CASE_INSENSITIVE | OBJ_OPENIF, 722 NULL, 723 NULL); 724 725 DeviceExtension->MediaChangeEvent = IoCreateSynchronizationEvent(&unicodeString, 726 &handle); 727 DeviceExtension->MediaChangeEventHandle = handle; 728 729 KeClearEvent(DeviceExtension->MediaChangeEvent); 730 731 RtlFreeUnicodeString(&unicodeString); 732 } 733 734 NTSTATUS 735 NTAPI 736 CreateCdRomDeviceObject( 737 IN PDRIVER_OBJECT DriverObject, 738 IN PDEVICE_OBJECT PortDeviceObject, 739 IN ULONG PortNumber, 740 IN PULONG DeviceCount, 741 IN PIO_SCSI_CAPABILITIES PortCapabilities, 742 IN PSCSI_INQUIRY_DATA LunInfo, 743 IN PCLASS_INIT_DATA InitializationData, 744 IN PUNICODE_STRING RegistryPath 745 ) 746 747 /*++ 748 749 Routine Description: 750 751 This routine creates an object for the device and then calls the 752 SCSI port driver for media capacity and sector size. 753 754 Arguments: 755 756 DriverObject - Pointer to driver object created by system. 757 PortDeviceObject - to connect to SCSI port driver. 758 DeviceCount - Number of previously installed CDROMs. 759 PortCapabilities - Pointer to structure returned by SCSI port 760 driver describing adapter capabilities (and limitations). 761 LunInfo - Pointer to configuration information for this device. 762 763 Return Value: 764 765 NTSTATUS 766 767 --*/ 768 { 769 CHAR ntNameBuffer[64]; 770 NTSTATUS status; 771 BOOLEAN changerDevice; 772 SCSI_REQUEST_BLOCK srb; 773 ULONG length; 774 PCDROM_DATA cddata; 775 PCDB cdb; 776 PVOID senseData = NULL; 777 PDEVICE_OBJECT deviceObject = NULL; 778 PDEVICE_EXTENSION deviceExtension = NULL; 779 PUCHAR buffer; 780 ULONG bps; 781 ULONG lastBit; 782 ULONG timeOut; 783 BOOLEAN srbListInitialized = FALSE; 784 785 // 786 // Claim the device. Note that any errors after this 787 // will goto the generic handler, where the device will 788 // be released. 789 // 790 791 status = ScsiClassClaimDevice(PortDeviceObject, 792 LunInfo, 793 FALSE, 794 &PortDeviceObject); 795 796 if (!NT_SUCCESS(status)) { 797 return(status); 798 } 799 800 // 801 // Create device object for this device. 802 // 803 804 sprintf(ntNameBuffer, 805 "\\Device\\CdRom%lu", 806 *DeviceCount); 807 808 status = ScsiClassCreateDeviceObject(DriverObject, 809 ntNameBuffer, 810 NULL, 811 &deviceObject, 812 InitializationData); 813 814 if (!NT_SUCCESS(status)) { 815 DebugPrint((1,"CreateCdRomDeviceObjects: Can not create device %s\n", 816 ntNameBuffer)); 817 818 goto CreateCdRomDeviceObjectExit; 819 } 820 821 // 822 // Indicate that IRPs should include MDLs. 823 // 824 825 deviceObject->Flags |= DO_DIRECT_IO; 826 827 // 828 // Set up required stack size in device object. 829 // 830 831 deviceObject->StackSize = PortDeviceObject->StackSize + 2; 832 833 deviceExtension = deviceObject->DeviceExtension; 834 835 // 836 // Allocate spinlock for split request completion. 837 // 838 839 KeInitializeSpinLock(&deviceExtension->SplitRequestSpinLock); 840 841 // 842 // This is the physical device. 843 // 844 845 deviceExtension->PhysicalDevice = deviceObject; 846 847 // 848 // Initialize lock count to zero. The lock count is used to 849 // disable the ejection mechanism when media is mounted. 850 // 851 852 deviceExtension->LockCount = 0; 853 854 // 855 // Save system cdrom number 856 // 857 858 deviceExtension->DeviceNumber = *DeviceCount; 859 860 // 861 // Copy port device object to device extension. 862 // 863 864 deviceExtension->PortDeviceObject = PortDeviceObject; 865 866 // 867 // Set the alignment requirements for the device based on the 868 // host adapter requirements 869 // 870 871 if (PortDeviceObject->AlignmentRequirement > deviceObject->AlignmentRequirement) { 872 deviceObject->AlignmentRequirement = PortDeviceObject->AlignmentRequirement; 873 } 874 875 // 876 // Save address of port driver capabilities. 877 // 878 879 deviceExtension->PortCapabilities = PortCapabilities; 880 881 // 882 // Clear SRB flags. 883 // 884 885 deviceExtension->SrbFlags = 0; 886 deviceExtension->SrbFlags |= SRB_FLAGS_DISABLE_SYNCH_TRANSFER; 887 888 // 889 // Allocate request sense buffer. 890 // 891 892 senseData = ExAllocatePool(NonPagedPoolCacheAligned, SENSE_BUFFER_SIZE); 893 894 if (senseData == NULL) { 895 896 // 897 // The buffer cannot be allocated. 898 // 899 900 status = STATUS_INSUFFICIENT_RESOURCES; 901 goto CreateCdRomDeviceObjectExit; 902 } 903 904 // 905 // Set the sense data pointer in the device extension. 906 // 907 908 deviceExtension->SenseData = senseData; 909 910 // 911 // CDROMs are not partitionable so starting offset is 0. 912 // 913 914 deviceExtension->StartingOffset.LowPart = 0; 915 deviceExtension->StartingOffset.HighPart = 0; 916 917 // 918 // Path/TargetId/LUN describes a device location on the SCSI bus. 919 // This information comes from the LunInfo buffer. 920 // 921 922 deviceExtension->PortNumber = (UCHAR)PortNumber; 923 deviceExtension->PathId = LunInfo->PathId; 924 deviceExtension->TargetId = LunInfo->TargetId; 925 deviceExtension->Lun = LunInfo->Lun; 926 927 // 928 // Set timeout value in seconds. 929 // 930 931 timeOut = ScsiClassQueryTimeOutRegistryValue(RegistryPath); 932 if (timeOut) { 933 deviceExtension->TimeOutValue = timeOut; 934 } else { 935 deviceExtension->TimeOutValue = SCSI_CDROM_TIMEOUT; 936 } 937 938 // 939 // Build the lookaside list for srb's for the physical disk. Should only 940 // need a couple. 941 // 942 943 ScsiClassInitializeSrbLookasideList(deviceExtension, 944 CDROM_SRB_LIST_SIZE); 945 946 srbListInitialized = TRUE; 947 948 // 949 // Back pointer to device object. 950 // 951 952 deviceExtension->DeviceObject = deviceObject; 953 954 // 955 // Allocate buffer for drive geometry. 956 // 957 958 deviceExtension->DiskGeometry = 959 ExAllocatePool(NonPagedPool, sizeof(DISK_GEOMETRY_EX)); 960 961 if (deviceExtension->DiskGeometry == NULL) { 962 963 status = STATUS_INSUFFICIENT_RESOURCES; 964 goto CreateCdRomDeviceObjectExit; 965 } 966 967 // 968 // Set up media change support defaults. 969 // 970 971 cddata = (PCDROM_DATA)(deviceExtension + 1); 972 973 KeInitializeSpinLock(&cddata->FormSpinLock); 974 KeInitializeSpinLock(&cddata->TimerIrpSpinLock); 975 InitializeListHead(&cddata->TimerIrpList); 976 977 cddata->MediaChangeCountDown = MEDIA_CHANGE_DEFAULT_TIME; 978 cddata->MediaChangeSupported = FALSE; 979 cddata->MediaChange = FALSE; 980 981 // 982 // Assume that there is initially no media in the device 983 // only notify upper layers if there is something there 984 // 985 986 deviceExtension->MediaChangeNoMedia = TRUE; 987 cddata->MediaChangeIrp = NULL; 988 #if DBG 989 cddata->MediaChangeIrpTimeInUse = 0; 990 cddata->MediaChangeIrpLost = FALSE; 991 #endif 992 993 // 994 // Scan for Scsi controllers that require special processing. 995 // 996 997 ScanForSpecial(deviceObject, 998 (PINQUIRYDATA) LunInfo->InquiryData, 999 PortCapabilities); 1000 1001 // 1002 // Do READ CAPACITY. This SCSI command 1003 // returns the last sector address on the device 1004 // and the bytes per sector. 1005 // These are used to calculate the drive capacity 1006 // in bytes. 1007 // 1008 1009 status = ScsiClassReadDriveCapacity(deviceObject); 1010 bps = deviceExtension->DiskGeometry->Geometry.BytesPerSector; 1011 1012 if (!NT_SUCCESS(status) || !bps) { 1013 1014 DebugPrint((1, 1015 "CreateCdRomDeviceObjects: Can't read capacity for device %s\n", 1016 ntNameBuffer)); 1017 1018 // 1019 // Set disk geometry to default values (per ISO 9660). 1020 // 1021 1022 bps = 2048; 1023 deviceExtension->SectorShift = 11; 1024 deviceExtension->PartitionLength.QuadPart = (LONGLONG)(0x7fffffff); 1025 } else { 1026 1027 // 1028 // Insure that bytes per sector is a power of 2 1029 // This corrects a problem with the HP 4020i CDR where it 1030 // returns an incorrect number for bytes per sector. 1031 // 1032 1033 lastBit = (ULONG) -1; 1034 while (bps) { 1035 lastBit++; 1036 bps = bps >> 1; 1037 } 1038 1039 bps = 1 << lastBit; 1040 } 1041 deviceExtension->DiskGeometry->Geometry.BytesPerSector = bps; 1042 DebugPrint((2, "CreateCdRomDeviceObject: Calc'd bps = %x\n", bps)); 1043 1044 // 1045 // Check to see if this is some sort of changer device 1046 // 1047 1048 changerDevice = FALSE; 1049 1050 // 1051 // Search for devices that have special requirements for media 1052 // change support. 1053 // 1054 1055 if (deviceExtension->Lun > 0) { 1056 changerDevice = TRUE; 1057 } 1058 1059 if (!changerDevice) { 1060 changerDevice = IsThisASanyo(deviceObject, deviceExtension->PathId, 1061 deviceExtension->TargetId); 1062 } 1063 1064 if (!changerDevice) { 1065 ULONG tmp; 1066 changerDevice = IsThisAnAtapiChanger(deviceObject, &tmp); 1067 } 1068 1069 if (!changerDevice) { 1070 changerDevice = IsThisAMultiLunDevice(deviceObject, PortDeviceObject); 1071 } 1072 1073 // 1074 // If it is a changer device, increment the timeout to take platter-swapping 1075 // time into account 1076 // 1077 1078 if(changerDevice) { 1079 deviceExtension->TimeOutValue += SCSI_CHANGER_BONUS_TIMEOUT; 1080 } 1081 1082 // 1083 // Create the media change named event. If this succeeds then continue 1084 // initializing the media change support data items. 1085 // 1086 1087 CdRomCreateNamedEvent(deviceExtension,*DeviceCount); 1088 if (deviceExtension->MediaChangeEvent) { 1089 1090 // 1091 // If this is not a changer, get an IRP for the timer request 1092 // and initialize the timer. 1093 // 1094 1095 if (!changerDevice) { 1096 1097 // 1098 // Not a changer device - continue with media change initialization. 1099 // Determine if the user actually wants media change events. 1100 // 1101 1102 if (CdRomCheckRegistryForMediaChangeValue(RegistryPath, *DeviceCount)) { 1103 PIO_STACK_LOCATION irpStack; 1104 PSCSI_REQUEST_BLOCK srb; 1105 PIRP irp; 1106 1107 // 1108 // User wants it - preallocate IRP and SRB. 1109 // 1110 1111 irp = IoAllocateIrp((CCHAR)(deviceObject->StackSize+1), 1112 FALSE); 1113 if (irp) { 1114 PVOID buffer; 1115 1116 srb = ExAllocatePool(NonPagedPool, sizeof(SCSI_REQUEST_BLOCK)); 1117 buffer = ExAllocatePool(NonPagedPoolCacheAligned, SENSE_BUFFER_SIZE); 1118 1119 if (srb && buffer) { 1120 PCDB cdb; 1121 1122 // 1123 // All resources have been allocated set up the IRP. 1124 // 1125 1126 IoSetNextIrpStackLocation(irp); 1127 irpStack = IoGetCurrentIrpStackLocation(irp); 1128 irpStack->DeviceObject = deviceObject; 1129 irpStack = IoGetNextIrpStackLocation(irp); 1130 cddata->MediaChangeIrp = irp; 1131 irpStack->Parameters.Scsi.Srb = srb; 1132 1133 // 1134 // Initialize the SRB 1135 // 1136 1137 RtlZeroMemory(srb, sizeof(SCSI_REQUEST_BLOCK)); 1138 1139 srb->CdbLength = 6; 1140 srb->TimeOutValue = deviceExtension->TimeOutValue * 2; 1141 srb->QueueTag = SP_UNTAGGED; 1142 srb->QueueAction = SRB_SIMPLE_TAG_REQUEST; 1143 srb->Length = SCSI_REQUEST_BLOCK_SIZE; 1144 srb->PathId = deviceExtension->PathId; 1145 srb->TargetId = deviceExtension->TargetId; 1146 srb->Lun = deviceExtension->Lun; 1147 srb->Function = SRB_FUNCTION_EXECUTE_SCSI; 1148 1149 // 1150 // Initialize and set up the sense information buffer 1151 // 1152 1153 RtlZeroMemory(buffer, SENSE_BUFFER_SIZE); 1154 srb->SenseInfoBuffer = buffer; 1155 srb->SenseInfoBufferLength = SENSE_BUFFER_SIZE; 1156 1157 // 1158 // Initialize the CDB 1159 // 1160 1161 cdb = (PCDB)&srb->Cdb[0]; 1162 cdb->CDB6GENERIC.OperationCode = SCSIOP_TEST_UNIT_READY; 1163 cdb->CDB6GENERIC.LogicalUnitNumber = deviceExtension->Lun; 1164 1165 // 1166 // It is ok to support media change events on this device. 1167 // 1168 1169 cddata->MediaChangeSupported = TRUE; 1170 cddata->MediaChange = TRUE; 1171 1172 } else { 1173 1174 if (srb) { 1175 ExFreePool(srb); 1176 } 1177 if (buffer) { 1178 ExFreePool(buffer); 1179 } 1180 IoFreeIrp(irp); 1181 } 1182 } 1183 } else { 1184 deviceExtension->MediaChangeEvent = NULL; 1185 } 1186 } else { 1187 deviceExtension->MediaChangeEvent = NULL; 1188 } 1189 } 1190 1191 // 1192 // Assume use of 6-byte mode sense/select for now. 1193 // 1194 1195 cddata->XAFlags |= XA_USE_6_BYTE; 1196 1197 // 1198 // Build and issue mode sense with Read error recovery page. This will be used to change 1199 // block size in case of any raw reads (Mode 2, Form 2). 1200 // 1201 1202 length = (sizeof(MODE_READ_RECOVERY_PAGE) + MODE_BLOCK_DESC_LENGTH + MODE_HEADER_LENGTH); 1203 1204 RtlZeroMemory(&srb, sizeof(SCSI_REQUEST_BLOCK)); 1205 1206 srb.CdbLength = 6; 1207 cdb = (PCDB)srb.Cdb; 1208 1209 // 1210 // Set timeout value from device extension. 1211 // 1212 1213 srb.TimeOutValue = deviceExtension->TimeOutValue; 1214 1215 // 1216 // Build the MODE SENSE CDB. The data returned will be kept in the device extension 1217 // and used to set block size. 1218 // 1219 1220 cdb->MODE_SENSE.OperationCode = SCSIOP_MODE_SENSE; 1221 cdb->MODE_SENSE.PageCode = 0x1; 1222 cdb->MODE_SENSE.AllocationLength = (UCHAR)length; 1223 1224 buffer = ExAllocatePool(NonPagedPoolCacheAligned, (sizeof(MODE_READ_RECOVERY_PAGE) + MODE_BLOCK_DESC_LENGTH + MODE_HEADER_LENGTH10)); 1225 if (!buffer) { 1226 status = STATUS_INSUFFICIENT_RESOURCES; 1227 goto CreateCdRomDeviceObjectExit; 1228 } 1229 1230 status = ScsiClassSendSrbSynchronous(deviceObject, 1231 &srb, 1232 buffer, 1233 length, 1234 FALSE); 1235 if (!NT_SUCCESS(status)) { 1236 1237 // 1238 // May be Atapi, try 10-byte. 1239 // 1240 1241 length = (sizeof(MODE_READ_RECOVERY_PAGE) + MODE_BLOCK_DESC_LENGTH + MODE_HEADER_LENGTH10); 1242 1243 RtlZeroMemory(&srb, sizeof(SCSI_REQUEST_BLOCK)); 1244 1245 // 1246 // Build the MODE SENSE CDB. 1247 // 1248 1249 srb.CdbLength = 10; 1250 cdb = (PCDB)srb.Cdb; 1251 1252 // 1253 // Set timeout value from device extension. 1254 // 1255 1256 srb.TimeOutValue = deviceExtension->TimeOutValue; 1257 1258 cdb->MODE_SENSE10.OperationCode = SCSIOP_MODE_SENSE10; 1259 cdb->MODE_SENSE10.PageCode = 0x1; 1260 1261 cdb->MODE_SENSE10.AllocationLength[0] = (UCHAR)(length >> 8); 1262 cdb->MODE_SENSE10.AllocationLength[1] = (UCHAR)(length & 0xFF); 1263 1264 status = ScsiClassSendSrbSynchronous(deviceObject, 1265 &srb, 1266 buffer, 1267 length, 1268 FALSE); 1269 if (status == STATUS_DATA_OVERRUN) { 1270 1271 // 1272 // Build and issue the ReadCd command to ensure that this device supports it. 1273 // 1274 1275 RtlZeroMemory(cdb, 12); 1276 1277 cdb->READ_CD.OperationCode = SCSIOP_READ_CD; 1278 1279 status = ScsiClassSendSrbSynchronous(deviceObject, 1280 &srb, 1281 NULL, 1282 0, 1283 FALSE); 1284 1285 // 1286 // If the command wasn't rejected then support the READ_CD. 1287 // 1288 1289 if (NT_SUCCESS(status) || (status == STATUS_NO_MEDIA_IN_DEVICE)) { 1290 1291 // 1292 // Using Read CD precludes issuing a mode select to 1293 // set the user data size. So, no buffer copy is 1294 // necessary. 1295 // 1296 1297 cddata->XAFlags &= ~XA_USE_6_BYTE; 1298 cddata->XAFlags |= XA_USE_READ_CD | XA_USE_10_BYTE; 1299 } else { 1300 1301 RtlCopyMemory(&cddata->u1.Header, buffer, sizeof(ERROR_RECOVERY_DATA10)); 1302 cddata->u1.Header.ModeDataLength = 0; 1303 1304 cddata->XAFlags &= ~XA_USE_6_BYTE; 1305 cddata->XAFlags |= XA_USE_10_BYTE; 1306 } 1307 1308 } else if (NT_SUCCESS(status)) { 1309 1310 RtlCopyMemory(&cddata->u1.Header, buffer, sizeof(ERROR_RECOVERY_DATA10)); 1311 cddata->u1.Header.ModeDataLength = 0; 1312 1313 cddata->XAFlags &= ~XA_USE_6_BYTE; 1314 cddata->XAFlags |= XA_USE_10_BYTE; 1315 1316 } else { 1317 cddata->XAFlags |= XA_NOT_SUPPORTED; 1318 } 1319 } else { 1320 RtlCopyMemory(&cddata->u1.Header, buffer, sizeof(ERROR_RECOVERY_DATA)); 1321 cddata->u1.Header.ModeDataLength = 0; 1322 } 1323 1324 ExFreePool(buffer); 1325 1326 // 1327 // Start the timer now regardless of if Autorun is enabled. 1328 // The timer must run forever since IoStopTimer faults. 1329 // 1330 1331 IoInitializeTimer(deviceObject, CdRomTickHandler, NULL); 1332 IoStartTimer(deviceObject); 1333 1334 return(STATUS_SUCCESS); 1335 1336 CreateCdRomDeviceObjectExit: 1337 1338 // 1339 // Release the device since an error occured. 1340 // 1341 1342 ScsiClassClaimDevice(PortDeviceObject, 1343 LunInfo, 1344 TRUE, 1345 NULL); 1346 1347 if (senseData != NULL) { 1348 ExFreePool(senseData); 1349 } 1350 1351 if (deviceExtension->DiskGeometry != NULL) { 1352 ExFreePool(deviceExtension->DiskGeometry); 1353 } 1354 1355 if (deviceObject != NULL) { 1356 if (srbListInitialized) { 1357 ExDeleteNPagedLookasideList(&deviceExtension->SrbLookasideListHead); 1358 } 1359 IoDeleteDevice(deviceObject); 1360 } 1361 1362 1363 return status; 1364 1365 } // end CreateCdRomDeviceObject() 1366 1367 VOID 1368 NTAPI 1369 ScsiCdRomStartIo( 1370 IN PDEVICE_OBJECT DeviceObject, 1371 IN PIRP Irp 1372 ) 1373 { 1374 1375 PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension; 1376 PIO_STACK_LOCATION currentIrpStack = IoGetCurrentIrpStackLocation(Irp); 1377 PIO_STACK_LOCATION nextIrpStack = IoGetNextIrpStackLocation(Irp); 1378 PIO_STACK_LOCATION irpStack; 1379 PIRP irp2 = NULL; 1380 ULONG transferPages; 1381 ULONG transferByteCount = currentIrpStack->Parameters.Read.Length; 1382 ULONG maximumTransferLength = deviceExtension->PortCapabilities->MaximumTransferLength; 1383 PCDROM_DATA cdData; 1384 PSCSI_REQUEST_BLOCK srb = NULL; 1385 PCDB cdb; 1386 PUCHAR senseBuffer = NULL; 1387 PVOID dataBuffer; 1388 NTSTATUS status; 1389 BOOLEAN use6Byte; 1390 1391 // 1392 // Mark IRP with status pending. 1393 // 1394 1395 IoMarkIrpPending(Irp); 1396 1397 // 1398 // If the flag is set in the device object, force a verify. 1399 // 1400 1401 if (DeviceObject->Flags & DO_VERIFY_VOLUME) { 1402 DebugPrint((2, "ScsiCdRomStartIo: [%lx] Volume needs verified\n", Irp)); 1403 if (!(currentIrpStack->Flags & SL_OVERRIDE_VERIFY_VOLUME)) { 1404 1405 if (Irp->Tail.Overlay.Thread) { 1406 IoSetHardErrorOrVerifyDevice(Irp, DeviceObject); 1407 } 1408 1409 Irp->IoStatus.Status = STATUS_VERIFY_REQUIRED; 1410 1411 DebugPrint((2, "ScsiCdRomStartIo: [%lx] Calling UpdateCapacity - " 1412 "ioctl event = %lx\n", 1413 Irp, 1414 nextIrpStack->Parameters.Others.Argument1 1415 )); 1416 1417 // 1418 // our device control dispatch routine stores an event in the next 1419 // stack location to signal when startio has completed. We need to 1420 // pass this in so that the update capacity completion routine can 1421 // set it rather than completing the Irp. 1422 // 1423 1424 status = CdRomUpdateCapacity(deviceExtension, 1425 Irp, 1426 nextIrpStack->Parameters.Others.Argument1 1427 ); 1428 1429 DebugPrint((2, "ScsiCdRomStartIo: [%lx] UpdateCapacity returned %lx\n", Irp, status)); 1430 ASSERT(status == STATUS_PENDING); 1431 return; 1432 } 1433 } 1434 1435 cdData = (PCDROM_DATA)(deviceExtension + 1); 1436 use6Byte = cdData->XAFlags & XA_USE_6_BYTE; 1437 1438 if (currentIrpStack->MajorFunction == IRP_MJ_READ) { 1439 1440 // 1441 // Add partition byte offset to make starting byte relative to 1442 // beginning of disk. In addition, add in skew for DM Driver, if any. 1443 // 1444 1445 currentIrpStack->Parameters.Read.ByteOffset.QuadPart += (deviceExtension->StartingOffset.QuadPart); 1446 1447 // 1448 // Calculate number of pages in this transfer. 1449 // 1450 1451 transferPages = ADDRESS_AND_SIZE_TO_SPAN_PAGES(MmGetMdlVirtualAddress(Irp->MdlAddress), 1452 currentIrpStack->Parameters.Read.Length); 1453 1454 // 1455 // Check if request length is greater than the maximum number of 1456 // bytes that the hardware can transfer. 1457 // 1458 1459 if (cdData->RawAccess) { 1460 1461 ASSERT(!(cdData->XAFlags & XA_USE_READ_CD)); 1462 1463 // 1464 // Fire off a mode select to switch back to cooked sectors. 1465 // 1466 1467 irp2 = IoAllocateIrp((CCHAR)(deviceExtension->DeviceObject->StackSize+1), 1468 FALSE); 1469 1470 if (!irp2) { 1471 Irp->IoStatus.Information = 0; 1472 Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; 1473 IoCompleteRequest(Irp, IO_DISK_INCREMENT); 1474 IoStartNextPacket(DeviceObject, FALSE); 1475 return; 1476 } 1477 1478 srb = ExAllocatePool(NonPagedPool, sizeof(SCSI_REQUEST_BLOCK)); 1479 if (!srb) { 1480 Irp->IoStatus.Information = 0; 1481 Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; 1482 IoCompleteRequest(Irp, IO_DISK_INCREMENT); 1483 IoFreeIrp(irp2); 1484 IoStartNextPacket(DeviceObject, FALSE); 1485 return; 1486 } 1487 1488 RtlZeroMemory(srb, sizeof(SCSI_REQUEST_BLOCK)); 1489 1490 cdb = (PCDB)srb->Cdb; 1491 1492 // 1493 // Allocate sense buffer. 1494 // 1495 1496 senseBuffer = ExAllocatePool(NonPagedPoolCacheAligned, SENSE_BUFFER_SIZE); 1497 1498 if (!senseBuffer) { 1499 Irp->IoStatus.Information = 0; 1500 Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; 1501 IoCompleteRequest(Irp, IO_DISK_INCREMENT); 1502 ExFreePool(srb); 1503 IoFreeIrp(irp2); 1504 IoStartNextPacket(DeviceObject, FALSE); 1505 return; 1506 } 1507 1508 // 1509 // Set up the irp. 1510 // 1511 1512 IoSetNextIrpStackLocation(irp2); 1513 irp2->IoStatus.Status = STATUS_SUCCESS; 1514 irp2->IoStatus.Information = 0; 1515 irp2->Flags = 0; 1516 irp2->UserBuffer = NULL; 1517 1518 // 1519 // Save the device object and irp in a private stack location. 1520 // 1521 1522 irpStack = IoGetCurrentIrpStackLocation(irp2); 1523 irpStack->DeviceObject = deviceExtension->DeviceObject; 1524 irpStack->Parameters.Others.Argument2 = (PVOID) Irp; 1525 1526 // 1527 // The retry count will be in the real Irp, as the retry logic will 1528 // recreate our private irp. 1529 // 1530 1531 if (!(nextIrpStack->Parameters.Others.Argument1)) { 1532 1533 // 1534 // Only jam this in if it doesn't exist. The completion routines can 1535 // call StartIo directly in the case of retries and resetting it will 1536 // cause infinite loops. 1537 // 1538 1539 nextIrpStack->Parameters.Others.Argument1 = (PVOID) MAXIMUM_RETRIES; 1540 } 1541 1542 // 1543 // Construct the IRP stack for the lower level driver. 1544 // 1545 1546 irpStack = IoGetNextIrpStackLocation(irp2); 1547 irpStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL; 1548 irpStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_SCSI_EXECUTE_IN; 1549 irpStack->Parameters.Scsi.Srb = srb; 1550 1551 srb->Length = SCSI_REQUEST_BLOCK_SIZE; 1552 srb->PathId = deviceExtension->PathId; 1553 srb->TargetId = deviceExtension->TargetId; 1554 srb->Lun = deviceExtension->Lun; 1555 srb->Function = SRB_FUNCTION_EXECUTE_SCSI; 1556 srb->Cdb[1] |= deviceExtension->Lun << 5; 1557 srb->SrbStatus = srb->ScsiStatus = 0; 1558 srb->NextSrb = 0; 1559 srb->OriginalRequest = irp2; 1560 srb->SenseInfoBufferLength = SENSE_BUFFER_SIZE; 1561 srb->SenseInfoBuffer = senseBuffer; 1562 1563 transferByteCount = (use6Byte) ? sizeof(ERROR_RECOVERY_DATA) : sizeof(ERROR_RECOVERY_DATA10); 1564 dataBuffer = ExAllocatePool(NonPagedPoolCacheAligned, transferByteCount ); 1565 if (!dataBuffer) { 1566 Irp->IoStatus.Information = 0; 1567 Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; 1568 IoCompleteRequest(Irp, IO_DISK_INCREMENT); 1569 ExFreePool(senseBuffer); 1570 ExFreePool(srb); 1571 IoFreeIrp(irp2); 1572 IoStartNextPacket(DeviceObject, FALSE); 1573 return; 1574 1575 } 1576 1577 irp2->MdlAddress = IoAllocateMdl(dataBuffer, 1578 transferByteCount, 1579 FALSE, 1580 FALSE, 1581 (PIRP) NULL); 1582 1583 if (!irp2->MdlAddress) { 1584 Irp->IoStatus.Information = 0; 1585 Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; 1586 IoCompleteRequest(Irp, IO_DISK_INCREMENT); 1587 ExFreePool(senseBuffer); 1588 ExFreePool(srb); 1589 ExFreePool(dataBuffer); 1590 IoFreeIrp(irp2); 1591 IoStartNextPacket(DeviceObject, FALSE); 1592 return; 1593 } 1594 1595 // 1596 // Prepare the MDL 1597 // 1598 1599 MmBuildMdlForNonPagedPool(irp2->MdlAddress); 1600 1601 srb->DataBuffer = dataBuffer; 1602 1603 // 1604 // Set the new block size in the descriptor. 1605 // 1606 1607 cdData->u1.BlockDescriptor.BlockLength[0] = (UCHAR)(COOKED_SECTOR_SIZE >> 16) & 0xFF; 1608 cdData->u1.BlockDescriptor.BlockLength[1] = (UCHAR)(COOKED_SECTOR_SIZE >> 8) & 0xFF; 1609 cdData->u1.BlockDescriptor.BlockLength[2] = (UCHAR)(COOKED_SECTOR_SIZE & 0xFF); 1610 1611 // 1612 // Move error page into dataBuffer. 1613 // 1614 1615 RtlCopyMemory(srb->DataBuffer, &cdData->u1.Header, transferByteCount); 1616 1617 // 1618 // Build and send a mode select to switch into raw mode. 1619 // 1620 1621 srb->SrbFlags = deviceExtension->SrbFlags; 1622 srb->SrbFlags |= (SRB_FLAGS_DISABLE_SYNCH_TRANSFER | SRB_FLAGS_DATA_OUT); 1623 srb->DataTransferLength = transferByteCount; 1624 srb->TimeOutValue = deviceExtension->TimeOutValue * 2; 1625 1626 if (use6Byte) { 1627 srb->CdbLength = 6; 1628 cdb->MODE_SELECT.OperationCode = SCSIOP_MODE_SELECT; 1629 cdb->MODE_SELECT.PFBit = 1; 1630 cdb->MODE_SELECT.ParameterListLength = (UCHAR)transferByteCount; 1631 } else { 1632 1633 srb->CdbLength = 10; 1634 cdb->MODE_SELECT10.OperationCode = SCSIOP_MODE_SELECT10; 1635 cdb->MODE_SELECT10.PFBit = 1; 1636 cdb->MODE_SELECT10.ParameterListLength[0] = (UCHAR)(transferByteCount >> 8); 1637 cdb->MODE_SELECT10.ParameterListLength[1] = (UCHAR)(transferByteCount & 0xFF); 1638 } 1639 1640 // 1641 // Update completion routine. 1642 // 1643 1644 IoSetCompletionRoutine(irp2, 1645 CdRomSwitchModeCompletion, 1646 srb, 1647 TRUE, 1648 TRUE, 1649 TRUE); 1650 1651 IoCallDriver(deviceExtension->PortDeviceObject, irp2); 1652 return; 1653 } 1654 1655 if ((currentIrpStack->Parameters.Read.Length > maximumTransferLength) || 1656 (transferPages > 1657 deviceExtension->PortCapabilities->MaximumPhysicalPages)) { 1658 1659 // 1660 // Request needs to be split. Completion of each portion of the 1661 // request will fire off the next portion. The final request will 1662 // signal Io to send a new request. 1663 // 1664 1665 transferPages = 1666 deviceExtension->PortCapabilities->MaximumPhysicalPages - 1; 1667 1668 if(maximumTransferLength > transferPages << PAGE_SHIFT) { 1669 maximumTransferLength = transferPages << PAGE_SHIFT; 1670 } 1671 1672 // 1673 // Check that the maximum transfer size is not zero 1674 // 1675 1676 if(maximumTransferLength == 0) { 1677 maximumTransferLength = PAGE_SIZE; 1678 } 1679 1680 ScsiClassSplitRequest(DeviceObject, Irp, maximumTransferLength); 1681 return; 1682 1683 } else { 1684 1685 // 1686 // Build SRB and CDB for this IRP. 1687 // 1688 1689 ScsiClassBuildRequest(DeviceObject, Irp); 1690 1691 } 1692 1693 1694 } else if (currentIrpStack->MajorFunction == IRP_MJ_DEVICE_CONTROL) { 1695 1696 // 1697 // Allocate an irp, srb and associated structures. 1698 // 1699 1700 irp2 = IoAllocateIrp((CCHAR)(deviceExtension->DeviceObject->StackSize+1), 1701 FALSE); 1702 1703 if (!irp2) { 1704 Irp->IoStatus.Information = 0; 1705 Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; 1706 IoCompleteRequest(Irp, IO_DISK_INCREMENT); 1707 IoStartNextPacket(DeviceObject, FALSE); 1708 DebugPrint((2, "ScsiCdRomStartIo: [%lx] bailing with status %lx at line %s\n", Irp, Irp->IoStatus.Status, __LINE__)); 1709 return; 1710 } 1711 1712 srb = ExAllocatePool(NonPagedPool, sizeof(SCSI_REQUEST_BLOCK)); 1713 if (!srb) { 1714 Irp->IoStatus.Information = 0; 1715 Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; 1716 IoCompleteRequest(Irp, IO_DISK_INCREMENT); 1717 IoFreeIrp(irp2); 1718 IoStartNextPacket(DeviceObject, FALSE); 1719 DebugPrint((2, "ScsiCdRomStartIo: [%lx] bailing with status %lx at line %s\n", Irp, Irp->IoStatus.Status, __LINE__)); 1720 return; 1721 } 1722 1723 RtlZeroMemory(srb, sizeof(SCSI_REQUEST_BLOCK)); 1724 1725 cdb = (PCDB)srb->Cdb; 1726 1727 // 1728 // Allocate sense buffer. 1729 // 1730 1731 senseBuffer = ExAllocatePool(NonPagedPoolCacheAligned, SENSE_BUFFER_SIZE); 1732 1733 if (!senseBuffer) { 1734 Irp->IoStatus.Information = 0; 1735 Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; 1736 IoCompleteRequest(Irp, IO_DISK_INCREMENT); 1737 ExFreePool(srb); 1738 IoFreeIrp(irp2); 1739 IoStartNextPacket(DeviceObject, FALSE); 1740 DebugPrint((2, "ScsiCdRomStartIo: [%lx] bailing with status %lx at line %s\n", Irp, Irp->IoStatus.Status, __LINE__)); 1741 return; 1742 } 1743 1744 // 1745 // Set up the irp. 1746 // 1747 1748 IoSetNextIrpStackLocation(irp2); 1749 irp2->IoStatus.Status = STATUS_SUCCESS; 1750 irp2->IoStatus.Information = 0; 1751 irp2->Flags = 0; 1752 irp2->UserBuffer = NULL; 1753 1754 // 1755 // Save the device object and irp in a private stack location. 1756 // 1757 1758 irpStack = IoGetCurrentIrpStackLocation(irp2); 1759 irpStack->DeviceObject = deviceExtension->DeviceObject; 1760 irpStack->Parameters.Others.Argument2 = (PVOID) Irp; 1761 1762 // 1763 // The retry count will be in the real Irp, as the retry logic will 1764 // recreate our private irp. 1765 // 1766 1767 if (!(nextIrpStack->Parameters.Others.Argument1)) { 1768 1769 // 1770 // Only jam this in if it doesn't exist. The completion routines can 1771 // call StartIo directly in the case of retries and resetting it will 1772 // cause infinite loops. 1773 // 1774 1775 nextIrpStack->Parameters.Others.Argument1 = (PVOID) MAXIMUM_RETRIES; 1776 } 1777 1778 // 1779 // Construct the IRP stack for the lower level driver. 1780 // 1781 1782 irpStack = IoGetNextIrpStackLocation(irp2); 1783 irpStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL; 1784 irpStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_SCSI_EXECUTE_IN; 1785 irpStack->Parameters.Scsi.Srb = srb; 1786 1787 IoSetCompletionRoutine(irp2, 1788 CdRomDeviceControlCompletion, 1789 srb, 1790 TRUE, 1791 TRUE, 1792 TRUE); 1793 // 1794 // Setup those fields that are generic to all requests. 1795 // 1796 1797 srb->Length = SCSI_REQUEST_BLOCK_SIZE; 1798 srb->PathId = deviceExtension->PathId; 1799 srb->TargetId = deviceExtension->TargetId; 1800 srb->Lun = deviceExtension->Lun; 1801 srb->Function = SRB_FUNCTION_EXECUTE_SCSI; 1802 srb->Cdb[1] |= deviceExtension->Lun << 5; 1803 srb->SrbStatus = srb->ScsiStatus = 0; 1804 srb->NextSrb = 0; 1805 srb->OriginalRequest = irp2; 1806 srb->SenseInfoBufferLength = SENSE_BUFFER_SIZE; 1807 srb->SenseInfoBuffer = senseBuffer; 1808 1809 switch (currentIrpStack->Parameters.DeviceIoControl.IoControlCode) { 1810 1811 case IOCTL_CDROM_RAW_READ: { 1812 1813 // 1814 // Determine whether the drive is currently in raw or cooked mode, 1815 // and which command to use to read the data. 1816 // 1817 1818 if (!(cdData->XAFlags & XA_USE_READ_CD)) { 1819 1820 PRAW_READ_INFO rawReadInfo = 1821 (PRAW_READ_INFO)currentIrpStack->Parameters.DeviceIoControl.Type3InputBuffer; 1822 ULONG maximumTransferLength; 1823 ULONG transferPages; 1824 1825 if (cdData->RawAccess) { 1826 1827 ULONG startingSector; 1828 1829 // 1830 // Free the recently allocated irp, as we don't need it. 1831 // 1832 1833 IoFreeIrp(irp2); 1834 1835 cdb = (PCDB)srb->Cdb; 1836 RtlZeroMemory(cdb, 12); 1837 1838 // 1839 // Calculate starting offset. 1840 // 1841 1842 startingSector = (ULONG)(rawReadInfo->DiskOffset.QuadPart >> deviceExtension->SectorShift); 1843 transferByteCount = rawReadInfo->SectorCount * RAW_SECTOR_SIZE; 1844 maximumTransferLength = deviceExtension->PortCapabilities->MaximumTransferLength; 1845 transferPages = ADDRESS_AND_SIZE_TO_SPAN_PAGES(MmGetMdlVirtualAddress(Irp->MdlAddress), 1846 transferByteCount); 1847 1848 // 1849 // Determine if request is within limits imposed by miniport. 1850 // 1851 1852 if (transferByteCount > maximumTransferLength || 1853 transferPages > deviceExtension->PortCapabilities->MaximumPhysicalPages) { 1854 1855 // 1856 // The claim is that this won't happen, and is backed up by 1857 // ActiveMovie usage, which does unbuffered XA reads of 0x18000, yet 1858 // we get only 4 sector requests. 1859 // 1860 1861 1862 Irp->IoStatus.Information = 0; 1863 Irp->IoStatus.Status = STATUS_INVALID_PARAMETER; 1864 IoCompleteRequest(Irp, IO_DISK_INCREMENT); 1865 ExFreePool(senseBuffer); 1866 ExFreePool(srb); 1867 IoStartNextPacket(DeviceObject, FALSE); 1868 return; 1869 1870 } 1871 1872 srb->OriginalRequest = Irp; 1873 srb->SrbFlags = deviceExtension->SrbFlags; 1874 srb->SrbFlags |= (SRB_FLAGS_DISABLE_SYNCH_TRANSFER | SRB_FLAGS_DATA_IN); 1875 srb->DataTransferLength = transferByteCount; 1876 srb->TimeOutValue = deviceExtension->TimeOutValue; 1877 srb->CdbLength = 10; 1878 srb->DataBuffer = MmGetMdlVirtualAddress(Irp->MdlAddress); 1879 1880 if (rawReadInfo->TrackMode == CDDA) { 1881 if (cdData->XAFlags & PLEXTOR_CDDA) { 1882 1883 srb->CdbLength = 12; 1884 1885 cdb->PLXTR_READ_CDDA.LogicalUnitNumber = deviceExtension->Lun; 1886 cdb->PLXTR_READ_CDDA.LogicalBlockByte3 = (UCHAR) (startingSector & 0xFF); 1887 cdb->PLXTR_READ_CDDA.LogicalBlockByte2 = (UCHAR) ((startingSector >> 8) & 0xFF); 1888 cdb->PLXTR_READ_CDDA.LogicalBlockByte1 = (UCHAR) ((startingSector >> 16) & 0xFF); 1889 cdb->PLXTR_READ_CDDA.LogicalBlockByte0 = (UCHAR) ((startingSector >> 24) & 0xFF); 1890 1891 cdb->PLXTR_READ_CDDA.TransferBlockByte3 = (UCHAR) (rawReadInfo->SectorCount & 0xFF); 1892 cdb->PLXTR_READ_CDDA.TransferBlockByte2 = (UCHAR) (rawReadInfo->SectorCount >> 8); 1893 cdb->PLXTR_READ_CDDA.TransferBlockByte1 = 0; 1894 cdb->PLXTR_READ_CDDA.TransferBlockByte0 = 0; 1895 1896 cdb->PLXTR_READ_CDDA.SubCode = 0; 1897 cdb->PLXTR_READ_CDDA.OperationCode = 0xD8; 1898 1899 } else if (cdData->XAFlags & NEC_CDDA) { 1900 1901 cdb->NEC_READ_CDDA.LogicalBlockByte3 = (UCHAR) (startingSector & 0xFF); 1902 cdb->NEC_READ_CDDA.LogicalBlockByte2 = (UCHAR) ((startingSector >> 8) & 0xFF); 1903 cdb->NEC_READ_CDDA.LogicalBlockByte1 = (UCHAR) ((startingSector >> 16) & 0xFF); 1904 cdb->NEC_READ_CDDA.LogicalBlockByte0 = (UCHAR) ((startingSector >> 24) & 0xFF); 1905 1906 cdb->NEC_READ_CDDA.TransferBlockByte1 = (UCHAR) (rawReadInfo->SectorCount & 0xFF); 1907 cdb->NEC_READ_CDDA.TransferBlockByte0 = (UCHAR) (rawReadInfo->SectorCount >> 8); 1908 1909 cdb->NEC_READ_CDDA.OperationCode = 0xD4; 1910 } 1911 } else { 1912 1913 cdb->CDB10.LogicalUnitNumber = deviceExtension->Lun; 1914 1915 cdb->CDB10.TransferBlocksMsb = (UCHAR) (rawReadInfo->SectorCount >> 8); 1916 cdb->CDB10.TransferBlocksLsb = (UCHAR) (rawReadInfo->SectorCount & 0xFF); 1917 1918 cdb->CDB10.LogicalBlockByte3 = (UCHAR) (startingSector & 0xFF); 1919 cdb->CDB10.LogicalBlockByte2 = (UCHAR) ((startingSector >> 8) & 0xFF); 1920 cdb->CDB10.LogicalBlockByte1 = (UCHAR) ((startingSector >> 16) & 0xFF); 1921 cdb->CDB10.LogicalBlockByte0 = (UCHAR) ((startingSector >> 24) & 0xFF); 1922 1923 cdb->CDB10.OperationCode = SCSIOP_READ; 1924 } 1925 1926 srb->SrbStatus = srb->ScsiStatus = 0; 1927 1928 nextIrpStack->MajorFunction = IRP_MJ_SCSI; 1929 nextIrpStack->Parameters.Scsi.Srb = srb; 1930 1931 if (!(nextIrpStack->Parameters.Others.Argument1)) { 1932 1933 // 1934 // Only jam this in if it doesn't exist. The completion routines can 1935 // call StartIo directly in the case of retries and resetting it will 1936 // cause infinite loops. 1937 // 1938 1939 nextIrpStack->Parameters.Others.Argument1 = (PVOID) MAXIMUM_RETRIES; 1940 } 1941 1942 // 1943 // Set up IoCompletion routine address. 1944 // 1945 1946 IoSetCompletionRoutine(Irp, 1947 CdRomXACompletion, 1948 srb, 1949 TRUE, 1950 TRUE, 1951 TRUE); 1952 1953 IoCallDriver(deviceExtension->PortDeviceObject, Irp); 1954 return; 1955 1956 } else { 1957 1958 transferByteCount = (use6Byte) ? sizeof(ERROR_RECOVERY_DATA) : sizeof(ERROR_RECOVERY_DATA10); 1959 dataBuffer = ExAllocatePool(NonPagedPoolCacheAligned, transferByteCount ); 1960 if (!dataBuffer) { 1961 Irp->IoStatus.Information = 0; 1962 Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; 1963 IoCompleteRequest(Irp, IO_DISK_INCREMENT); 1964 ExFreePool(senseBuffer); 1965 ExFreePool(srb); 1966 IoFreeIrp(irp2); 1967 IoStartNextPacket(DeviceObject, FALSE); 1968 return; 1969 1970 } 1971 1972 irp2->MdlAddress = IoAllocateMdl(dataBuffer, 1973 transferByteCount, 1974 FALSE, 1975 FALSE, 1976 (PIRP) NULL); 1977 1978 if (!irp2->MdlAddress) { 1979 Irp->IoStatus.Information = 0; 1980 Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; 1981 IoCompleteRequest(Irp, IO_DISK_INCREMENT); 1982 ExFreePool(senseBuffer); 1983 ExFreePool(srb); 1984 ExFreePool(dataBuffer); 1985 IoFreeIrp(irp2); 1986 IoStartNextPacket(DeviceObject, FALSE); 1987 return; 1988 } 1989 1990 // 1991 // Prepare the MDL 1992 // 1993 1994 MmBuildMdlForNonPagedPool(irp2->MdlAddress); 1995 1996 srb->DataBuffer = dataBuffer; 1997 1998 // 1999 // Set the new block size in the descriptor. 2000 // 2001 2002 cdData->u1.BlockDescriptor.BlockLength[0] = (UCHAR)(RAW_SECTOR_SIZE >> 16) & 0xFF; 2003 cdData->u1.BlockDescriptor.BlockLength[1] = (UCHAR)(RAW_SECTOR_SIZE >> 8) & 0xFF; 2004 cdData->u1.BlockDescriptor.BlockLength[2] = (UCHAR)(RAW_SECTOR_SIZE & 0xFF); 2005 2006 2007 // 2008 // TODO: Set density code, based on operation 2009 // 2010 2011 cdData->u1.BlockDescriptor.DensityCode = 0; 2012 2013 2014 // 2015 // Move error page into dataBuffer. 2016 // 2017 2018 RtlCopyMemory(srb->DataBuffer, &cdData->u1.Header, transferByteCount); 2019 2020 2021 // 2022 // Build and send a mode select to switch into raw mode. 2023 // 2024 2025 srb->SrbFlags = deviceExtension->SrbFlags; 2026 srb->SrbFlags |= (SRB_FLAGS_DISABLE_SYNCH_TRANSFER | SRB_FLAGS_DATA_OUT); 2027 srb->DataTransferLength = transferByteCount; 2028 srb->TimeOutValue = deviceExtension->TimeOutValue * 2; 2029 2030 if (use6Byte) { 2031 srb->CdbLength = 6; 2032 cdb->MODE_SELECT.OperationCode = SCSIOP_MODE_SELECT; 2033 cdb->MODE_SELECT.PFBit = 1; 2034 cdb->MODE_SELECT.ParameterListLength = (UCHAR)transferByteCount; 2035 } else { 2036 2037 srb->CdbLength = 10; 2038 cdb->MODE_SELECT10.OperationCode = SCSIOP_MODE_SELECT10; 2039 cdb->MODE_SELECT10.PFBit = 1; 2040 cdb->MODE_SELECT10.ParameterListLength[0] = (UCHAR)(transferByteCount >> 8); 2041 cdb->MODE_SELECT10.ParameterListLength[1] = (UCHAR)(transferByteCount & 0xFF); 2042 } 2043 2044 // 2045 // Update completion routine. 2046 // 2047 2048 IoSetCompletionRoutine(irp2, 2049 CdRomSwitchModeCompletion, 2050 srb, 2051 TRUE, 2052 TRUE, 2053 TRUE); 2054 2055 } 2056 2057 } else { 2058 2059 PRAW_READ_INFO rawReadInfo = 2060 (PRAW_READ_INFO)currentIrpStack->Parameters.DeviceIoControl.Type3InputBuffer; 2061 ULONG startingSector; 2062 2063 // 2064 // Free the recently allocated irp, as we don't need it. 2065 // 2066 2067 IoFreeIrp(irp2); 2068 2069 cdb = (PCDB)srb->Cdb; 2070 RtlZeroMemory(cdb, 12); 2071 2072 2073 // 2074 // Calculate starting offset. 2075 // 2076 2077 startingSector = (ULONG)(rawReadInfo->DiskOffset.QuadPart >> deviceExtension->SectorShift); 2078 transferByteCount = rawReadInfo->SectorCount * RAW_SECTOR_SIZE; 2079 2080 2081 srb->OriginalRequest = Irp; 2082 srb->SrbFlags = deviceExtension->SrbFlags; 2083 srb->SrbFlags |= (SRB_FLAGS_DISABLE_SYNCH_TRANSFER | SRB_FLAGS_DATA_IN); 2084 srb->DataTransferLength = transferByteCount; 2085 srb->TimeOutValue = deviceExtension->TimeOutValue; 2086 srb->DataBuffer = MmGetMdlVirtualAddress(Irp->MdlAddress); 2087 srb->CdbLength = 12; 2088 srb->SrbStatus = srb->ScsiStatus = 0; 2089 2090 // 2091 // Fill in CDB fields. 2092 // 2093 2094 cdb = (PCDB)srb->Cdb; 2095 2096 2097 cdb->READ_CD.TransferBlocks[2] = (UCHAR) (rawReadInfo->SectorCount & 0xFF); 2098 cdb->READ_CD.TransferBlocks[1] = (UCHAR) (rawReadInfo->SectorCount >> 8 ); 2099 cdb->READ_CD.TransferBlocks[0] = (UCHAR) (rawReadInfo->SectorCount >> 16); 2100 2101 2102 cdb->READ_CD.StartingLBA[3] = (UCHAR) (startingSector & 0xFF); 2103 cdb->READ_CD.StartingLBA[2] = (UCHAR) ((startingSector >> 8)); 2104 cdb->READ_CD.StartingLBA[1] = (UCHAR) ((startingSector >> 16)); 2105 cdb->READ_CD.StartingLBA[0] = (UCHAR) ((startingSector >> 24)); 2106 2107 // 2108 // Setup cdb depending upon the sector type we want. 2109 // 2110 2111 switch (rawReadInfo->TrackMode) { 2112 case CDDA: 2113 2114 cdb->READ_CD.ExpectedSectorType = CD_DA_SECTOR; 2115 cdb->READ_CD.IncludeUserData = 1; 2116 cdb->READ_CD.HeaderCode = 3; 2117 cdb->READ_CD.IncludeSyncData = 1; 2118 break; 2119 2120 case YellowMode2: 2121 2122 cdb->READ_CD.ExpectedSectorType = YELLOW_MODE2_SECTOR; 2123 cdb->READ_CD.IncludeUserData = 1; 2124 cdb->READ_CD.HeaderCode = 1; 2125 cdb->READ_CD.IncludeSyncData = 1; 2126 break; 2127 2128 case XAForm2: 2129 2130 cdb->READ_CD.ExpectedSectorType = FORM2_MODE2_SECTOR; 2131 cdb->READ_CD.IncludeUserData = 1; 2132 cdb->READ_CD.HeaderCode = 3; 2133 cdb->READ_CD.IncludeSyncData = 1; 2134 break; 2135 2136 default: 2137 Irp->IoStatus.Information = 0; 2138 Irp->IoStatus.Status = STATUS_INVALID_PARAMETER; 2139 IoCompleteRequest(Irp, IO_DISK_INCREMENT); 2140 ExFreePool(senseBuffer); 2141 ExFreePool(srb); 2142 IoStartNextPacket(DeviceObject, FALSE); 2143 DebugPrint((2, "ScsiCdRomStartIo: [%lx] bailing with status %lx at line %s\n", Irp, Irp->IoStatus.Status, __LINE__)); 2144 return; 2145 } 2146 2147 cdb->READ_CD.OperationCode = SCSIOP_READ_CD; 2148 2149 nextIrpStack->MajorFunction = IRP_MJ_SCSI; 2150 nextIrpStack->Parameters.Scsi.Srb = srb; 2151 2152 if (!(nextIrpStack->Parameters.Others.Argument1)) { 2153 2154 // 2155 // Only jam this in if it doesn't exist. The completion routines can 2156 // call StartIo directly in the case of retries and resetting it will 2157 // cause infinite loops. 2158 // 2159 2160 nextIrpStack->Parameters.Others.Argument1 = (PVOID) MAXIMUM_RETRIES; 2161 } 2162 2163 // 2164 // Set up IoCompletion routine address. 2165 // 2166 2167 IoSetCompletionRoutine(Irp, 2168 CdRomXACompletion, 2169 srb, 2170 TRUE, 2171 TRUE, 2172 TRUE); 2173 2174 IoCallDriver(deviceExtension->PortDeviceObject, Irp); 2175 return; 2176 2177 } 2178 2179 IoCallDriver(deviceExtension->PortDeviceObject, irp2); 2180 return; 2181 } 2182 2183 case IOCTL_DISK_GET_LENGTH_INFO: 2184 case IOCTL_DISK_GET_DRIVE_GEOMETRY_EX: 2185 case IOCTL_DISK_GET_DRIVE_GEOMETRY: 2186 case IOCTL_CDROM_GET_DRIVE_GEOMETRY_EX: 2187 case IOCTL_CDROM_GET_DRIVE_GEOMETRY: { 2188 2189 // 2190 // Issue ReadCapacity to update device extension 2191 // with information for current media. 2192 // 2193 2194 DebugPrint((3, 2195 "CdRomStartIo: Get drive capacity\n")); 2196 2197 // 2198 // setup remaining srb and cdb parameters. 2199 // 2200 2201 srb->SrbFlags = deviceExtension->SrbFlags; 2202 srb->SrbFlags |= (SRB_FLAGS_DISABLE_SYNCH_TRANSFER | SRB_FLAGS_DATA_IN); 2203 srb->DataTransferLength = sizeof(READ_CAPACITY_DATA); 2204 srb->CdbLength = 10; 2205 srb->TimeOutValue = deviceExtension->TimeOutValue; 2206 2207 dataBuffer = ExAllocatePool(NonPagedPoolCacheAligned, sizeof(READ_CAPACITY_DATA)); 2208 if (!dataBuffer) { 2209 Irp->IoStatus.Information = 0; 2210 Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; 2211 IoCompleteRequest(Irp, IO_DISK_INCREMENT); 2212 ExFreePool(senseBuffer); 2213 ExFreePool(srb); 2214 IoFreeIrp(irp2); 2215 IoStartNextPacket(DeviceObject, FALSE); 2216 DebugPrint((2, "ScsiCdRomStartIo: [%lx] bailing with status %lx at line %s\n", Irp, Irp->IoStatus.Status, __LINE__)); 2217 return; 2218 2219 } 2220 2221 irp2->MdlAddress = IoAllocateMdl(dataBuffer, 2222 sizeof(READ_CAPACITY_DATA), 2223 FALSE, 2224 FALSE, 2225 (PIRP) NULL); 2226 2227 if (!irp2->MdlAddress) { 2228 Irp->IoStatus.Information = 0; 2229 Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; 2230 IoCompleteRequest(Irp, IO_DISK_INCREMENT); 2231 ExFreePool(senseBuffer); 2232 ExFreePool(srb); 2233 ExFreePool(dataBuffer); 2234 IoFreeIrp(irp2); 2235 IoStartNextPacket(DeviceObject, FALSE); 2236 DebugPrint((2, "ScsiCdRomStartIo: [%lx] bailing with status %lx at line %s\n", Irp, Irp->IoStatus.Status, __LINE__)); 2237 return; 2238 } 2239 2240 // 2241 // Prepare the MDL 2242 // 2243 2244 MmBuildMdlForNonPagedPool(irp2->MdlAddress); 2245 2246 srb->DataBuffer = dataBuffer; 2247 cdb->CDB10.OperationCode = SCSIOP_READ_CAPACITY; 2248 2249 IoCallDriver(deviceExtension->PortDeviceObject, irp2); 2250 return; 2251 } 2252 2253 case IOCTL_CDROM_CHECK_VERIFY: { 2254 2255 // 2256 // Since a test unit ready is about to be performed, reset the timer 2257 // value to decrease the opportunities for it to race with this code. 2258 // 2259 2260 cdData->MediaChangeCountDown = MEDIA_CHANGE_DEFAULT_TIME; 2261 2262 // 2263 // Set up the SRB/CDB 2264 // 2265 2266 srb->CdbLength = 6; 2267 cdb->CDB6GENERIC.OperationCode = SCSIOP_TEST_UNIT_READY; 2268 srb->TimeOutValue = deviceExtension->TimeOutValue * 2; 2269 srb->SrbFlags = deviceExtension->SrbFlags; 2270 srb->SrbFlags |= (SRB_FLAGS_DISABLE_SYNCH_TRANSFER | SRB_FLAGS_NO_DATA_TRANSFER); 2271 2272 DebugPrint((2, "ScsiCdRomStartIo: [%lx] Sending CHECK_VERIFY irp %lx\n", Irp, irp2)); 2273 IoCallDriver(deviceExtension->PortDeviceObject, irp2); 2274 return; 2275 } 2276 2277 case IOCTL_CDROM_GET_LAST_SESSION: 2278 2279 // 2280 // Set format to return first and last session numbers. 2281 // 2282 2283 cdb->READ_TOC.Format = GET_LAST_SESSION; 2284 2285 // 2286 // Fall through to READ TOC code. 2287 // 2288 2289 case IOCTL_CDROM_READ_TOC: { 2290 2291 2292 if (currentIrpStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_CDROM_READ_TOC) { 2293 2294 // 2295 // Use MSF addressing if not request for session information. 2296 // 2297 2298 cdb->READ_TOC.Msf = CDB_USE_MSF; 2299 } 2300 2301 // 2302 // Set size of TOC structure. 2303 // 2304 2305 transferByteCount = 2306 currentIrpStack->Parameters.Read.Length > 2307 sizeof(CDROM_TOC) ? sizeof(CDROM_TOC): 2308 currentIrpStack->Parameters.Read.Length; 2309 2310 cdb->READ_TOC.AllocationLength[0] = (UCHAR) (transferByteCount >> 8); 2311 cdb->READ_TOC.AllocationLength[1] = (UCHAR) (transferByteCount & 0xFF); 2312 2313 cdb->READ_TOC.Control = 0; 2314 2315 // 2316 // Start at beginning of disc. 2317 // 2318 2319 cdb->READ_TOC.StartingTrack = 0; 2320 2321 // 2322 // setup remaining srb and cdb parameters. 2323 // 2324 2325 srb->SrbFlags = deviceExtension->SrbFlags; 2326 srb->SrbFlags |= (SRB_FLAGS_DISABLE_SYNCH_TRANSFER | SRB_FLAGS_DATA_IN); 2327 srb->DataTransferLength = transferByteCount; 2328 srb->CdbLength = 10; 2329 srb->TimeOutValue = deviceExtension->TimeOutValue; 2330 2331 dataBuffer = ExAllocatePool(NonPagedPoolCacheAligned, transferByteCount); 2332 if (!dataBuffer) { 2333 Irp->IoStatus.Information = 0; 2334 Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; 2335 IoCompleteRequest(Irp, IO_DISK_INCREMENT); 2336 ExFreePool(senseBuffer); 2337 ExFreePool(srb); 2338 IoFreeIrp(irp2); 2339 IoStartNextPacket(DeviceObject, FALSE); 2340 return; 2341 2342 } 2343 2344 irp2->MdlAddress = IoAllocateMdl(dataBuffer, 2345 transferByteCount, 2346 FALSE, 2347 FALSE, 2348 (PIRP) NULL); 2349 2350 if (!irp2->MdlAddress) { 2351 Irp->IoStatus.Information = 0; 2352 Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; 2353 IoCompleteRequest(Irp, IO_DISK_INCREMENT); 2354 ExFreePool(senseBuffer); 2355 ExFreePool(srb); 2356 ExFreePool(dataBuffer); 2357 IoFreeIrp(irp2); 2358 IoStartNextPacket(DeviceObject, FALSE); 2359 return; 2360 } 2361 2362 // 2363 // Prepare the MDL 2364 // 2365 2366 MmBuildMdlForNonPagedPool(irp2->MdlAddress); 2367 2368 srb->DataBuffer = dataBuffer; 2369 cdb->READ_TOC.OperationCode = SCSIOP_READ_TOC; 2370 2371 IoCallDriver(deviceExtension->PortDeviceObject, irp2); 2372 return; 2373 2374 } 2375 2376 case IOCTL_CDROM_PLAY_AUDIO_MSF: { 2377 2378 PCDROM_PLAY_AUDIO_MSF inputBuffer = Irp->AssociatedIrp.SystemBuffer; 2379 2380 // 2381 // Set up the SRB/CDB 2382 // 2383 2384 srb->CdbLength = 10; 2385 cdb->PLAY_AUDIO_MSF.OperationCode = SCSIOP_PLAY_AUDIO_MSF; 2386 2387 cdb->PLAY_AUDIO_MSF.StartingM = inputBuffer->StartingM; 2388 cdb->PLAY_AUDIO_MSF.StartingS = inputBuffer->StartingS; 2389 cdb->PLAY_AUDIO_MSF.StartingF = inputBuffer->StartingF; 2390 2391 cdb->PLAY_AUDIO_MSF.EndingM = inputBuffer->EndingM; 2392 cdb->PLAY_AUDIO_MSF.EndingS = inputBuffer->EndingS; 2393 cdb->PLAY_AUDIO_MSF.EndingF = inputBuffer->EndingF; 2394 2395 srb->TimeOutValue = deviceExtension->TimeOutValue; 2396 srb->SrbFlags = deviceExtension->SrbFlags; 2397 srb->SrbFlags |= (SRB_FLAGS_DISABLE_SYNCH_TRANSFER | SRB_FLAGS_NO_DATA_TRANSFER); 2398 2399 IoCallDriver(deviceExtension->PortDeviceObject, irp2); 2400 return; 2401 2402 } 2403 2404 case IOCTL_CDROM_READ_Q_CHANNEL: { 2405 2406 PCDROM_SUB_Q_DATA_FORMAT inputBuffer = 2407 Irp->AssociatedIrp.SystemBuffer; 2408 2409 // 2410 // Allocate buffer for subq channel information. 2411 // 2412 2413 dataBuffer = ExAllocatePool(NonPagedPoolCacheAligned, 2414 sizeof(SUB_Q_CHANNEL_DATA)); 2415 2416 if (!dataBuffer) { 2417 Irp->IoStatus.Information = 0; 2418 Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; 2419 IoCompleteRequest(Irp, IO_DISK_INCREMENT); 2420 ExFreePool(senseBuffer); 2421 ExFreePool(srb); 2422 IoFreeIrp(irp2); 2423 IoStartNextPacket(DeviceObject, FALSE); 2424 return; 2425 2426 } 2427 2428 irp2->MdlAddress = IoAllocateMdl(dataBuffer, 2429 transferByteCount, 2430 FALSE, 2431 FALSE, 2432 (PIRP) NULL); 2433 2434 if (!irp2->MdlAddress) { 2435 Irp->IoStatus.Information = 0; 2436 Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; 2437 IoCompleteRequest(Irp, IO_DISK_INCREMENT); 2438 ExFreePool(senseBuffer); 2439 ExFreePool(srb); 2440 ExFreePool(dataBuffer); 2441 IoFreeIrp(irp2); 2442 IoStartNextPacket(DeviceObject, FALSE); 2443 return; 2444 } 2445 2446 // 2447 // Prepare the MDL 2448 // 2449 2450 MmBuildMdlForNonPagedPool(irp2->MdlAddress); 2451 2452 srb->DataBuffer = dataBuffer; 2453 2454 // 2455 // Always logical unit 0, but only use MSF addressing 2456 // for IOCTL_CDROM_CURRENT_POSITION 2457 // 2458 2459 if (inputBuffer->Format==IOCTL_CDROM_CURRENT_POSITION) 2460 cdb->SUBCHANNEL.Msf = CDB_USE_MSF; 2461 2462 // 2463 // Return subchannel data 2464 // 2465 2466 cdb->SUBCHANNEL.SubQ = CDB_SUBCHANNEL_BLOCK; 2467 2468 // 2469 // Specify format of information to return 2470 // 2471 2472 cdb->SUBCHANNEL.Format = inputBuffer->Format; 2473 2474 // 2475 // Specify which track to access (only used by Track ISRC reads) 2476 // 2477 2478 if (inputBuffer->Format==IOCTL_CDROM_TRACK_ISRC) { 2479 cdb->SUBCHANNEL.TrackNumber = inputBuffer->Track; 2480 } 2481 2482 // 2483 // Set size of channel data -- however, this is dependent on 2484 // what information we are requesting (which Format) 2485 // 2486 2487 switch( inputBuffer->Format ) { 2488 2489 case IOCTL_CDROM_CURRENT_POSITION: 2490 transferByteCount = sizeof(SUB_Q_CURRENT_POSITION); 2491 break; 2492 2493 case IOCTL_CDROM_MEDIA_CATALOG: 2494 transferByteCount = sizeof(SUB_Q_MEDIA_CATALOG_NUMBER); 2495 break; 2496 2497 case IOCTL_CDROM_TRACK_ISRC: 2498 transferByteCount = sizeof(SUB_Q_TRACK_ISRC); 2499 break; 2500 } 2501 2502 cdb->SUBCHANNEL.AllocationLength[0] = (UCHAR) (transferByteCount >> 8); 2503 cdb->SUBCHANNEL.AllocationLength[1] = (UCHAR) (transferByteCount & 0xFF); 2504 cdb->SUBCHANNEL.OperationCode = SCSIOP_READ_SUB_CHANNEL; 2505 srb->SrbFlags = deviceExtension->SrbFlags; 2506 srb->SrbFlags |= (SRB_FLAGS_DISABLE_SYNCH_TRANSFER | SRB_FLAGS_DATA_IN); 2507 srb->DataTransferLength = transferByteCount; 2508 srb->CdbLength = 10; 2509 srb->TimeOutValue = deviceExtension->TimeOutValue; 2510 2511 IoCallDriver(deviceExtension->PortDeviceObject, irp2); 2512 return; 2513 2514 } 2515 2516 case IOCTL_CDROM_PAUSE_AUDIO: { 2517 2518 cdb->PAUSE_RESUME.OperationCode = SCSIOP_PAUSE_RESUME; 2519 cdb->PAUSE_RESUME.Action = CDB_AUDIO_PAUSE; 2520 2521 srb->CdbLength = 10; 2522 srb->TimeOutValue = deviceExtension->TimeOutValue; 2523 srb->SrbFlags = deviceExtension->SrbFlags; 2524 srb->SrbFlags |= (SRB_FLAGS_DISABLE_SYNCH_TRANSFER | SRB_FLAGS_NO_DATA_TRANSFER); 2525 2526 IoCallDriver(deviceExtension->PortDeviceObject, irp2); 2527 return; 2528 } 2529 2530 case IOCTL_CDROM_RESUME_AUDIO: { 2531 2532 cdb->PAUSE_RESUME.OperationCode = SCSIOP_PAUSE_RESUME; 2533 cdb->PAUSE_RESUME.Action = CDB_AUDIO_RESUME; 2534 2535 srb->CdbLength = 10; 2536 srb->TimeOutValue = deviceExtension->TimeOutValue; 2537 srb->SrbFlags = deviceExtension->SrbFlags; 2538 srb->SrbFlags |= (SRB_FLAGS_DISABLE_SYNCH_TRANSFER | SRB_FLAGS_NO_DATA_TRANSFER); 2539 2540 IoCallDriver(deviceExtension->PortDeviceObject, irp2); 2541 return; 2542 } 2543 2544 case IOCTL_CDROM_SEEK_AUDIO_MSF: { 2545 2546 PCDROM_SEEK_AUDIO_MSF inputBuffer = Irp->AssociatedIrp.SystemBuffer; 2547 ULONG logicalBlockAddress; 2548 2549 logicalBlockAddress = MSF_TO_LBA(inputBuffer->M, inputBuffer->S, inputBuffer->F); 2550 2551 cdb->SEEK.OperationCode = SCSIOP_SEEK; 2552 cdb->SEEK.LogicalBlockAddress[0] = ((PFOUR_BYTE)&logicalBlockAddress)->Byte3; 2553 cdb->SEEK.LogicalBlockAddress[1] = ((PFOUR_BYTE)&logicalBlockAddress)->Byte2; 2554 cdb->SEEK.LogicalBlockAddress[2] = ((PFOUR_BYTE)&logicalBlockAddress)->Byte1; 2555 cdb->SEEK.LogicalBlockAddress[3] = ((PFOUR_BYTE)&logicalBlockAddress)->Byte0; 2556 2557 srb->CdbLength = 10; 2558 srb->TimeOutValue = deviceExtension->TimeOutValue; 2559 srb->SrbFlags = deviceExtension->SrbFlags; 2560 srb->SrbFlags |= (SRB_FLAGS_DISABLE_SYNCH_TRANSFER | SRB_FLAGS_NO_DATA_TRANSFER); 2561 2562 IoCallDriver(deviceExtension->PortDeviceObject, irp2); 2563 return; 2564 2565 } 2566 2567 case IOCTL_CDROM_STOP_AUDIO: { 2568 2569 cdb->START_STOP.OperationCode = SCSIOP_START_STOP_UNIT; 2570 cdb->START_STOP.Immediate = 1; 2571 cdb->START_STOP.Start = 0; 2572 cdb->START_STOP.LoadEject = 0; 2573 2574 srb->CdbLength = 6; 2575 srb->TimeOutValue = deviceExtension->TimeOutValue; 2576 2577 srb->SrbFlags = deviceExtension->SrbFlags; 2578 srb->SrbFlags |= (SRB_FLAGS_DISABLE_SYNCH_TRANSFER | SRB_FLAGS_NO_DATA_TRANSFER); 2579 2580 IoCallDriver(deviceExtension->PortDeviceObject, irp2); 2581 return; 2582 } 2583 2584 case IOCTL_CDROM_GET_CONTROL: { 2585 // 2586 // Allocate buffer for volume control information. 2587 // 2588 2589 dataBuffer = ExAllocatePool(NonPagedPoolCacheAligned, 2590 MODE_DATA_SIZE); 2591 2592 if (!dataBuffer) { 2593 Irp->IoStatus.Information = 0; 2594 Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; 2595 IoCompleteRequest(Irp, IO_DISK_INCREMENT); 2596 ExFreePool(senseBuffer); 2597 ExFreePool(srb); 2598 IoFreeIrp(irp2); 2599 IoStartNextPacket(DeviceObject, FALSE); 2600 return; 2601 2602 } 2603 2604 irp2->MdlAddress = IoAllocateMdl(dataBuffer, 2605 MODE_DATA_SIZE, 2606 FALSE, 2607 FALSE, 2608 (PIRP) NULL); 2609 2610 if (!irp2->MdlAddress) { 2611 Irp->IoStatus.Information = 0; 2612 Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; 2613 IoCompleteRequest(Irp, IO_DISK_INCREMENT); 2614 ExFreePool(senseBuffer); 2615 ExFreePool(srb); 2616 ExFreePool(dataBuffer); 2617 IoFreeIrp(irp2); 2618 IoStartNextPacket(DeviceObject, FALSE); 2619 return; 2620 } 2621 2622 // 2623 // Prepare the MDL 2624 // 2625 2626 MmBuildMdlForNonPagedPool(irp2->MdlAddress); 2627 srb->DataBuffer = dataBuffer; 2628 2629 RtlZeroMemory(dataBuffer, MODE_DATA_SIZE); 2630 2631 // 2632 // Setup for either 6 or 10 byte CDBs. 2633 // 2634 2635 if (use6Byte) { 2636 2637 cdb->MODE_SENSE.OperationCode = SCSIOP_MODE_SENSE; 2638 cdb->MODE_SENSE.PageCode = CDROM_AUDIO_CONTROL_PAGE; 2639 cdb->MODE_SENSE.AllocationLength = MODE_DATA_SIZE; 2640 2641 // 2642 // Disable block descriptors. 2643 // 2644 2645 cdb->MODE_SENSE.Dbd = TRUE; 2646 2647 srb->CdbLength = 6; 2648 } else { 2649 2650 cdb->MODE_SENSE10.OperationCode = SCSIOP_MODE_SENSE10; 2651 cdb->MODE_SENSE10.PageCode = CDROM_AUDIO_CONTROL_PAGE; 2652 cdb->MODE_SENSE10.AllocationLength[0] = (UCHAR)(MODE_DATA_SIZE >> 8); 2653 cdb->MODE_SENSE10.AllocationLength[1] = (UCHAR)(MODE_DATA_SIZE & 0xFF); 2654 2655 // 2656 // Disable block descriptors. 2657 // 2658 2659 cdb->MODE_SENSE10.Dbd = TRUE; 2660 2661 srb->CdbLength = 10; 2662 } 2663 2664 srb->TimeOutValue = deviceExtension->TimeOutValue; 2665 srb->DataTransferLength = MODE_DATA_SIZE; 2666 srb->SrbFlags = deviceExtension->SrbFlags; 2667 srb->SrbFlags |= (SRB_FLAGS_DISABLE_SYNCH_TRANSFER | SRB_FLAGS_DATA_IN); 2668 2669 IoCallDriver(deviceExtension->PortDeviceObject, irp2); 2670 return; 2671 2672 } 2673 2674 case IOCTL_CDROM_GET_VOLUME: 2675 case IOCTL_CDROM_SET_VOLUME: { 2676 2677 dataBuffer = ExAllocatePool(NonPagedPoolCacheAligned, 2678 MODE_DATA_SIZE); 2679 2680 if (!dataBuffer) { 2681 Irp->IoStatus.Information = 0; 2682 Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; 2683 IoCompleteRequest(Irp, IO_DISK_INCREMENT); 2684 ExFreePool(senseBuffer); 2685 ExFreePool(srb); 2686 IoFreeIrp(irp2); 2687 IoStartNextPacket(DeviceObject, FALSE); 2688 return; 2689 } 2690 2691 irp2->MdlAddress = IoAllocateMdl(dataBuffer, 2692 MODE_DATA_SIZE, 2693 FALSE, 2694 FALSE, 2695 (PIRP) NULL); 2696 2697 if (!irp2->MdlAddress) { 2698 Irp->IoStatus.Information = 0; 2699 Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; 2700 IoCompleteRequest(Irp, IO_DISK_INCREMENT); 2701 ExFreePool(senseBuffer); 2702 ExFreePool(srb); 2703 ExFreePool(dataBuffer); 2704 IoFreeIrp(irp2); 2705 IoStartNextPacket(DeviceObject, FALSE); 2706 return; 2707 } 2708 2709 // 2710 // Prepare the MDL 2711 // 2712 2713 MmBuildMdlForNonPagedPool(irp2->MdlAddress); 2714 srb->DataBuffer = dataBuffer; 2715 2716 RtlZeroMemory(dataBuffer, MODE_DATA_SIZE); 2717 2718 2719 if (use6Byte) { 2720 cdb->MODE_SENSE.OperationCode = SCSIOP_MODE_SENSE; 2721 cdb->MODE_SENSE.PageCode = CDROM_AUDIO_CONTROL_PAGE; 2722 cdb->MODE_SENSE.AllocationLength = MODE_DATA_SIZE; 2723 2724 srb->CdbLength = 6; 2725 2726 } else { 2727 2728 cdb->MODE_SENSE10.OperationCode = SCSIOP_MODE_SENSE10; 2729 cdb->MODE_SENSE10.PageCode = CDROM_AUDIO_CONTROL_PAGE; 2730 cdb->MODE_SENSE10.AllocationLength[0] = (UCHAR)(MODE_DATA_SIZE >> 8); 2731 cdb->MODE_SENSE10.AllocationLength[1] = (UCHAR)(MODE_DATA_SIZE & 0xFF); 2732 2733 srb->CdbLength = 10; 2734 } 2735 2736 srb->TimeOutValue = deviceExtension->TimeOutValue; 2737 srb->DataTransferLength = MODE_DATA_SIZE; 2738 srb->SrbFlags = deviceExtension->SrbFlags; 2739 srb->SrbFlags |= (SRB_FLAGS_DISABLE_SYNCH_TRANSFER | SRB_FLAGS_DATA_IN); 2740 2741 if (currentIrpStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_CDROM_SET_VOLUME) { 2742 2743 // 2744 // Setup a different completion routine as the mode sense data is needed in order 2745 // to send the mode select. 2746 // 2747 2748 IoSetCompletionRoutine(irp2, 2749 CdRomSetVolumeIntermediateCompletion, 2750 srb, 2751 TRUE, 2752 TRUE, 2753 TRUE); 2754 2755 } 2756 2757 IoCallDriver(deviceExtension->PortDeviceObject, irp2); 2758 return; 2759 2760 } 2761 2762 default: 2763 2764 // 2765 // Just complete the request - CdRomClassIoctlCompletion will take 2766 // care of it for us 2767 // 2768 2769 IoCompleteRequest(Irp, IO_NO_INCREMENT); 2770 ExFreePool(senseBuffer); 2771 ExFreePool(srb); 2772 IoFreeIrp(irp2); 2773 return; 2774 2775 } // end switch() 2776 } 2777 2778 // 2779 // If a read or an unhandled IRP_MJ_XX, end up here. The unhandled IRP_MJ's 2780 // are expected and composed of AutoRun Irps, at present. 2781 // 2782 2783 IoCallDriver(deviceExtension->PortDeviceObject, Irp); 2784 return; 2785 } 2786 2787 2788 NTSTATUS 2789 NTAPI 2790 ScsiCdRomReadVerification( 2791 IN PDEVICE_OBJECT DeviceObject, 2792 IN PIRP Irp 2793 ) 2794 2795 /*++ 2796 2797 Routine Description: 2798 2799 This is the entry called by the I/O system for read requests. 2800 It builds the SRB and sends it to the port driver. 2801 2802 Arguments: 2803 2804 DeviceObject - the system object for the device. 2805 Irp - IRP involved. 2806 2807 Return Value: 2808 2809 NT Status 2810 2811 --*/ 2812 2813 { 2814 PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension; 2815 PIO_STACK_LOCATION currentIrpStack = IoGetCurrentIrpStackLocation(Irp); 2816 ULONG transferByteCount = currentIrpStack->Parameters.Read.Length; 2817 LARGE_INTEGER startingOffset = currentIrpStack->Parameters.Read.ByteOffset; 2818 2819 // 2820 // If the cd is playing music then reject this request. 2821 // 2822 2823 if (PLAY_ACTIVE(deviceExtension)) { 2824 Irp->IoStatus.Status = STATUS_DEVICE_BUSY; 2825 return STATUS_DEVICE_BUSY; 2826 } 2827 2828 // 2829 // Verify parameters of this request. 2830 // Check that ending sector is on disc and 2831 // that number of bytes to transfer is a multiple of 2832 // the sector size. 2833 // 2834 2835 startingOffset.QuadPart = currentIrpStack->Parameters.Read.ByteOffset.QuadPart + 2836 transferByteCount; 2837 2838 if (!deviceExtension->DiskGeometry->Geometry.BytesPerSector) { 2839 deviceExtension->DiskGeometry->Geometry.BytesPerSector = 2048; 2840 } 2841 2842 if ((startingOffset.QuadPart > deviceExtension->PartitionLength.QuadPart) || 2843 (transferByteCount & (deviceExtension->DiskGeometry->Geometry.BytesPerSector - 1))) { 2844 2845 DebugPrint((1,"ScsiCdRomRead: Invalid I/O parameters\n")); 2846 DebugPrint((1, "\toffset %x:%x, Length %x:%x\n", 2847 startingOffset.u.HighPart, 2848 startingOffset.u.LowPart, 2849 deviceExtension->PartitionLength.u.HighPart, 2850 deviceExtension->PartitionLength.u.LowPart)); 2851 DebugPrint((1, "\tbps %x\n", deviceExtension->DiskGeometry->Geometry.BytesPerSector)); 2852 2853 // 2854 // Fail request with status of invalid parameters. 2855 // 2856 2857 Irp->IoStatus.Status = STATUS_INVALID_PARAMETER; 2858 2859 return STATUS_INVALID_PARAMETER; 2860 } 2861 2862 2863 return STATUS_SUCCESS; 2864 2865 } // end ScsiCdRomReadVerification() 2866 2867 2868 NTSTATUS 2869 NTAPI 2870 CdRomDeviceControlCompletion( 2871 IN PDEVICE_OBJECT DeviceObject, 2872 IN PIRP Irp, 2873 IN PVOID Context 2874 ) 2875 { 2876 PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension; 2877 PDEVICE_EXTENSION physicalExtension = deviceExtension->PhysicalDevice->DeviceExtension; 2878 PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp); 2879 PCDROM_DATA cdData = (PCDROM_DATA)(deviceExtension + 1); 2880 BOOLEAN use6Byte = cdData->XAFlags & XA_USE_6_BYTE; 2881 PIO_STACK_LOCATION realIrpStack; 2882 PIO_STACK_LOCATION realIrpNextStack; 2883 PSCSI_REQUEST_BLOCK srb = Context; 2884 PIRP realIrp = NULL; 2885 NTSTATUS status; 2886 BOOLEAN retry; 2887 2888 // 2889 // Extract the 'real' irp from the irpstack. 2890 // 2891 2892 realIrp = (PIRP) irpStack->Parameters.Others.Argument2; 2893 realIrpStack = IoGetCurrentIrpStackLocation(realIrp); 2894 realIrpNextStack = IoGetNextIrpStackLocation(realIrp); 2895 2896 // 2897 // Check SRB status for success of completing request. 2898 // 2899 2900 if (SRB_STATUS(srb->SrbStatus) != SRB_STATUS_SUCCESS) { 2901 2902 DebugPrint((2, 2903 "CdRomDeviceControlCompletion: Irp %lx, Srb %lx Real Irp %lx Status %lx\n", 2904 Irp, 2905 srb, 2906 realIrp, 2907 srb->SrbStatus)); 2908 2909 // 2910 // Release the queue if it is frozen. 2911 // 2912 2913 if (srb->SrbStatus & SRB_STATUS_QUEUE_FROZEN) { 2914 DebugPrint((2, "CdRomDeviceControlCompletion: Releasing Queue\n")); 2915 ScsiClassReleaseQueue(DeviceObject); 2916 } 2917 2918 2919 retry = ScsiClassInterpretSenseInfo(DeviceObject, 2920 srb, 2921 irpStack->MajorFunction, 2922 irpStack->Parameters.DeviceIoControl.IoControlCode, 2923 MAXIMUM_RETRIES - ((ULONG_PTR)realIrpNextStack->Parameters.Others.Argument1), 2924 &status); 2925 2926 DebugPrint((2, "CdRomDeviceControlCompletion: IRP will %sbe retried\n", 2927 (retry ? "" : "not "))); 2928 2929 // 2930 // Some of the Device Controls need special cases on non-Success status's. 2931 // 2932 2933 if (realIrpStack->MajorFunction == IRP_MJ_DEVICE_CONTROL) { 2934 if ((realIrpStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_CDROM_GET_LAST_SESSION) || 2935 (realIrpStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_CDROM_READ_TOC) || 2936 (realIrpStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_CDROM_GET_CONTROL) || 2937 (realIrpStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_CDROM_GET_VOLUME)) { 2938 2939 if (status == STATUS_DATA_OVERRUN) { 2940 status = STATUS_SUCCESS; 2941 retry = FALSE; 2942 } 2943 } 2944 2945 if (realIrpStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_CDROM_READ_Q_CHANNEL) { 2946 PLAY_ACTIVE(deviceExtension) = FALSE; 2947 } 2948 } 2949 2950 // 2951 // If the status is verified required and the this request 2952 // should bypass verify required then retry the request. 2953 // 2954 2955 if (realIrpStack->Flags & SL_OVERRIDE_VERIFY_VOLUME && 2956 status == STATUS_VERIFY_REQUIRED) { 2957 2958 if (((realIrpStack->MajorFunction == IRP_MJ_DEVICE_CONTROL) || 2959 (realIrpStack->MajorFunction == IRP_MJ_INTERNAL_DEVICE_CONTROL)) && 2960 (realIrpStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_CDROM_CHECK_VERIFY)) { 2961 2962 ExFreePool(srb->SenseInfoBuffer); 2963 if (srb->DataBuffer) { 2964 ExFreePool(srb->DataBuffer); 2965 } 2966 ExFreePool(srb); 2967 if (Irp->MdlAddress) { 2968 IoFreeMdl(Irp->MdlAddress); 2969 } 2970 2971 IoFreeIrp(Irp); 2972 2973 // 2974 // Update the geometry information, as the media could have changed. 2975 // The completion routine for this will complete the real irp and start 2976 // the next packet. 2977 // 2978 2979 status = CdRomUpdateCapacity(deviceExtension,realIrp, NULL); 2980 DebugPrint((2, "CdRomDeviceControlCompletion: [%lx] CdRomUpdateCapacity completed with status %lx\n", realIrp, status)); 2981 ASSERT(status == STATUS_PENDING); 2982 2983 return STATUS_MORE_PROCESSING_REQUIRED; 2984 2985 } else { 2986 2987 status = STATUS_IO_DEVICE_ERROR; 2988 retry = TRUE; 2989 } 2990 2991 } 2992 2993 if (retry && (realIrpNextStack->Parameters.Others.Argument1 = (PVOID)((ULONG_PTR)realIrpNextStack->Parameters.Others.Argument1-1))) { 2994 2995 2996 if (((ULONG_PTR)realIrpNextStack->Parameters.Others.Argument1)) { 2997 2998 // 2999 // Retry request. 3000 // 3001 3002 DebugPrint((1, "Retry request %lx - Calling StartIo\n", Irp)); 3003 3004 3005 ExFreePool(srb->SenseInfoBuffer); 3006 if (srb->DataBuffer) { 3007 ExFreePool(srb->DataBuffer); 3008 } 3009 ExFreePool(srb); 3010 if (Irp->MdlAddress) { 3011 IoFreeMdl(Irp->MdlAddress); 3012 } 3013 3014 IoFreeIrp(Irp); 3015 3016 // 3017 // Call StartIo directly since IoStartNextPacket hasn't been called, 3018 // the serialisation is still intact. 3019 // 3020 3021 ScsiCdRomStartIo(DeviceObject, realIrp); 3022 return STATUS_MORE_PROCESSING_REQUIRED; 3023 3024 } 3025 3026 // 3027 // Exhausted retries. Fall through and complete the request with the appropriate status. 3028 // 3029 3030 } 3031 } else { 3032 3033 // 3034 // Set status for successful request. 3035 // 3036 3037 status = STATUS_SUCCESS; 3038 } 3039 3040 if (NT_SUCCESS(status)) { 3041 3042 switch (realIrpStack->Parameters.DeviceIoControl.IoControlCode) { 3043 3044 case IOCTL_DISK_GET_LENGTH_INFO: { 3045 3046 PREAD_CAPACITY_DATA readCapacityBuffer = srb->DataBuffer; 3047 ULONG lastSector; 3048 ULONG bps; 3049 ULONG lastBit; 3050 ULONG tmp; 3051 3052 // 3053 // Swizzle bytes from Read Capacity and translate into 3054 // the necessary geometry information in the device extension. 3055 // 3056 3057 tmp = readCapacityBuffer->BytesPerBlock; 3058 ((PFOUR_BYTE)&bps)->Byte0 = ((PFOUR_BYTE)&tmp)->Byte3; 3059 ((PFOUR_BYTE)&bps)->Byte1 = ((PFOUR_BYTE)&tmp)->Byte2; 3060 ((PFOUR_BYTE)&bps)->Byte2 = ((PFOUR_BYTE)&tmp)->Byte1; 3061 ((PFOUR_BYTE)&bps)->Byte3 = ((PFOUR_BYTE)&tmp)->Byte0; 3062 3063 // 3064 // Insure that bps is a power of 2. 3065 // This corrects a problem with the HP 4020i CDR where it 3066 // returns an incorrect number for bytes per sector. 3067 // 3068 3069 if (!bps) { 3070 bps = 2048; 3071 } else { 3072 lastBit = (ULONG) -1; 3073 while (bps) { 3074 lastBit++; 3075 bps = bps >> 1; 3076 } 3077 3078 bps = 1 << lastBit; 3079 } 3080 deviceExtension->DiskGeometry->Geometry.BytesPerSector = bps; 3081 3082 DebugPrint((2, 3083 "CdRomDeviceControlCompletion: Calculated bps %#x\n", 3084 deviceExtension->DiskGeometry->Geometry.BytesPerSector)); 3085 3086 // 3087 // Copy last sector in reverse byte order. 3088 // 3089 3090 tmp = readCapacityBuffer->LogicalBlockAddress; 3091 ((PFOUR_BYTE)&lastSector)->Byte0 = ((PFOUR_BYTE)&tmp)->Byte3; 3092 ((PFOUR_BYTE)&lastSector)->Byte1 = ((PFOUR_BYTE)&tmp)->Byte2; 3093 ((PFOUR_BYTE)&lastSector)->Byte2 = ((PFOUR_BYTE)&tmp)->Byte1; 3094 ((PFOUR_BYTE)&lastSector)->Byte3 = ((PFOUR_BYTE)&tmp)->Byte0; 3095 3096 // 3097 // Calculate sector to byte shift. 3098 // 3099 3100 WHICH_BIT(bps, deviceExtension->SectorShift); 3101 3102 DebugPrint((2,"SCSI ScsiClassReadDriveCapacity: Sector size is %d\n", 3103 deviceExtension->DiskGeometry->Geometry.BytesPerSector)); 3104 3105 DebugPrint((2,"SCSI ScsiClassReadDriveCapacity: Number of Sectors is %d\n", 3106 lastSector + 1)); 3107 3108 // 3109 // Calculate media capacity in bytes. 3110 // 3111 3112 deviceExtension->PartitionLength.QuadPart = (LONGLONG)(lastSector + 1); 3113 3114 // 3115 // Calculate number of cylinders. 3116 // 3117 3118 deviceExtension->DiskGeometry->Geometry.Cylinders.QuadPart = (LONGLONG)((lastSector + 1)/(32 * 64)); 3119 3120 deviceExtension->PartitionLength.QuadPart = 3121 (deviceExtension->PartitionLength.QuadPart << deviceExtension->SectorShift); 3122 3123 if (DeviceObject->Characteristics & FILE_REMOVABLE_MEDIA) { 3124 3125 // 3126 // This device supports removable media. 3127 // 3128 3129 deviceExtension->DiskGeometry->Geometry.MediaType = RemovableMedia; 3130 3131 } else { 3132 3133 // 3134 // Assume media type is fixed disk. 3135 // 3136 3137 deviceExtension->DiskGeometry->Geometry.MediaType = FixedMedia; 3138 } 3139 3140 // 3141 // Assume sectors per track are 32; 3142 // 3143 3144 deviceExtension->DiskGeometry->Geometry.SectorsPerTrack = 32; 3145 3146 // 3147 // Assume tracks per cylinder (number of heads) is 64. 3148 // 3149 3150 deviceExtension->DiskGeometry->Geometry.TracksPerCylinder = 64; 3151 3152 // 3153 // Copy the device extension's geometry info into the user buffer. 3154 // 3155 3156 RtlMoveMemory(realIrp->AssociatedIrp.SystemBuffer, 3157 &deviceExtension->PartitionLength, 3158 sizeof(GET_LENGTH_INFORMATION)); 3159 3160 // 3161 // update information field. 3162 // 3163 3164 realIrp->IoStatus.Information = sizeof(DISK_GEOMETRY); 3165 break; 3166 } 3167 3168 case IOCTL_DISK_GET_DRIVE_GEOMETRY_EX: 3169 case IOCTL_CDROM_GET_DRIVE_GEOMETRY_EX: { 3170 3171 PREAD_CAPACITY_DATA readCapacityBuffer = srb->DataBuffer; 3172 ULONG lastSector; 3173 ULONG bps; 3174 ULONG lastBit; 3175 ULONG tmp; 3176 PDISK_GEOMETRY_EX geometryEx; 3177 3178 // 3179 // Swizzle bytes from Read Capacity and translate into 3180 // the necessary geometry information in the device extension. 3181 // 3182 3183 tmp = readCapacityBuffer->BytesPerBlock; 3184 ((PFOUR_BYTE)&bps)->Byte0 = ((PFOUR_BYTE)&tmp)->Byte3; 3185 ((PFOUR_BYTE)&bps)->Byte1 = ((PFOUR_BYTE)&tmp)->Byte2; 3186 ((PFOUR_BYTE)&bps)->Byte2 = ((PFOUR_BYTE)&tmp)->Byte1; 3187 ((PFOUR_BYTE)&bps)->Byte3 = ((PFOUR_BYTE)&tmp)->Byte0; 3188 3189 // 3190 // Insure that bps is a power of 2. 3191 // This corrects a problem with the HP 4020i CDR where it 3192 // returns an incorrect number for bytes per sector. 3193 // 3194 3195 if (!bps) { 3196 bps = 2048; 3197 } else { 3198 lastBit = (ULONG) -1; 3199 while (bps) { 3200 lastBit++; 3201 bps = bps >> 1; 3202 } 3203 3204 bps = 1 << lastBit; 3205 } 3206 deviceExtension->DiskGeometry->Geometry.BytesPerSector = bps; 3207 3208 DebugPrint((2, 3209 "CdRomDeviceControlCompletion: Calculated bps %#x\n", 3210 deviceExtension->DiskGeometry->Geometry.BytesPerSector)); 3211 3212 // 3213 // Copy last sector in reverse byte order. 3214 // 3215 3216 tmp = readCapacityBuffer->LogicalBlockAddress; 3217 ((PFOUR_BYTE)&lastSector)->Byte0 = ((PFOUR_BYTE)&tmp)->Byte3; 3218 ((PFOUR_BYTE)&lastSector)->Byte1 = ((PFOUR_BYTE)&tmp)->Byte2; 3219 ((PFOUR_BYTE)&lastSector)->Byte2 = ((PFOUR_BYTE)&tmp)->Byte1; 3220 ((PFOUR_BYTE)&lastSector)->Byte3 = ((PFOUR_BYTE)&tmp)->Byte0; 3221 3222 // 3223 // Calculate sector to byte shift. 3224 // 3225 3226 WHICH_BIT(bps, deviceExtension->SectorShift); 3227 3228 DebugPrint((2,"SCSI ScsiClassReadDriveCapacity: Sector size is %d\n", 3229 deviceExtension->DiskGeometry->Geometry.BytesPerSector)); 3230 3231 DebugPrint((2,"SCSI ScsiClassReadDriveCapacity: Number of Sectors is %d\n", 3232 lastSector + 1)); 3233 3234 // 3235 // Calculate media capacity in bytes. 3236 // 3237 3238 deviceExtension->PartitionLength.QuadPart = (LONGLONG)(lastSector + 1); 3239 3240 // 3241 // Calculate number of cylinders. 3242 // 3243 3244 deviceExtension->DiskGeometry->Geometry.Cylinders.QuadPart = (LONGLONG)((lastSector + 1)/(32 * 64)); 3245 3246 deviceExtension->PartitionLength.QuadPart = 3247 (deviceExtension->PartitionLength.QuadPart << deviceExtension->SectorShift); 3248 3249 if (DeviceObject->Characteristics & FILE_REMOVABLE_MEDIA) { 3250 3251 // 3252 // This device supports removable media. 3253 // 3254 3255 deviceExtension->DiskGeometry->Geometry.MediaType = RemovableMedia; 3256 3257 } else { 3258 3259 // 3260 // Assume media type is fixed disk. 3261 // 3262 3263 deviceExtension->DiskGeometry->Geometry.MediaType = FixedMedia; 3264 } 3265 3266 // 3267 // Assume sectors per track are 32; 3268 // 3269 3270 deviceExtension->DiskGeometry->Geometry.SectorsPerTrack = 32; 3271 3272 // 3273 // Assume tracks per cylinder (number of heads) is 64. 3274 // 3275 3276 deviceExtension->DiskGeometry->Geometry.TracksPerCylinder = 64; 3277 3278 // 3279 // Copy the device extension's geometry info into the user buffer. 3280 // 3281 3282 geometryEx = realIrp->AssociatedIrp.SystemBuffer; 3283 RtlMoveMemory(&geometryEx->Geometry, 3284 &deviceExtension->DiskGeometry->Geometry, 3285 sizeof(DISK_GEOMETRY)); 3286 3287 // 3288 // Copy the extended information 3289 // 3290 3291 geometryEx->DiskSize = deviceExtension->PartitionLength; 3292 3293 // 3294 // update information field. 3295 // 3296 3297 realIrp->IoStatus.Information = FIELD_OFFSET(DISK_GEOMETRY_EX, Data); 3298 break; 3299 } 3300 3301 case IOCTL_DISK_GET_DRIVE_GEOMETRY: 3302 case IOCTL_CDROM_GET_DRIVE_GEOMETRY: { 3303 3304 PREAD_CAPACITY_DATA readCapacityBuffer = srb->DataBuffer; 3305 ULONG lastSector; 3306 ULONG bps; 3307 ULONG lastBit; 3308 ULONG tmp; 3309 3310 // 3311 // Swizzle bytes from Read Capacity and translate into 3312 // the necessary geometry information in the device extension. 3313 // 3314 3315 tmp = readCapacityBuffer->BytesPerBlock; 3316 ((PFOUR_BYTE)&bps)->Byte0 = ((PFOUR_BYTE)&tmp)->Byte3; 3317 ((PFOUR_BYTE)&bps)->Byte1 = ((PFOUR_BYTE)&tmp)->Byte2; 3318 ((PFOUR_BYTE)&bps)->Byte2 = ((PFOUR_BYTE)&tmp)->Byte1; 3319 ((PFOUR_BYTE)&bps)->Byte3 = ((PFOUR_BYTE)&tmp)->Byte0; 3320 3321 // 3322 // Insure that bps is a power of 2. 3323 // This corrects a problem with the HP 4020i CDR where it 3324 // returns an incorrect number for bytes per sector. 3325 // 3326 3327 if (!bps) { 3328 bps = 2048; 3329 } else { 3330 lastBit = (ULONG) -1; 3331 while (bps) { 3332 lastBit++; 3333 bps = bps >> 1; 3334 } 3335 3336 bps = 1 << lastBit; 3337 } 3338 deviceExtension->DiskGeometry->Geometry.BytesPerSector = bps; 3339 3340 DebugPrint((2, 3341 "CdRomDeviceControlCompletion: Calculated bps %#x\n", 3342 deviceExtension->DiskGeometry->Geometry.BytesPerSector)); 3343 3344 // 3345 // Copy last sector in reverse byte order. 3346 // 3347 3348 tmp = readCapacityBuffer->LogicalBlockAddress; 3349 ((PFOUR_BYTE)&lastSector)->Byte0 = ((PFOUR_BYTE)&tmp)->Byte3; 3350 ((PFOUR_BYTE)&lastSector)->Byte1 = ((PFOUR_BYTE)&tmp)->Byte2; 3351 ((PFOUR_BYTE)&lastSector)->Byte2 = ((PFOUR_BYTE)&tmp)->Byte1; 3352 ((PFOUR_BYTE)&lastSector)->Byte3 = ((PFOUR_BYTE)&tmp)->Byte0; 3353 3354 // 3355 // Calculate sector to byte shift. 3356 // 3357 3358 WHICH_BIT(bps, deviceExtension->SectorShift); 3359 3360 DebugPrint((2,"SCSI ScsiClassReadDriveCapacity: Sector size is %d\n", 3361 deviceExtension->DiskGeometry->Geometry.BytesPerSector)); 3362 3363 DebugPrint((2,"SCSI ScsiClassReadDriveCapacity: Number of Sectors is %d\n", 3364 lastSector + 1)); 3365 3366 // 3367 // Calculate media capacity in bytes. 3368 // 3369 3370 deviceExtension->PartitionLength.QuadPart = (LONGLONG)(lastSector + 1); 3371 3372 // 3373 // Calculate number of cylinders. 3374 // 3375 3376 deviceExtension->DiskGeometry->Geometry.Cylinders.QuadPart = (LONGLONG)((lastSector + 1)/(32 * 64)); 3377 3378 deviceExtension->PartitionLength.QuadPart = 3379 (deviceExtension->PartitionLength.QuadPart << deviceExtension->SectorShift); 3380 3381 if (DeviceObject->Characteristics & FILE_REMOVABLE_MEDIA) { 3382 3383 // 3384 // This device supports removable media. 3385 // 3386 3387 deviceExtension->DiskGeometry->Geometry.MediaType = RemovableMedia; 3388 3389 } else { 3390 3391 // 3392 // Assume media type is fixed disk. 3393 // 3394 3395 deviceExtension->DiskGeometry->Geometry.MediaType = FixedMedia; 3396 } 3397 3398 // 3399 // Assume sectors per track are 32; 3400 // 3401 3402 deviceExtension->DiskGeometry->Geometry.SectorsPerTrack = 32; 3403 3404 // 3405 // Assume tracks per cylinder (number of heads) is 64. 3406 // 3407 3408 deviceExtension->DiskGeometry->Geometry.TracksPerCylinder = 64; 3409 3410 // 3411 // Copy the device extension's geometry info into the user buffer. 3412 // 3413 3414 RtlMoveMemory(realIrp->AssociatedIrp.SystemBuffer, 3415 deviceExtension->DiskGeometry, 3416 sizeof(DISK_GEOMETRY)); 3417 3418 // 3419 // update information field. 3420 // 3421 3422 realIrp->IoStatus.Information = sizeof(DISK_GEOMETRY); 3423 break; 3424 } 3425 3426 case IOCTL_CDROM_CHECK_VERIFY: 3427 3428 if((realIrpStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_CDROM_CHECK_VERIFY) && 3429 (realIrpStack->Parameters.DeviceIoControl.OutputBufferLength)) { 3430 3431 *((PULONG)realIrp->AssociatedIrp.SystemBuffer) = 3432 physicalExtension->MediaChangeCount; 3433 realIrp->IoStatus.Information = sizeof(ULONG); 3434 } else { 3435 realIrp->IoStatus.Information = 0; 3436 } 3437 3438 DebugPrint((2, "CdRomDeviceControlCompletion: [%lx] completing CHECK_VERIFY buddy irp %lx\n", realIrp, Irp)); 3439 break; 3440 3441 case IOCTL_CDROM_GET_LAST_SESSION: 3442 case IOCTL_CDROM_READ_TOC: { 3443 3444 PCDROM_TOC toc = srb->DataBuffer; 3445 3446 // 3447 // Copy the device extension's geometry info into the user buffer. 3448 // 3449 3450 RtlMoveMemory(realIrp->AssociatedIrp.SystemBuffer, 3451 toc, 3452 srb->DataTransferLength); 3453 3454 // 3455 // update information field. 3456 // 3457 3458 realIrp->IoStatus.Information = srb->DataTransferLength; 3459 break; 3460 } 3461 3462 case IOCTL_CDROM_PLAY_AUDIO_MSF: 3463 3464 PLAY_ACTIVE(deviceExtension) = TRUE; 3465 3466 break; 3467 3468 case IOCTL_CDROM_READ_Q_CHANNEL: { 3469 3470 PSUB_Q_CHANNEL_DATA userChannelData = realIrp->AssociatedIrp.SystemBuffer; 3471 #if DBG 3472 PCDROM_SUB_Q_DATA_FORMAT inputBuffer = realIrp->AssociatedIrp.SystemBuffer; 3473 #endif 3474 PSUB_Q_CHANNEL_DATA subQPtr = srb->DataBuffer; 3475 3476 #if DBG 3477 switch( inputBuffer->Format ) { 3478 3479 case IOCTL_CDROM_CURRENT_POSITION: 3480 DebugPrint((2,"CdRomDeviceControlCompletion: Audio Status is %u\n", subQPtr->CurrentPosition.Header.AudioStatus )); 3481 DebugPrint((2,"CdRomDeviceControlCompletion: ADR = 0x%x\n", subQPtr->CurrentPosition.ADR )); 3482 DebugPrint((2,"CdRomDeviceControlCompletion: Control = 0x%x\n", subQPtr->CurrentPosition.Control )); 3483 DebugPrint((2,"CdRomDeviceControlCompletion: Track = %u\n", subQPtr->CurrentPosition.TrackNumber )); 3484 DebugPrint((2,"CdRomDeviceControlCompletion: Index = %u\n", subQPtr->CurrentPosition.IndexNumber )); 3485 DebugPrint((2,"CdRomDeviceControlCompletion: Absolute Address = %x\n", *((PULONG)subQPtr->CurrentPosition.AbsoluteAddress) )); 3486 DebugPrint((2,"CdRomDeviceControlCompletion: Relative Address = %x\n", *((PULONG)subQPtr->CurrentPosition.TrackRelativeAddress) )); 3487 break; 3488 3489 case IOCTL_CDROM_MEDIA_CATALOG: 3490 DebugPrint((2,"CdRomDeviceControlCompletion: Audio Status is %u\n", subQPtr->MediaCatalog.Header.AudioStatus )); 3491 DebugPrint((2,"CdRomDeviceControlCompletion: Mcval is %u\n", subQPtr->MediaCatalog.Mcval )); 3492 break; 3493 3494 case IOCTL_CDROM_TRACK_ISRC: 3495 DebugPrint((2,"CdRomDeviceControlCompletion: Audio Status is %u\n", subQPtr->TrackIsrc.Header.AudioStatus )); 3496 DebugPrint((2,"CdRomDeviceControlCompletion: Tcval is %u\n", subQPtr->TrackIsrc.Tcval )); 3497 break; 3498 3499 } 3500 #endif 3501 3502 // 3503 // Update the play active status. 3504 // 3505 3506 if (subQPtr->CurrentPosition.Header.AudioStatus == AUDIO_STATUS_IN_PROGRESS) { 3507 3508 PLAY_ACTIVE(deviceExtension) = TRUE; 3509 3510 } else { 3511 3512 PLAY_ACTIVE(deviceExtension) = FALSE; 3513 3514 } 3515 3516 // 3517 // Check if output buffer is large enough to contain 3518 // the data. 3519 // 3520 3521 if (realIrpStack->Parameters.DeviceIoControl.OutputBufferLength < 3522 srb->DataTransferLength) { 3523 3524 srb->DataTransferLength = 3525 realIrpStack->Parameters.DeviceIoControl.OutputBufferLength; 3526 } 3527 3528 // 3529 // Copy our buffer into users. 3530 // 3531 3532 RtlMoveMemory(userChannelData, 3533 subQPtr, 3534 srb->DataTransferLength); 3535 3536 realIrp->IoStatus.Information = srb->DataTransferLength; 3537 break; 3538 } 3539 3540 case IOCTL_CDROM_PAUSE_AUDIO: 3541 3542 PLAY_ACTIVE(deviceExtension) = FALSE; 3543 realIrp->IoStatus.Information = 0; 3544 break; 3545 3546 case IOCTL_CDROM_RESUME_AUDIO: 3547 3548 realIrp->IoStatus.Information = 0; 3549 break; 3550 3551 case IOCTL_CDROM_SEEK_AUDIO_MSF: 3552 3553 realIrp->IoStatus.Information = 0; 3554 break; 3555 3556 case IOCTL_CDROM_STOP_AUDIO: 3557 3558 PLAY_ACTIVE(deviceExtension) = FALSE; 3559 3560 realIrp->IoStatus.Information = 0; 3561 break; 3562 3563 case IOCTL_CDROM_GET_CONTROL: { 3564 3565 PCDROM_AUDIO_CONTROL audioControl = srb->DataBuffer; 3566 PAUDIO_OUTPUT audioOutput; 3567 ULONG bytesTransferred; 3568 3569 audioOutput = ScsiClassFindModePage((PCHAR)audioControl, 3570 srb->DataTransferLength, 3571 CDROM_AUDIO_CONTROL_PAGE, 3572 use6Byte); 3573 // 3574 // Verify the page is as big as expected. 3575 // 3576 3577 bytesTransferred = (PCHAR) audioOutput - (PCHAR) audioControl + 3578 sizeof(AUDIO_OUTPUT); 3579 3580 if (audioOutput != NULL && 3581 srb->DataTransferLength >= bytesTransferred) { 3582 3583 audioControl->LbaFormat = audioOutput->LbaFormat; 3584 3585 audioControl->LogicalBlocksPerSecond = 3586 (audioOutput->LogicalBlocksPerSecond[0] << (UCHAR)8) | 3587 audioOutput->LogicalBlocksPerSecond[1]; 3588 3589 realIrp->IoStatus.Information = sizeof(CDROM_AUDIO_CONTROL); 3590 3591 } else { 3592 realIrp->IoStatus.Information = 0; 3593 status = STATUS_INVALID_DEVICE_REQUEST; 3594 } 3595 break; 3596 } 3597 3598 case IOCTL_CDROM_GET_VOLUME: { 3599 3600 PAUDIO_OUTPUT audioOutput; 3601 PVOLUME_CONTROL volumeControl = srb->DataBuffer; 3602 ULONG i,bytesTransferred; 3603 3604 audioOutput = ScsiClassFindModePage((PCHAR)volumeControl, 3605 srb->DataTransferLength, 3606 CDROM_AUDIO_CONTROL_PAGE, 3607 use6Byte); 3608 3609 // 3610 // Verify the page is as big as expected. 3611 // 3612 3613 bytesTransferred = (PCHAR) audioOutput - (PCHAR) volumeControl + 3614 sizeof(AUDIO_OUTPUT); 3615 3616 if (audioOutput != NULL && 3617 srb->DataTransferLength >= bytesTransferred) { 3618 3619 for (i=0; i<4; i++) { 3620 volumeControl->PortVolume[i] = 3621 audioOutput->PortOutput[i].Volume; 3622 } 3623 3624 // 3625 // Set bytes transferred in IRP. 3626 // 3627 3628 realIrp->IoStatus.Information = sizeof(VOLUME_CONTROL); 3629 3630 } else { 3631 realIrp->IoStatus.Information = 0; 3632 status = STATUS_INVALID_DEVICE_REQUEST; 3633 } 3634 3635 break; 3636 } 3637 3638 case IOCTL_CDROM_SET_VOLUME: 3639 3640 realIrp->IoStatus.Information = sizeof(VOLUME_CONTROL); 3641 break; 3642 3643 default: 3644 3645 ASSERT(FALSE); 3646 realIrp->IoStatus.Information = 0; 3647 status = STATUS_INVALID_DEVICE_REQUEST; 3648 3649 } // end switch() 3650 } 3651 3652 // 3653 // Deallocate srb and sense buffer. 3654 // 3655 3656 if (srb) { 3657 if (srb->DataBuffer) { 3658 ExFreePool(srb->DataBuffer); 3659 } 3660 if (srb->SenseInfoBuffer) { 3661 ExFreePool(srb->SenseInfoBuffer); 3662 } 3663 ExFreePool(srb); 3664 } 3665 3666 if (realIrp->PendingReturned) { 3667 IoMarkIrpPending(realIrp); 3668 } 3669 3670 if (Irp->MdlAddress) { 3671 IoFreeMdl(Irp->MdlAddress); 3672 } 3673 3674 IoFreeIrp(Irp); 3675 3676 // 3677 // Set status in completing IRP. 3678 // 3679 3680 realIrp->IoStatus.Status = status; 3681 3682 // 3683 // Set the hard error if necessary. 3684 // 3685 3686 if (!NT_SUCCESS(status) && IoIsErrorUserInduced(status)) { 3687 3688 // 3689 // Store DeviceObject for filesystem, and clear 3690 // in IoStatus.Information field. 3691 // 3692 3693 DebugPrint((1, "CdRomDeviceCompletion - Setting Hard Error on realIrp %lx\n", 3694 realIrp)); 3695 IoSetHardErrorOrVerifyDevice(realIrp, DeviceObject); 3696 realIrp->IoStatus.Information = 0; 3697 } 3698 3699 IoCompleteRequest(realIrp, IO_DISK_INCREMENT); 3700 3701 IoStartNextPacket(DeviceObject, FALSE); 3702 3703 return STATUS_MORE_PROCESSING_REQUIRED; 3704 } 3705 3706 NTSTATUS 3707 NTAPI 3708 CdRomSetVolumeIntermediateCompletion( 3709 IN PDEVICE_OBJECT DeviceObject, 3710 IN PIRP Irp, 3711 IN PVOID Context 3712 ) 3713 { 3714 PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension; 3715 PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp); 3716 PCDROM_DATA cdData = (PCDROM_DATA)(deviceExtension + 1); 3717 BOOLEAN use6Byte = cdData->XAFlags & XA_USE_6_BYTE; 3718 PIO_STACK_LOCATION realIrpStack; 3719 PIO_STACK_LOCATION realIrpNextStack; 3720 PSCSI_REQUEST_BLOCK srb = Context; 3721 PIRP realIrp = NULL; 3722 NTSTATUS status; 3723 BOOLEAN retry; 3724 3725 // 3726 // Extract the 'real' irp from the irpstack. 3727 // 3728 3729 realIrp = (PIRP) irpStack->Parameters.Others.Argument2; 3730 realIrpStack = IoGetCurrentIrpStackLocation(realIrp); 3731 realIrpNextStack = IoGetNextIrpStackLocation(realIrp); 3732 3733 // 3734 // Check SRB status for success of completing request. 3735 // 3736 3737 if (SRB_STATUS(srb->SrbStatus) != SRB_STATUS_SUCCESS) { 3738 3739 DebugPrint((2, 3740 "CdRomSetVolumeIntermediateCompletion: Irp %lx, Srb %lx Real Irp\n", 3741 Irp, 3742 srb, 3743 realIrp)); 3744 3745 // 3746 // Release the queue if it is frozen. 3747 // 3748 3749 if (srb->SrbStatus & SRB_STATUS_QUEUE_FROZEN) { 3750 ScsiClassReleaseQueue(DeviceObject); 3751 } 3752 3753 3754 retry = ScsiClassInterpretSenseInfo(DeviceObject, 3755 srb, 3756 irpStack->MajorFunction, 3757 irpStack->Parameters.DeviceIoControl.IoControlCode, 3758 MAXIMUM_RETRIES - ((ULONG_PTR)realIrpNextStack->Parameters.Others.Argument1), 3759 &status); 3760 3761 if (status == STATUS_DATA_OVERRUN) { 3762 status = STATUS_SUCCESS; 3763 retry = FALSE; 3764 } 3765 3766 // 3767 // If the status is verified required and the this request 3768 // should bypass verify required then retry the request. 3769 // 3770 3771 if (realIrpStack->Flags & SL_OVERRIDE_VERIFY_VOLUME && 3772 status == STATUS_VERIFY_REQUIRED) { 3773 3774 status = STATUS_IO_DEVICE_ERROR; 3775 retry = TRUE; 3776 } 3777 3778 if (retry && (realIrpNextStack->Parameters.Others.Argument1 = (PVOID)((ULONG_PTR)realIrpNextStack->Parameters.Others.Argument1-1))) { 3779 3780 if (((ULONG_PTR)realIrpNextStack->Parameters.Others.Argument1)) { 3781 3782 // 3783 // Retry request. 3784 // 3785 3786 DebugPrint((1, "Retry request %lx - Calling StartIo\n", Irp)); 3787 3788 3789 ExFreePool(srb->SenseInfoBuffer); 3790 ExFreePool(srb->DataBuffer); 3791 ExFreePool(srb); 3792 if (Irp->MdlAddress) { 3793 IoFreeMdl(Irp->MdlAddress); 3794 } 3795 3796 IoFreeIrp(Irp); 3797 3798 // 3799 // Call StartIo directly since IoStartNextPacket hasn't been called, 3800 // the serialisation is still intact. 3801 // 3802 ScsiCdRomStartIo(DeviceObject, realIrp); 3803 return STATUS_MORE_PROCESSING_REQUIRED; 3804 3805 } 3806 3807 // 3808 // Exhausted retries. Fall through and complete the request with the appropriate status. 3809 // 3810 3811 } 3812 } else { 3813 3814 // 3815 // Set status for successful request. 3816 // 3817 3818 status = STATUS_SUCCESS; 3819 } 3820 3821 if (NT_SUCCESS(status)) { 3822 3823 PAUDIO_OUTPUT audioInput = NULL; 3824 PAUDIO_OUTPUT audioOutput; 3825 PVOLUME_CONTROL volumeControl = realIrp->AssociatedIrp.SystemBuffer; 3826 ULONG i,bytesTransferred,headerLength; 3827 PVOID dataBuffer; 3828 PCDB cdb; 3829 3830 audioInput = ScsiClassFindModePage((PCHAR)srb->DataBuffer, 3831 srb->DataTransferLength, 3832 CDROM_AUDIO_CONTROL_PAGE, 3833 use6Byte); 3834 3835 // 3836 // Check to make sure the mode sense data is valid before we go on 3837 // 3838 3839 if(audioInput == NULL) { 3840 3841 DebugPrint((1, "Mode Sense Page %d not found\n", 3842 CDROM_AUDIO_CONTROL_PAGE)); 3843 3844 realIrp->IoStatus.Information = 0; 3845 realIrp->IoStatus.Status = STATUS_IO_DEVICE_ERROR; 3846 IoCompleteRequest(realIrp, IO_DISK_INCREMENT); 3847 ExFreePool(srb->SenseInfoBuffer); 3848 ExFreePool(srb); 3849 IoFreeMdl(Irp->MdlAddress); 3850 IoFreeIrp(Irp); 3851 return STATUS_MORE_PROCESSING_REQUIRED; 3852 } 3853 3854 if (use6Byte) { 3855 headerLength = sizeof(MODE_PARAMETER_HEADER); 3856 } else { 3857 headerLength = sizeof(MODE_PARAMETER_HEADER10); 3858 } 3859 3860 bytesTransferred = sizeof(AUDIO_OUTPUT) + headerLength; 3861 3862 // 3863 // Allocate a new buffer for the mode select. 3864 // 3865 3866 dataBuffer = ExAllocatePool(NonPagedPoolCacheAligned, bytesTransferred); 3867 3868 if (!dataBuffer) { 3869 realIrp->IoStatus.Information = 0; 3870 realIrp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; 3871 IoCompleteRequest(realIrp, IO_DISK_INCREMENT); 3872 ExFreePool(srb->SenseInfoBuffer); 3873 ExFreePool(srb); 3874 IoFreeMdl(Irp->MdlAddress); 3875 IoFreeIrp(Irp); 3876 return STATUS_MORE_PROCESSING_REQUIRED; 3877 } 3878 3879 RtlZeroMemory(dataBuffer, bytesTransferred); 3880 3881 // 3882 // Rebuild the data buffer to include the user requested values. 3883 // 3884 3885 audioOutput = (PAUDIO_OUTPUT) ((PCHAR) dataBuffer + headerLength); 3886 3887 for (i=0; i<4; i++) { 3888 audioOutput->PortOutput[i].Volume = 3889 volumeControl->PortVolume[i]; 3890 audioOutput->PortOutput[i].ChannelSelection = 3891 audioInput->PortOutput[i].ChannelSelection; 3892 } 3893 3894 audioOutput->CodePage = CDROM_AUDIO_CONTROL_PAGE; 3895 audioOutput->ParameterLength = sizeof(AUDIO_OUTPUT) - 2; 3896 audioOutput->Immediate = MODE_SELECT_IMMEDIATE; 3897 3898 // 3899 // Free the old data buffer, mdl. 3900 // 3901 3902 ExFreePool(srb->DataBuffer); 3903 IoFreeMdl(Irp->MdlAddress); 3904 3905 // 3906 // rebuild the srb. 3907 // 3908 3909 cdb = (PCDB)srb->Cdb; 3910 RtlZeroMemory(cdb, CDB12GENERIC_LENGTH); 3911 3912 srb->SrbStatus = srb->ScsiStatus = 0; 3913 srb->SrbFlags = deviceExtension->SrbFlags; 3914 srb->SrbFlags |= (SRB_FLAGS_DISABLE_SYNCH_TRANSFER | SRB_FLAGS_DATA_OUT); 3915 srb->DataTransferLength = bytesTransferred; 3916 3917 if (use6Byte) { 3918 3919 cdb->MODE_SELECT.OperationCode = SCSIOP_MODE_SELECT; 3920 cdb->MODE_SELECT.ParameterListLength = (UCHAR) bytesTransferred; 3921 cdb->MODE_SELECT.PFBit = 1; 3922 srb->CdbLength = 6; 3923 } else { 3924 3925 cdb->MODE_SELECT10.OperationCode = SCSIOP_MODE_SELECT10; 3926 cdb->MODE_SELECT10.ParameterListLength[0] = (UCHAR) (bytesTransferred >> 8); 3927 cdb->MODE_SELECT10.ParameterListLength[1] = (UCHAR) (bytesTransferred & 0xFF); 3928 cdb->MODE_SELECT10.PFBit = 1; 3929 srb->CdbLength = 10; 3930 } 3931 3932 // 3933 // Prepare the MDL 3934 // 3935 3936 Irp->MdlAddress = IoAllocateMdl(dataBuffer, 3937 bytesTransferred, 3938 FALSE, 3939 FALSE, 3940 (PIRP) NULL); 3941 3942 if (!Irp->MdlAddress) { 3943 realIrp->IoStatus.Information = 0; 3944 realIrp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; 3945 IoCompleteRequest(realIrp, IO_DISK_INCREMENT); 3946 ExFreePool(srb->SenseInfoBuffer); 3947 ExFreePool(srb); 3948 ExFreePool(dataBuffer); 3949 IoFreeIrp(Irp); 3950 return STATUS_MORE_PROCESSING_REQUIRED; 3951 3952 } 3953 3954 MmBuildMdlForNonPagedPool(Irp->MdlAddress); 3955 srb->DataBuffer = dataBuffer; 3956 3957 irpStack = IoGetNextIrpStackLocation(Irp); 3958 irpStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL; 3959 irpStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_SCSI_EXECUTE_IN; 3960 irpStack->Parameters.Scsi.Srb = srb; 3961 3962 // 3963 // reset the irp completion. 3964 // 3965 3966 IoSetCompletionRoutine(Irp, 3967 CdRomDeviceControlCompletion, 3968 srb, 3969 TRUE, 3970 TRUE, 3971 TRUE); 3972 // 3973 // Call the port driver. 3974 // 3975 3976 IoCallDriver(deviceExtension->PortDeviceObject, Irp); 3977 3978 return STATUS_MORE_PROCESSING_REQUIRED; 3979 } 3980 3981 // 3982 // Deallocate srb and sense buffer. 3983 // 3984 3985 if (srb) { 3986 if (srb->DataBuffer) { 3987 ExFreePool(srb->DataBuffer); 3988 } 3989 if (srb->SenseInfoBuffer) { 3990 ExFreePool(srb->SenseInfoBuffer); 3991 } 3992 ExFreePool(srb); 3993 } 3994 3995 if (Irp->PendingReturned) { 3996 IoMarkIrpPending(Irp); 3997 } 3998 3999 if (realIrp->PendingReturned) { 4000 IoMarkIrpPending(realIrp); 4001 } 4002 4003 if (Irp->MdlAddress) { 4004 IoFreeMdl(Irp->MdlAddress); 4005 } 4006 4007 IoFreeIrp(Irp); 4008 4009 // 4010 // Set status in completing IRP. 4011 // 4012 4013 realIrp->IoStatus.Status = status; 4014 4015 // 4016 // Set the hard error if necessary. 4017 // 4018 4019 if (!NT_SUCCESS(status) && IoIsErrorUserInduced(status)) { 4020 4021 // 4022 // Store DeviceObject for filesystem, and clear 4023 // in IoStatus.Information field. 4024 // 4025 4026 IoSetHardErrorOrVerifyDevice(realIrp, DeviceObject); 4027 realIrp->IoStatus.Information = 0; 4028 } 4029 4030 IoCompleteRequest(realIrp, IO_DISK_INCREMENT); 4031 4032 IoStartNextPacket(DeviceObject, FALSE); 4033 4034 return STATUS_MORE_PROCESSING_REQUIRED; 4035 } 4036 4037 4038 NTSTATUS 4039 NTAPI 4040 CdRomSwitchModeCompletion( 4041 IN PDEVICE_OBJECT DeviceObject, 4042 IN PIRP Irp, 4043 IN PVOID Context 4044 ) 4045 { 4046 PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension; 4047 PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp); 4048 PCDROM_DATA cdData = (PCDROM_DATA)(deviceExtension + 1); 4049 PIO_STACK_LOCATION realIrpStack; 4050 PIO_STACK_LOCATION realIrpNextStack; 4051 PSCSI_REQUEST_BLOCK srb = Context; 4052 PIRP realIrp = NULL; 4053 NTSTATUS status; 4054 BOOLEAN retry; 4055 4056 // 4057 // Extract the 'real' irp from the irpstack. 4058 // 4059 4060 realIrp = (PIRP) irpStack->Parameters.Others.Argument2; 4061 realIrpStack = IoGetCurrentIrpStackLocation(realIrp); 4062 realIrpNextStack = IoGetNextIrpStackLocation(realIrp); 4063 4064 // 4065 // Check SRB status for success of completing request. 4066 // 4067 4068 if (SRB_STATUS(srb->SrbStatus) != SRB_STATUS_SUCCESS) { 4069 4070 DebugPrint((2, 4071 "CdRomSetVolumeIntermediateCompletion: Irp %lx, Srb %lx Real Irp\n", 4072 Irp, 4073 srb, 4074 realIrp)); 4075 4076 // 4077 // Release the queue if it is frozen. 4078 // 4079 4080 if (srb->SrbStatus & SRB_STATUS_QUEUE_FROZEN) { 4081 ScsiClassReleaseQueue(DeviceObject); 4082 } 4083 4084 4085 retry = ScsiClassInterpretSenseInfo(DeviceObject, 4086 srb, 4087 irpStack->MajorFunction, 4088 irpStack->Parameters.DeviceIoControl.IoControlCode, 4089 MAXIMUM_RETRIES - ((ULONG_PTR)realIrpNextStack->Parameters.Others.Argument1), 4090 &status); 4091 4092 // 4093 // If the status is verified required and the this request 4094 // should bypass verify required then retry the request. 4095 // 4096 4097 if (realIrpStack->Flags & SL_OVERRIDE_VERIFY_VOLUME && 4098 status == STATUS_VERIFY_REQUIRED) { 4099 4100 status = STATUS_IO_DEVICE_ERROR; 4101 retry = TRUE; 4102 } 4103 4104 if (retry && (realIrpNextStack->Parameters.Others.Argument1 = (PVOID)((ULONG_PTR)realIrpNextStack->Parameters.Others.Argument1-1))) { 4105 4106 if (((ULONG_PTR)realIrpNextStack->Parameters.Others.Argument1)) { 4107 4108 // 4109 // Retry request. 4110 // 4111 4112 DebugPrint((1, "Retry request %lx - Calling StartIo\n", Irp)); 4113 4114 4115 ExFreePool(srb->SenseInfoBuffer); 4116 ExFreePool(srb->DataBuffer); 4117 ExFreePool(srb); 4118 if (Irp->MdlAddress) { 4119 IoFreeMdl(Irp->MdlAddress); 4120 } 4121 4122 IoFreeIrp(Irp); 4123 4124 // 4125 // Call StartIo directly since IoStartNextPacket hasn't been called, 4126 // the serialisation is still intact. 4127 // 4128 4129 ScsiCdRomStartIo(DeviceObject, realIrp); 4130 return STATUS_MORE_PROCESSING_REQUIRED; 4131 4132 } 4133 4134 // 4135 // Exhausted retries. Fall through and complete the request with the appropriate status. 4136 // 4137 } 4138 } else { 4139 4140 // 4141 // Set status for successful request. 4142 // 4143 4144 status = STATUS_SUCCESS; 4145 } 4146 4147 if (NT_SUCCESS(status)) { 4148 4149 ULONG sectorSize, startingSector, transferByteCount; 4150 PCDB cdb; 4151 4152 // 4153 // Update device ext. to show which mode we are currently using. 4154 // 4155 4156 sectorSize = cdData->u1.BlockDescriptor.BlockLength[0] << 16; 4157 sectorSize |= (cdData->u1.BlockDescriptor.BlockLength[1] << 8); 4158 sectorSize |= (cdData->u1.BlockDescriptor.BlockLength[2]); 4159 4160 cdData->RawAccess = (sectorSize == RAW_SECTOR_SIZE) ? TRUE : FALSE; 4161 4162 // 4163 // Free the old data buffer, mdl. 4164 // 4165 4166 ExFreePool(srb->DataBuffer); 4167 IoFreeMdl(Irp->MdlAddress); 4168 IoFreeIrp(Irp); 4169 4170 // 4171 // rebuild the srb. 4172 // 4173 4174 cdb = (PCDB)srb->Cdb; 4175 RtlZeroMemory(cdb, CDB12GENERIC_LENGTH); 4176 4177 4178 if (cdData->RawAccess) { 4179 4180 PRAW_READ_INFO rawReadInfo = 4181 (PRAW_READ_INFO)realIrpStack->Parameters.DeviceIoControl.Type3InputBuffer; 4182 4183 ULONG maximumTransferLength; 4184 ULONG transferPages; 4185 4186 // 4187 // Calculate starting offset. 4188 // 4189 4190 startingSector = (ULONG)(rawReadInfo->DiskOffset.QuadPart >> deviceExtension->SectorShift); 4191 transferByteCount = rawReadInfo->SectorCount * RAW_SECTOR_SIZE; 4192 maximumTransferLength = deviceExtension->PortCapabilities->MaximumTransferLength; 4193 transferPages = ADDRESS_AND_SIZE_TO_SPAN_PAGES(MmGetMdlVirtualAddress(realIrp->MdlAddress), 4194 transferByteCount); 4195 4196 // 4197 // Determine if request is within limits imposed by miniport. 4198 // If the request is larger than the miniport's capabilities, split it. 4199 // 4200 4201 if (transferByteCount > maximumTransferLength || 4202 transferPages > deviceExtension->PortCapabilities->MaximumPhysicalPages) { 4203 4204 realIrp->IoStatus.Information = 0; 4205 realIrp->IoStatus.Status = STATUS_INVALID_PARAMETER; 4206 IoCompleteRequest(realIrp, IO_DISK_INCREMENT); 4207 4208 ExFreePool(srb->SenseInfoBuffer); 4209 ExFreePool(srb); 4210 4211 IoStartNextPacket(DeviceObject, FALSE); 4212 4213 return STATUS_MORE_PROCESSING_REQUIRED; 4214 } 4215 4216 srb->OriginalRequest = realIrp; 4217 srb->SrbFlags = deviceExtension->SrbFlags; 4218 srb->SrbFlags |= (SRB_FLAGS_DISABLE_SYNCH_TRANSFER | SRB_FLAGS_DATA_IN); 4219 srb->DataTransferLength = transferByteCount; 4220 srb->TimeOutValue = deviceExtension->TimeOutValue; 4221 srb->CdbLength = 10; 4222 srb->DataBuffer = MmGetMdlVirtualAddress(realIrp->MdlAddress); 4223 4224 if (rawReadInfo->TrackMode == CDDA) { 4225 if (cdData->XAFlags & PLEXTOR_CDDA) { 4226 4227 srb->CdbLength = 12; 4228 4229 cdb->PLXTR_READ_CDDA.LogicalUnitNumber = deviceExtension->Lun; 4230 cdb->PLXTR_READ_CDDA.LogicalBlockByte3 = (UCHAR) (startingSector & 0xFF); 4231 cdb->PLXTR_READ_CDDA.LogicalBlockByte2 = (UCHAR) ((startingSector >> 8) & 0xFF); 4232 cdb->PLXTR_READ_CDDA.LogicalBlockByte1 = (UCHAR) ((startingSector >> 16) & 0xFF); 4233 cdb->PLXTR_READ_CDDA.LogicalBlockByte0 = (UCHAR) ((startingSector >> 24) & 0xFF); 4234 4235 cdb->PLXTR_READ_CDDA.TransferBlockByte3 = (UCHAR) (rawReadInfo->SectorCount & 0xFF); 4236 cdb->PLXTR_READ_CDDA.TransferBlockByte2 = (UCHAR) (rawReadInfo->SectorCount >> 8); 4237 cdb->PLXTR_READ_CDDA.TransferBlockByte1 = 0; 4238 cdb->PLXTR_READ_CDDA.TransferBlockByte0 = 0; 4239 4240 cdb->PLXTR_READ_CDDA.SubCode = 0; 4241 cdb->PLXTR_READ_CDDA.OperationCode = 0xD8; 4242 4243 } else if (cdData->XAFlags & NEC_CDDA) { 4244 4245 cdb->NEC_READ_CDDA.LogicalBlockByte3 = (UCHAR) (startingSector & 0xFF); 4246 cdb->NEC_READ_CDDA.LogicalBlockByte2 = (UCHAR) ((startingSector >> 8) & 0xFF); 4247 cdb->NEC_READ_CDDA.LogicalBlockByte1 = (UCHAR) ((startingSector >> 16) & 0xFF); 4248 cdb->NEC_READ_CDDA.LogicalBlockByte0 = (UCHAR) ((startingSector >> 24) & 0xFF); 4249 4250 cdb->NEC_READ_CDDA.TransferBlockByte1 = (UCHAR) (rawReadInfo->SectorCount & 0xFF); 4251 cdb->NEC_READ_CDDA.TransferBlockByte0 = (UCHAR) (rawReadInfo->SectorCount >> 8); 4252 4253 cdb->NEC_READ_CDDA.OperationCode = 0xD4; 4254 } 4255 } else { 4256 cdb->CDB10.LogicalUnitNumber = deviceExtension->Lun; 4257 4258 cdb->CDB10.TransferBlocksMsb = (UCHAR) (rawReadInfo->SectorCount >> 8); 4259 cdb->CDB10.TransferBlocksLsb = (UCHAR) (rawReadInfo->SectorCount & 0xFF); 4260 4261 cdb->CDB10.LogicalBlockByte3 = (UCHAR) (startingSector & 0xFF); 4262 cdb->CDB10.LogicalBlockByte2 = (UCHAR) ((startingSector >> 8) & 0xFF); 4263 cdb->CDB10.LogicalBlockByte1 = (UCHAR) ((startingSector >> 16) & 0xFF); 4264 cdb->CDB10.LogicalBlockByte0 = (UCHAR) ((startingSector >> 24) & 0xFF); 4265 4266 cdb->CDB10.OperationCode = SCSIOP_READ; 4267 } 4268 4269 srb->SrbStatus = srb->ScsiStatus = 0; 4270 4271 4272 irpStack = IoGetNextIrpStackLocation(realIrp); 4273 irpStack->MajorFunction = IRP_MJ_SCSI; 4274 irpStack->Parameters.Scsi.Srb = srb; 4275 4276 if (!(irpStack->Parameters.Others.Argument1)) { 4277 4278 // 4279 // Only jam this in if it doesn't exist. The completion routines can 4280 // call StartIo directly in the case of retries and resetting it will 4281 // cause infinite loops. 4282 // 4283 4284 irpStack->Parameters.Others.Argument1 = (PVOID) MAXIMUM_RETRIES; 4285 } 4286 4287 // 4288 // Set up IoCompletion routine address. 4289 // 4290 4291 IoSetCompletionRoutine(realIrp, 4292 CdRomXACompletion, 4293 srb, 4294 TRUE, 4295 TRUE, 4296 TRUE); 4297 } else { 4298 4299 ULONG maximumTransferLength = deviceExtension->PortCapabilities->MaximumTransferLength; 4300 ULONG transferPages = ADDRESS_AND_SIZE_TO_SPAN_PAGES(MmGetMdlVirtualAddress(realIrp->MdlAddress), 4301 realIrpStack->Parameters.Read.Length); 4302 // 4303 // Back to cooked sectors. Build and send a normal read. 4304 // The real work for setting offsets and checking for splitrequests was 4305 // done in startio 4306 // 4307 4308 if ((realIrpStack->Parameters.Read.Length > maximumTransferLength) || 4309 (transferPages > deviceExtension->PortCapabilities->MaximumPhysicalPages)) { 4310 4311 // 4312 // Request needs to be split. Completion of each portion of the request will 4313 // fire off the next portion. The final request will signal Io to send a new request. 4314 // 4315 4316 ScsiClassSplitRequest(DeviceObject, realIrp, maximumTransferLength); 4317 return STATUS_MORE_PROCESSING_REQUIRED; 4318 4319 } else { 4320 4321 // 4322 // Build SRB and CDB for this IRP. 4323 // 4324 4325 ScsiClassBuildRequest(DeviceObject, realIrp); 4326 4327 } 4328 } 4329 4330 // 4331 // Call the port driver. 4332 // 4333 4334 IoCallDriver(deviceExtension->PortDeviceObject, realIrp); 4335 4336 return STATUS_MORE_PROCESSING_REQUIRED; 4337 } 4338 4339 // 4340 // Update device Extension flags to indicate that XA isn't supported. 4341 // 4342 4343 cdData->XAFlags |= XA_NOT_SUPPORTED; 4344 4345 // 4346 // Deallocate srb and sense buffer. 4347 // 4348 4349 if (srb) { 4350 if (srb->DataBuffer) { 4351 ExFreePool(srb->DataBuffer); 4352 } 4353 if (srb->SenseInfoBuffer) { 4354 ExFreePool(srb->SenseInfoBuffer); 4355 } 4356 ExFreePool(srb); 4357 } 4358 4359 if (Irp->PendingReturned) { 4360 IoMarkIrpPending(Irp); 4361 } 4362 4363 if (realIrp->PendingReturned) { 4364 IoMarkIrpPending(realIrp); 4365 } 4366 4367 if (Irp->MdlAddress) { 4368 IoFreeMdl(Irp->MdlAddress); 4369 } 4370 4371 IoFreeIrp(Irp); 4372 4373 // 4374 // Set status in completing IRP. 4375 // 4376 4377 realIrp->IoStatus.Status = status; 4378 4379 // 4380 // Set the hard error if necessary. 4381 // 4382 4383 if (!NT_SUCCESS(status) && IoIsErrorUserInduced(status)) { 4384 4385 // 4386 // Store DeviceObject for filesystem, and clear 4387 // in IoStatus.Information field. 4388 // 4389 4390 IoSetHardErrorOrVerifyDevice(realIrp, DeviceObject); 4391 realIrp->IoStatus.Information = 0; 4392 } 4393 4394 IoCompleteRequest(realIrp, IO_DISK_INCREMENT); 4395 4396 IoStartNextPacket(DeviceObject, FALSE); 4397 4398 return STATUS_MORE_PROCESSING_REQUIRED; 4399 } 4400 4401 NTSTATUS 4402 NTAPI 4403 CdRomXACompletion( 4404 IN PDEVICE_OBJECT DeviceObject, 4405 IN PIRP Irp, 4406 IN PVOID Context 4407 ) 4408 4409 /*++ 4410 4411 Routine Description: 4412 4413 This routine executes when the port driver has completed a request. 4414 It looks at the SRB status in the completing SRB and if not success 4415 it checks for valid request sense buffer information. If valid, the 4416 info is used to update status with more precise message of type of 4417 error. This routine deallocates the SRB. 4418 4419 Arguments: 4420 4421 DeviceObject - Supplies the device object which represents the logical 4422 unit. 4423 4424 Irp - Supplies the Irp which has completed. 4425 4426 Context - Supplies a pointer to the SRB. 4427 4428 Return Value: 4429 4430 NT status 4431 4432 --*/ 4433 4434 { 4435 PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp); 4436 PIO_STACK_LOCATION irpNextStack = IoGetNextIrpStackLocation(Irp); 4437 PSCSI_REQUEST_BLOCK srb = Context; 4438 NTSTATUS status; 4439 BOOLEAN retry; 4440 4441 // 4442 // Check SRB status for success of completing request. 4443 // 4444 4445 if (SRB_STATUS(srb->SrbStatus) != SRB_STATUS_SUCCESS) { 4446 4447 DebugPrint((2,"ScsiClassIoComplete: IRP %lx, SRB %lx\n", Irp, srb)); 4448 4449 // 4450 // Release the queue if it is frozen. 4451 // 4452 4453 if (srb->SrbStatus & SRB_STATUS_QUEUE_FROZEN) { 4454 ScsiClassReleaseQueue(DeviceObject); 4455 } 4456 4457 retry = ScsiClassInterpretSenseInfo( 4458 DeviceObject, 4459 srb, 4460 irpStack->MajorFunction, 4461 irpStack->MajorFunction == IRP_MJ_DEVICE_CONTROL ? irpStack->Parameters.DeviceIoControl.IoControlCode : 0, 4462 MAXIMUM_RETRIES - ((ULONG_PTR)irpNextStack->Parameters.Others.Argument1), 4463 &status); 4464 4465 // 4466 // If the status is verified required and the this request 4467 // should bypass verify required then retry the request. 4468 // 4469 4470 if (irpStack->Flags & SL_OVERRIDE_VERIFY_VOLUME && 4471 status == STATUS_VERIFY_REQUIRED) { 4472 4473 status = STATUS_IO_DEVICE_ERROR; 4474 retry = TRUE; 4475 } 4476 4477 if (retry && (irpNextStack->Parameters.Others.Argument1 = (PVOID)((ULONG_PTR)irpNextStack->Parameters.Others.Argument1-1))) { 4478 4479 if (((ULONG_PTR)irpNextStack->Parameters.Others.Argument1)) { 4480 4481 // 4482 // Retry request. 4483 // 4484 4485 DebugPrint((1, "CdRomXACompletion: Retry request %lx - Calling StartIo\n", Irp)); 4486 4487 4488 ExFreePool(srb->SenseInfoBuffer); 4489 ExFreePool(srb->DataBuffer); 4490 ExFreePool(srb); 4491 4492 // 4493 // Call StartIo directly since IoStartNextPacket hasn't been called, 4494 // the serialisation is still intact. 4495 // 4496 4497 ScsiCdRomStartIo(DeviceObject, Irp); 4498 return STATUS_MORE_PROCESSING_REQUIRED; 4499 4500 } 4501 4502 // 4503 // Exhausted retries. Fall through and complete the request with the appropriate status. 4504 // 4505 } 4506 } else { 4507 4508 // 4509 // Set status for successful request. 4510 // 4511 4512 status = STATUS_SUCCESS; 4513 4514 } // end if (SRB_STATUS(srb->SrbStatus) ... 4515 4516 // 4517 // Return SRB to nonpaged pool. 4518 // 4519 4520 ExFreePool(srb); 4521 4522 // 4523 // Set status in completing IRP. 4524 // 4525 4526 Irp->IoStatus.Status = status; 4527 4528 // 4529 // Set the hard error if necessary. 4530 // 4531 4532 if (!NT_SUCCESS(status) && IoIsErrorUserInduced(status)) { 4533 4534 // 4535 // Store DeviceObject for filesystem, and clear 4536 // in IoStatus.Information field. 4537 // 4538 4539 IoSetHardErrorOrVerifyDevice(Irp, DeviceObject); 4540 Irp->IoStatus.Information = 0; 4541 } 4542 4543 // 4544 // If pending has be returned for this irp then mark the current stack as 4545 // pending. 4546 // 4547 4548 if (Irp->PendingReturned) { 4549 IoMarkIrpPending(Irp); 4550 } 4551 4552 //IoCompleteRequest(Irp, IO_DISK_INCREMENT); 4553 IoStartNextPacket(DeviceObject, FALSE); 4554 4555 return status; 4556 } 4557 4558 NTSTATUS 4559 NTAPI 4560 CdRomDeviceControl( 4561 IN PDEVICE_OBJECT DeviceObject, 4562 IN PIRP Irp 4563 ) 4564 4565 /*++ 4566 4567 Routine Description: 4568 4569 This is the NT device control handler for CDROMs. 4570 4571 Arguments: 4572 4573 DeviceObject - for this CDROM 4574 4575 Irp - IO Request packet 4576 4577 Return Value: 4578 4579 NTSTATUS 4580 4581 --*/ 4582 4583 { 4584 PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp); 4585 PIO_STACK_LOCATION nextStack; 4586 PKEVENT deviceControlEvent; 4587 PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension; 4588 PCDROM_DATA cdData = (PCDROM_DATA)(deviceExtension+1); 4589 SCSI_REQUEST_BLOCK srb; 4590 NTSTATUS status; 4591 KIRQL irql; 4592 4593 ULONG ioctlCode; 4594 ULONG baseCode; 4595 ULONG functionCode; 4596 4597 RetryControl: 4598 4599 // 4600 // Zero the SRB on stack. 4601 // 4602 4603 RtlZeroMemory(&srb, sizeof(SCSI_REQUEST_BLOCK)); 4604 4605 Irp->IoStatus.Information = 0; 4606 4607 // 4608 // if this is a class driver ioctl then we need to change the base code 4609 // to IOCTL_CDROM_BASE so that the switch statement can handle it. 4610 // 4611 // WARNING - currently the scsi class ioctl function codes are between 4612 // 0x200 & 0x300. this routine depends on that fact 4613 // 4614 4615 ioctlCode = irpStack->Parameters.DeviceIoControl.IoControlCode; 4616 baseCode = ioctlCode >> 16; 4617 functionCode = (ioctlCode & (~0xffffc003)) >> 2; 4618 4619 DebugPrint((1, "CdRomDeviceControl: Ioctl Code = %#08lx, Base Code = %#lx," 4620 " Function Code = %#lx\n", 4621 ioctlCode, 4622 baseCode, 4623 functionCode 4624 )); 4625 4626 if((functionCode >= 0x200) && (functionCode <= 0x300)) { 4627 4628 ioctlCode = (ioctlCode & 0x0000ffff) | CTL_CODE(IOCTL_CDROM_BASE, 0, 0, 0); 4629 4630 DebugPrint((1, "CdRomDeviceControl: Class Code - new ioctl code is %#08lx\n", 4631 ioctlCode)); 4632 4633 irpStack->Parameters.DeviceIoControl.IoControlCode = ioctlCode; 4634 4635 } 4636 4637 switch (ioctlCode) { 4638 4639 case IOCTL_CDROM_RAW_READ: { 4640 4641 LARGE_INTEGER startingOffset; 4642 ULONG transferBytes; 4643 PRAW_READ_INFO rawReadInfo = (PRAW_READ_INFO)irpStack->Parameters.DeviceIoControl.Type3InputBuffer; 4644 PUCHAR userData = (PUCHAR)Irp->AssociatedIrp.SystemBuffer; 4645 4646 // 4647 // Ensure that XA reads are supported. 4648 // 4649 4650 if (cdData->XAFlags & XA_NOT_SUPPORTED) { 4651 4652 DebugPrint((1, 4653 "CdRomDeviceControl: XA Reads not supported. Flags (%x)\n", 4654 cdData->XAFlags)); 4655 4656 status = STATUS_INVALID_DEVICE_REQUEST; 4657 break; 4658 } 4659 4660 // 4661 // Check that ending sector is on disc and buffers are there and of 4662 // correct size. 4663 // 4664 4665 if (rawReadInfo == NULL) { 4666 4667 // 4668 // Called from user space. Validate the buffers. 4669 // 4670 4671 rawReadInfo = (PRAW_READ_INFO)userData; 4672 irpStack->Parameters.DeviceIoControl.Type3InputBuffer = (PVOID)userData; 4673 4674 if (rawReadInfo == NULL) { 4675 4676 DebugPrint((1,"CdRomDeviceControl: Invalid I/O parameters for XA Read (No extent info\n")); 4677 4678 Irp->IoStatus.Status = STATUS_INVALID_PARAMETER; 4679 4680 IoCompleteRequest(Irp, IO_NO_INCREMENT); 4681 return STATUS_INVALID_PARAMETER; 4682 } 4683 4684 if (irpStack->Parameters.DeviceIoControl.InputBufferLength != sizeof(RAW_READ_INFO)) { 4685 4686 DebugPrint((1,"CdRomDeviceControl: Invalid I/O parameters for XA Read (Invalid info buffer\n")); 4687 4688 Irp->IoStatus.Status = STATUS_INVALID_PARAMETER; 4689 4690 IoCompleteRequest(Irp, IO_NO_INCREMENT); 4691 return STATUS_INVALID_PARAMETER; 4692 } 4693 } 4694 4695 startingOffset.QuadPart = rawReadInfo->DiskOffset.QuadPart; 4696 transferBytes = rawReadInfo->SectorCount * RAW_SECTOR_SIZE; 4697 4698 if (irpStack->Parameters.DeviceIoControl.OutputBufferLength < transferBytes) { 4699 4700 DebugPrint((1,"CdRomDeviceControl: Invalid I/O parameters for XA Read (Bad buffer size)\n")); 4701 4702 // 4703 // Fail request with status of invalid parameters. 4704 // 4705 4706 Irp->IoStatus.Status = STATUS_INVALID_PARAMETER; 4707 4708 IoCompleteRequest(Irp, IO_NO_INCREMENT); 4709 return STATUS_INVALID_PARAMETER; 4710 } 4711 4712 if ((startingOffset.QuadPart + transferBytes) > deviceExtension->PartitionLength.QuadPart) { 4713 4714 DebugPrint((1,"CdRomDeviceControl: Invalid I/O parameters for XA Read (Request Out of Bounds)\n")); 4715 4716 // 4717 // Fail request with status of invalid parameters. 4718 // 4719 4720 status = STATUS_INVALID_PARAMETER; 4721 break; 4722 } 4723 4724 IoMarkIrpPending(Irp); 4725 IoStartPacket(DeviceObject, Irp, NULL, NULL); 4726 4727 return STATUS_PENDING; 4728 } 4729 4730 case IOCTL_DISK_GET_DRIVE_GEOMETRY: 4731 case IOCTL_CDROM_GET_DRIVE_GEOMETRY: { 4732 4733 DebugPrint((2,"CdRomDeviceControl: Get drive geometry\n")); 4734 4735 if ( irpStack->Parameters.DeviceIoControl.OutputBufferLength < 4736 sizeof( DISK_GEOMETRY ) ) { 4737 4738 status = STATUS_INFO_LENGTH_MISMATCH; 4739 break; 4740 } 4741 4742 IoMarkIrpPending(Irp); 4743 IoStartPacket(DeviceObject,Irp, NULL,NULL); 4744 4745 return STATUS_PENDING; 4746 } 4747 4748 case IOCTL_DISK_GET_DRIVE_GEOMETRY_EX: 4749 case IOCTL_CDROM_GET_DRIVE_GEOMETRY_EX: { 4750 4751 DebugPrint((2,"CdRomDeviceControl: Get drive geometry ex\n")); 4752 4753 if ( irpStack->Parameters.DeviceIoControl.OutputBufferLength < 4754 sizeof( DISK_GEOMETRY_EX ) ) { 4755 4756 status = STATUS_INFO_LENGTH_MISMATCH; 4757 break; 4758 } 4759 4760 IoMarkIrpPending(Irp); 4761 IoStartPacket(DeviceObject,Irp, NULL,NULL); 4762 4763 return STATUS_PENDING; 4764 } 4765 4766 case IOCTL_DISK_GET_LENGTH_INFO: { 4767 4768 DebugPrint((2,"CdRomDeviceControl: Get length info\n")); 4769 4770 if ( irpStack->Parameters.DeviceIoControl.OutputBufferLength < 4771 sizeof( GET_LENGTH_INFORMATION ) ) { 4772 4773 status = STATUS_INFO_LENGTH_MISMATCH; 4774 break; 4775 } 4776 4777 IoMarkIrpPending(Irp); 4778 IoStartPacket(DeviceObject,Irp, NULL,NULL); 4779 4780 return STATUS_PENDING; 4781 } 4782 4783 case IOCTL_CDROM_GET_LAST_SESSION: 4784 case IOCTL_CDROM_READ_TOC: { 4785 4786 // 4787 // If the cd is playing music then reject this request. 4788 // 4789 4790 if (CdRomIsPlayActive(DeviceObject)) { 4791 Irp->IoStatus.Status = STATUS_DEVICE_BUSY; 4792 IoCompleteRequest(Irp, IO_NO_INCREMENT); 4793 return STATUS_DEVICE_BUSY; 4794 } 4795 4796 IoMarkIrpPending(Irp); 4797 IoStartPacket(DeviceObject, Irp, NULL, NULL); 4798 4799 return STATUS_PENDING; 4800 } 4801 4802 case IOCTL_CDROM_PLAY_AUDIO_MSF: { 4803 4804 // 4805 // Play Audio MSF 4806 // 4807 4808 DebugPrint((2,"CdRomDeviceControl: Play audio MSF\n")); 4809 4810 if (irpStack->Parameters.DeviceIoControl.InputBufferLength < 4811 sizeof(CDROM_PLAY_AUDIO_MSF)) { 4812 4813 // 4814 // Indicate unsuccessful status. 4815 // 4816 4817 status = STATUS_BUFFER_TOO_SMALL; 4818 break; 4819 } 4820 4821 IoMarkIrpPending(Irp); 4822 IoStartPacket(DeviceObject, Irp, NULL, NULL); 4823 4824 return STATUS_PENDING; 4825 } 4826 4827 case IOCTL_CDROM_SEEK_AUDIO_MSF: { 4828 4829 4830 // 4831 // Seek Audio MSF 4832 // 4833 4834 DebugPrint((2,"CdRomDeviceControl: Seek audio MSF\n")); 4835 4836 if (irpStack->Parameters.DeviceIoControl.InputBufferLength < 4837 sizeof(CDROM_SEEK_AUDIO_MSF)) { 4838 4839 // 4840 // Indicate unsuccessful status. 4841 // 4842 4843 status = STATUS_BUFFER_TOO_SMALL; 4844 break; 4845 } else { 4846 IoMarkIrpPending(Irp); 4847 IoStartPacket(DeviceObject, Irp, NULL, NULL); 4848 4849 return STATUS_PENDING; 4850 4851 } 4852 } 4853 4854 case IOCTL_CDROM_PAUSE_AUDIO: { 4855 4856 // 4857 // Pause audio 4858 // 4859 4860 DebugPrint((2, "CdRomDeviceControl: Pause audio\n")); 4861 4862 IoMarkIrpPending(Irp); 4863 IoStartPacket(DeviceObject, Irp, NULL, NULL); 4864 4865 return STATUS_PENDING; 4866 4867 break; 4868 } 4869 4870 case IOCTL_CDROM_RESUME_AUDIO: { 4871 4872 // 4873 // Resume audio 4874 // 4875 4876 DebugPrint((2, "CdRomDeviceControl: Resume audio\n")); 4877 4878 IoMarkIrpPending(Irp); 4879 IoStartPacket(DeviceObject, Irp, NULL, NULL); 4880 4881 return STATUS_PENDING; 4882 } 4883 4884 case IOCTL_CDROM_READ_Q_CHANNEL: { 4885 4886 if(irpStack->Parameters.DeviceIoControl.InputBufferLength < 4887 sizeof(CDROM_SUB_Q_DATA_FORMAT)) { 4888 4889 status = STATUS_BUFFER_TOO_SMALL; 4890 Irp->IoStatus.Information = 0; 4891 break; 4892 } 4893 4894 IoMarkIrpPending(Irp); 4895 IoStartPacket(DeviceObject, Irp, NULL, NULL); 4896 4897 return STATUS_PENDING; 4898 } 4899 4900 case IOCTL_CDROM_GET_CONTROL: { 4901 4902 DebugPrint((2, "CdRomDeviceControl: Get audio control\n")); 4903 4904 // 4905 // Verify user buffer is large enough for the data. 4906 // 4907 4908 if (irpStack->Parameters.DeviceIoControl.OutputBufferLength < 4909 sizeof(CDROM_AUDIO_CONTROL)) { 4910 4911 // 4912 // Indicate unsuccessful status and no data transferred. 4913 // 4914 4915 status = STATUS_BUFFER_TOO_SMALL; 4916 Irp->IoStatus.Information = 0; 4917 break; 4918 4919 } else { 4920 4921 IoMarkIrpPending(Irp); 4922 IoStartPacket(DeviceObject, Irp, NULL, NULL); 4923 4924 return STATUS_PENDING; 4925 } 4926 } 4927 4928 case IOCTL_CDROM_GET_VOLUME: { 4929 4930 DebugPrint((2, "CdRomDeviceControl: Get volume control\n")); 4931 4932 // 4933 // Verify user buffer is large enough for data. 4934 // 4935 4936 if (irpStack->Parameters.DeviceIoControl.OutputBufferLength < 4937 sizeof(VOLUME_CONTROL)) { 4938 4939 // 4940 // Indicate unsuccessful status and no data transferred. 4941 // 4942 4943 status = STATUS_BUFFER_TOO_SMALL; 4944 Irp->IoStatus.Information = 0; 4945 break; 4946 4947 } else { 4948 IoMarkIrpPending(Irp); 4949 IoStartPacket(DeviceObject, Irp, NULL, NULL); 4950 4951 return STATUS_PENDING; 4952 } 4953 } 4954 4955 case IOCTL_CDROM_SET_VOLUME: { 4956 4957 DebugPrint((2, "CdRomDeviceControl: Set volume control\n")); 4958 4959 if (irpStack->Parameters.DeviceIoControl.InputBufferLength < 4960 sizeof(VOLUME_CONTROL)) { 4961 4962 // 4963 // Indicate unsuccessful status. 4964 // 4965 4966 status = STATUS_BUFFER_TOO_SMALL; 4967 break; 4968 } else { 4969 4970 IoMarkIrpPending(Irp); 4971 IoStartPacket(DeviceObject, Irp, NULL, NULL); 4972 4973 return STATUS_PENDING; 4974 } 4975 } 4976 4977 case IOCTL_CDROM_STOP_AUDIO: { 4978 4979 // 4980 // Stop play. 4981 // 4982 4983 DebugPrint((2, "CdRomDeviceControl: Stop audio\n")); 4984 4985 IoMarkIrpPending(Irp); 4986 IoStartPacket(DeviceObject,Irp, NULL,NULL); 4987 4988 return STATUS_PENDING; 4989 } 4990 4991 case IOCTL_CDROM_CHECK_VERIFY: { 4992 DebugPrint((1, "CdRomDeviceControl: [%lx] Check Verify\n", Irp)); 4993 IoMarkIrpPending(Irp); 4994 4995 if((irpStack->Parameters.DeviceIoControl.OutputBufferLength) && 4996 (irpStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(ULONG))) { 4997 4998 DebugPrint((1, "CdRomDeviceControl: Check Verify: media count " 4999 "buffer too small\n")); 5000 5001 status = STATUS_BUFFER_TOO_SMALL; 5002 break; 5003 } 5004 5005 IoStartPacket(DeviceObject,Irp, NULL,NULL); 5006 5007 return STATUS_PENDING; 5008 } 5009 5010 default: { 5011 5012 // 5013 // allocate an event and stuff it into our stack location. 5014 // 5015 5016 deviceControlEvent = ExAllocatePool(NonPagedPool, sizeof(KEVENT)); 5017 5018 if(!deviceControlEvent) { 5019 5020 status = STATUS_INSUFFICIENT_RESOURCES; 5021 5022 } else { 5023 5024 PIO_STACK_LOCATION currentStack; 5025 5026 KeInitializeEvent(deviceControlEvent, NotificationEvent, FALSE); 5027 5028 currentStack = IoGetCurrentIrpStackLocation(Irp); 5029 nextStack = IoGetNextIrpStackLocation(Irp); 5030 5031 // 5032 // Copy the stack down a notch 5033 // 5034 5035 *nextStack = *currentStack; 5036 5037 IoSetCompletionRoutine( 5038 Irp, 5039 CdRomClassIoctlCompletion, 5040 deviceControlEvent, 5041 TRUE, 5042 TRUE, 5043 TRUE 5044 ); 5045 5046 IoSetNextIrpStackLocation(Irp); 5047 5048 Irp->IoStatus.Status = STATUS_SUCCESS; 5049 Irp->IoStatus.Information = 0; 5050 5051 // 5052 // Override volume verifies on this stack location so that we 5053 // will be forced through the synchronization. Once this location 5054 // goes away we get the old value back 5055 // 5056 5057 nextStack->Flags |= SL_OVERRIDE_VERIFY_VOLUME; 5058 5059 IoMarkIrpPending(Irp); 5060 5061 IoStartPacket(DeviceObject, Irp, NULL, NULL); 5062 5063 // 5064 // Wait for CdRomClassIoctlCompletion to set the event. This 5065 // ensures serialization remains intact for these unhandled device 5066 // controls. 5067 // 5068 5069 KeWaitForSingleObject( 5070 deviceControlEvent, 5071 Suspended, 5072 KernelMode, 5073 FALSE, 5074 NULL); 5075 5076 ExFreePool(deviceControlEvent); 5077 5078 DebugPrint((2, "CdRomDeviceControl: irp %#08lx synchronized\n", Irp)); 5079 5080 // 5081 // If an error occured then propagate that back up - we are no longer 5082 // guaranteed synchronization and the upper layers will have to 5083 // retry. 5084 // 5085 // If no error occured, call down to the class driver directly 5086 // then start up the next request. 5087 // 5088 5089 if(Irp->IoStatus.Status == STATUS_SUCCESS) { 5090 5091 status = ScsiClassDeviceControl(DeviceObject, Irp); 5092 5093 KeRaiseIrql(DISPATCH_LEVEL, &irql); 5094 5095 IoStartNextPacket(DeviceObject, FALSE); 5096 5097 KeLowerIrql(irql); 5098 } 5099 } 5100 5101 return status; 5102 } 5103 5104 } // end switch() 5105 5106 if (status == STATUS_VERIFY_REQUIRED) { 5107 5108 // 5109 // If the status is verified required and this request 5110 // should bypass verify required then retry the request. 5111 // 5112 5113 if (irpStack->Flags & SL_OVERRIDE_VERIFY_VOLUME) { 5114 5115 status = STATUS_IO_DEVICE_ERROR; 5116 goto RetryControl; 5117 5118 } 5119 } 5120 5121 if (IoIsErrorUserInduced(status)) { 5122 5123 IoSetHardErrorOrVerifyDevice(Irp, DeviceObject); 5124 5125 } 5126 5127 // 5128 // Update IRP with completion status. 5129 // 5130 5131 Irp->IoStatus.Status = status; 5132 5133 // 5134 // Complete the request. 5135 // 5136 5137 IoCompleteRequest(Irp, IO_DISK_INCREMENT); 5138 DebugPrint((2, "CdRomDeviceControl: Status is %lx\n", status)); 5139 return status; 5140 5141 } // end ScsiCdRomDeviceControl() 5142 5143 VOID 5144 NTAPI 5145 ScanForSpecial( 5146 PDEVICE_OBJECT DeviceObject, 5147 PINQUIRYDATA InquiryData, 5148 PIO_SCSI_CAPABILITIES PortCapabilities 5149 ) 5150 5151 /*++ 5152 5153 Routine Description: 5154 5155 This function checks to see if an SCSI logical unit requires an special 5156 initialization or error processing. 5157 5158 Arguments: 5159 5160 DeviceObject - Supplies the device object to be tested. 5161 5162 InquiryData - Supplies the inquiry data returned by the device of interest. 5163 5164 PortCapabilities - Supplies the capabilities of the device object. 5165 5166 Return Value: 5167 5168 None. 5169 5170 --*/ 5171 5172 { 5173 PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension; 5174 PCDROM_DATA cdData = (PCDROM_DATA)(deviceExtension+1); 5175 5176 // 5177 // Look for a Hitachi CDR-1750. Read-ahead must be disabled in order 5178 // to get this cdrom drive to work on scsi adapters that use PIO. 5179 // 5180 5181 if ((strncmp((PCHAR)InquiryData->VendorId, "HITACHI CDR-1750S", strlen("HITACHI CDR-1750S")) == 0 || 5182 strncmp((PCHAR)InquiryData->VendorId, "HITACHI CDR-3650/1650S", strlen("HITACHI CDR-3650/1650S")) == 0) 5183 && PortCapabilities->AdapterUsesPio) { 5184 5185 DebugPrint((1, "CdRom ScanForSpecial: Found Hitachi CDR-1750S.\n")); 5186 5187 // 5188 // Setup an error handler to reinitialize the cd rom after it is reset. 5189 // 5190 5191 deviceExtension->ClassError = HitachProcessError; 5192 5193 } else if (( RtlCompareMemory( InquiryData->VendorId,"FUJITSU", 7 ) == 7 ) && 5194 (( RtlCompareMemory( InquiryData->ProductId,"FMCD-101", 8 ) == 8 ) || 5195 ( RtlCompareMemory( InquiryData->ProductId,"FMCD-102", 8 ) == 8 ))) { 5196 5197 // 5198 // When Read command is issued to FMCD-101 or FMCD-102 and there is a music 5199 // cd in it. It takes longer time than SCSI_CDROM_TIMEOUT before returning 5200 // error status. 5201 // 5202 5203 deviceExtension->TimeOutValue = 20; 5204 5205 } else if (( RtlCompareMemory( InquiryData->VendorId,"TOSHIBA", 7) == 7) && 5206 (( RtlCompareMemory( InquiryData->ProductId,"CD-ROM XM-34", 12) == 12))) { 5207 5208 SCSI_REQUEST_BLOCK srb; 5209 PCDB cdb; 5210 ULONG length; 5211 PUCHAR buffer; 5212 NTSTATUS status; 5213 5214 // 5215 // Set the density code and the error handler. 5216 // 5217 5218 length = (sizeof(MODE_READ_RECOVERY_PAGE) + MODE_BLOCK_DESC_LENGTH + MODE_HEADER_LENGTH); 5219 5220 RtlZeroMemory(&srb, sizeof(SCSI_REQUEST_BLOCK)); 5221 5222 // 5223 // Build the MODE SENSE CDB. 5224 // 5225 5226 srb.CdbLength = 6; 5227 cdb = (PCDB)srb.Cdb; 5228 5229 // 5230 // Set timeout value from device extension. 5231 // 5232 5233 srb.TimeOutValue = deviceExtension->TimeOutValue; 5234 5235 cdb->MODE_SENSE.OperationCode = SCSIOP_MODE_SENSE; 5236 cdb->MODE_SENSE.PageCode = 0x1; 5237 cdb->MODE_SENSE.AllocationLength = (UCHAR)length; 5238 5239 buffer = ExAllocatePool(NonPagedPoolCacheAligned, (sizeof(MODE_READ_RECOVERY_PAGE) + MODE_BLOCK_DESC_LENGTH + MODE_HEADER_LENGTH)); 5240 if (!buffer) { 5241 return; 5242 } 5243 5244 status = ScsiClassSendSrbSynchronous(DeviceObject, 5245 &srb, 5246 buffer, 5247 length, 5248 FALSE); 5249 5250 ((PERROR_RECOVERY_DATA)buffer)->BlockDescriptor.DensityCode = 0x83; 5251 ((PERROR_RECOVERY_DATA)buffer)->Header.ModeDataLength = 0x0; 5252 5253 RtlCopyMemory(&cdData->u1.Header, buffer, sizeof(ERROR_RECOVERY_DATA)); 5254 5255 RtlZeroMemory(&srb, sizeof(SCSI_REQUEST_BLOCK)); 5256 5257 // 5258 // Build the MODE SENSE CDB. 5259 // 5260 5261 srb.CdbLength = 6; 5262 cdb = (PCDB)srb.Cdb; 5263 5264 // 5265 // Set timeout value from device extension. 5266 // 5267 5268 srb.TimeOutValue = deviceExtension->TimeOutValue; 5269 5270 cdb->MODE_SELECT.OperationCode = SCSIOP_MODE_SELECT; 5271 cdb->MODE_SELECT.PFBit = 1; 5272 cdb->MODE_SELECT.ParameterListLength = (UCHAR)length; 5273 5274 status = ScsiClassSendSrbSynchronous(DeviceObject, 5275 &srb, 5276 buffer, 5277 length, 5278 TRUE); 5279 5280 if (!NT_SUCCESS(status)) { 5281 DebugPrint((1, 5282 "Cdrom.ScanForSpecial: Setting density code on Toshiba failed [%x]\n", 5283 status)); 5284 } 5285 5286 deviceExtension->ClassError = ToshibaProcessError; 5287 5288 ExFreePool(buffer); 5289 5290 } 5291 5292 // 5293 // Determine special CD-DA requirements. 5294 // 5295 5296 if (RtlCompareMemory( InquiryData->VendorId,"PLEXTOR",7) == 7) { 5297 cdData->XAFlags |= PLEXTOR_CDDA; 5298 } else if (RtlCompareMemory ( InquiryData->VendorId,"NEC",3) == 3) { 5299 cdData->XAFlags |= NEC_CDDA; 5300 } 5301 5302 return; 5303 } 5304 5305 VOID 5306 NTAPI 5307 HitachProcessError( 5308 PDEVICE_OBJECT DeviceObject, 5309 PSCSI_REQUEST_BLOCK Srb, 5310 NTSTATUS *Status, 5311 BOOLEAN *Retry 5312 ) 5313 /*++ 5314 5315 Routine Description: 5316 5317 This routine checks the type of error. If the error indicates CD-ROM the 5318 CD-ROM needs to be reinitialized then a Mode sense command is sent to the 5319 device. This command disables read-ahead for the device. 5320 5321 Arguments: 5322 5323 DeviceObject - Supplies a pointer to the device object. 5324 5325 Srb - Supplies a pointer to the failing Srb. 5326 5327 Status - Not used. 5328 5329 Retry - Not used. 5330 5331 Return Value: 5332 5333 None. 5334 5335 --*/ 5336 5337 { 5338 PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension; 5339 PSENSE_DATA senseBuffer = Srb->SenseInfoBuffer; 5340 LARGE_INTEGER largeInt; 5341 PUCHAR modePage; 5342 PIO_STACK_LOCATION irpStack; 5343 PIRP irp; 5344 PSCSI_REQUEST_BLOCK srb; 5345 PCOMPLETION_CONTEXT context; 5346 PCDB cdb; 5347 ULONG alignment; 5348 5349 UNREFERENCED_PARAMETER(Status); 5350 UNREFERENCED_PARAMETER(Retry); 5351 5352 largeInt.QuadPart = (LONGLONG) 1; 5353 5354 // 5355 // Check the status. The initialization command only needs to be sent 5356 // if UNIT ATTENTION is returned. 5357 // 5358 5359 if (!(Srb->SrbStatus & SRB_STATUS_AUTOSENSE_VALID)) { 5360 5361 // 5362 // The drive does not require reinitialization. 5363 // 5364 5365 return; 5366 } 5367 5368 // 5369 // Found a bad HITACHI cd-rom. These devices do not work with PIO 5370 // adapters when read-ahead is enabled. Read-ahead is disabled by 5371 // a mode select command. The mode select page code is zero and the 5372 // length is 6 bytes. All of the other bytes should be zero. 5373 // 5374 5375 5376 if ((senseBuffer->SenseKey & 0xf) == SCSI_SENSE_UNIT_ATTENTION) { 5377 5378 DebugPrint((1, "HitachiProcessError: Reinitializing the CD-ROM.\n")); 5379 5380 // 5381 // Send the special mode select command to disable read-ahead 5382 // on the CD-ROM reader. 5383 // 5384 5385 alignment = DeviceObject->AlignmentRequirement ? 5386 DeviceObject->AlignmentRequirement : 1; 5387 5388 context = ExAllocatePool( 5389 NonPagedPool, 5390 sizeof(COMPLETION_CONTEXT) + HITACHI_MODE_DATA_SIZE + alignment 5391 ); 5392 5393 if (context == NULL) { 5394 5395 // 5396 // If there is not enough memory to fulfill this request, 5397 // simply return. A subsequent retry will fail and another 5398 // chance to start the unit. 5399 // 5400 5401 return; 5402 } 5403 5404 context->DeviceObject = DeviceObject; 5405 srb = &context->Srb; 5406 5407 RtlZeroMemory(srb, SCSI_REQUEST_BLOCK_SIZE); 5408 5409 // 5410 // Write length to SRB. 5411 // 5412 5413 srb->Length = SCSI_REQUEST_BLOCK_SIZE; 5414 5415 // 5416 // Set up SCSI bus address. 5417 // 5418 5419 srb->PathId = deviceExtension->PathId; 5420 srb->TargetId = deviceExtension->TargetId; 5421 srb->Lun = deviceExtension->Lun; 5422 5423 srb->Function = SRB_FUNCTION_EXECUTE_SCSI; 5424 srb->TimeOutValue = deviceExtension->TimeOutValue; 5425 5426 // 5427 // Set the transfer length. 5428 // 5429 5430 srb->DataTransferLength = HITACHI_MODE_DATA_SIZE; 5431 srb->SrbFlags = SRB_FLAGS_DATA_OUT | SRB_FLAGS_DISABLE_AUTOSENSE | SRB_FLAGS_DISABLE_SYNCH_TRANSFER; 5432 5433 // 5434 // The data buffer must be aligned. 5435 // 5436 5437 srb->DataBuffer = (PVOID) (((ULONG_PTR) (context + 1) + (alignment - 1)) & 5438 ~(alignment - 1)); 5439 5440 5441 // 5442 // Build the HITACHI read-ahead mode select CDB. 5443 // 5444 5445 srb->CdbLength = 6; 5446 cdb = (PCDB)srb->Cdb; 5447 cdb->MODE_SENSE.LogicalUnitNumber = srb->Lun; 5448 cdb->MODE_SENSE.OperationCode = SCSIOP_MODE_SELECT; 5449 cdb->MODE_SENSE.AllocationLength = HITACHI_MODE_DATA_SIZE; 5450 5451 // 5452 // Initialize the mode sense data. 5453 // 5454 5455 modePage = srb->DataBuffer; 5456 5457 RtlZeroMemory(modePage, HITACHI_MODE_DATA_SIZE); 5458 5459 // 5460 // Set the page length field to 6. 5461 // 5462 5463 modePage[5] = 6; 5464 5465 // 5466 // Build the asynchronous request to be sent to the port driver. 5467 // 5468 5469 irp = IoBuildAsynchronousFsdRequest(IRP_MJ_WRITE, 5470 DeviceObject, 5471 srb->DataBuffer, 5472 srb->DataTransferLength, 5473 &largeInt, 5474 NULL); 5475 5476 IoSetCompletionRoutine(irp, 5477 (PIO_COMPLETION_ROUTINE)ScsiClassAsynchronousCompletion, 5478 context, 5479 TRUE, 5480 TRUE, 5481 TRUE); 5482 5483 irpStack = IoGetNextIrpStackLocation(irp); 5484 5485 irpStack->MajorFunction = IRP_MJ_SCSI; 5486 5487 srb->OriginalRequest = irp; 5488 5489 // 5490 // Save SRB address in next stack for port driver. 5491 // 5492 5493 irpStack->Parameters.Scsi.Srb = (PVOID)srb; 5494 5495 // 5496 // Set up IRP Address. 5497 // 5498 5499 (VOID)IoCallDriver(deviceExtension->PortDeviceObject, irp); 5500 5501 } 5502 } 5503 5504 NTSTATUS 5505 NTAPI 5506 ToshibaProcessErrorCompletion( 5507 PDEVICE_OBJECT DeviceObject, 5508 PIRP Irp, 5509 PVOID Context 5510 ) 5511 5512 /*++ 5513 5514 Routine Description: 5515 5516 Completion routine for the ClassError routine to handle older Toshiba units 5517 that require setting the density code. 5518 5519 Arguments: 5520 5521 DeviceObject - Supplies a pointer to the device object. 5522 5523 Irp - Pointer to irp created to set the density code. 5524 5525 Context - Supplies a pointer to the Mode Select Srb. 5526 5527 5528 Return Value: 5529 5530 STATUS_MORE_PROCESSING_REQUIRED 5531 5532 --*/ 5533 5534 { 5535 5536 PSCSI_REQUEST_BLOCK srb = Context; 5537 5538 // 5539 // Check for a frozen queue. 5540 // 5541 5542 if (srb->SrbStatus & SRB_STATUS_QUEUE_FROZEN) { 5543 5544 // 5545 // Unfreeze the queue getting the device object from the context. 5546 // 5547 5548 ScsiClassReleaseQueue(DeviceObject); 5549 } 5550 5551 // 5552 // Free all of the allocations. 5553 // 5554 5555 ExFreePool(srb->DataBuffer); 5556 ExFreePool(srb); 5557 IoFreeMdl(Irp->MdlAddress); 5558 IoFreeIrp(Irp); 5559 5560 // 5561 // Indicate the I/O system should stop processing the Irp completion. 5562 // 5563 5564 return STATUS_MORE_PROCESSING_REQUIRED; 5565 } 5566 5567 VOID 5568 NTAPI 5569 ToshibaProcessError( 5570 PDEVICE_OBJECT DeviceObject, 5571 PSCSI_REQUEST_BLOCK Srb, 5572 NTSTATUS *Status, 5573 BOOLEAN *Retry 5574 ) 5575 5576 /*++ 5577 5578 Routine Description: 5579 5580 This routine checks the type of error. If the error indicates a unit attention, 5581 the density code needs to be set via a Mode select command. 5582 5583 Arguments: 5584 5585 DeviceObject - Supplies a pointer to the device object. 5586 5587 Srb - Supplies a pointer to the failing Srb. 5588 5589 Status - Not used. 5590 5591 Retry - Not used. 5592 5593 Return Value: 5594 5595 None. 5596 5597 --*/ 5598 5599 { 5600 PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension; 5601 PCDROM_DATA cdData = (PCDROM_DATA)(deviceExtension+1); 5602 PSENSE_DATA senseBuffer = Srb->SenseInfoBuffer; 5603 PIO_STACK_LOCATION irpStack; 5604 PIRP irp; 5605 PSCSI_REQUEST_BLOCK srb; 5606 ULONG length; 5607 PCDB cdb; 5608 PUCHAR dataBuffer; 5609 5610 5611 if (!(Srb->SrbStatus & SRB_STATUS_AUTOSENSE_VALID)) { 5612 return; 5613 } 5614 5615 // 5616 // The Toshiba's require the density code to be set on power up and media changes. 5617 // 5618 5619 if ((senseBuffer->SenseKey & 0xf) == SCSI_SENSE_UNIT_ATTENTION) { 5620 5621 5622 irp = IoAllocateIrp((CCHAR)(deviceExtension->DeviceObject->StackSize+1), 5623 FALSE); 5624 5625 if (!irp) { 5626 return; 5627 } 5628 5629 srb = ExAllocatePool(NonPagedPool, sizeof(SCSI_REQUEST_BLOCK)); 5630 if (!srb) { 5631 IoFreeIrp(irp); 5632 return; 5633 } 5634 5635 5636 length = sizeof(ERROR_RECOVERY_DATA); 5637 dataBuffer = ExAllocatePool(NonPagedPoolCacheAligned, length); 5638 if (!dataBuffer) { 5639 ExFreePool(srb); 5640 IoFreeIrp(irp); 5641 return; 5642 } 5643 5644 irp->MdlAddress = IoAllocateMdl(dataBuffer, 5645 length, 5646 FALSE, 5647 FALSE, 5648 (PIRP) NULL); 5649 5650 if (!irp->MdlAddress) { 5651 ExFreePool(srb); 5652 ExFreePool(dataBuffer); 5653 IoFreeIrp(irp); 5654 return; 5655 } 5656 5657 // 5658 // Prepare the MDL 5659 // 5660 5661 MmBuildMdlForNonPagedPool(irp->MdlAddress); 5662 5663 RtlZeroMemory(srb, sizeof(SCSI_REQUEST_BLOCK)); 5664 5665 srb->DataBuffer = dataBuffer; 5666 cdb = (PCDB)srb->Cdb; 5667 5668 // 5669 // Set up the irp. 5670 // 5671 5672 IoSetNextIrpStackLocation(irp); 5673 irp->IoStatus.Status = STATUS_SUCCESS; 5674 irp->IoStatus.Information = 0; 5675 irp->Flags = 0; 5676 irp->UserBuffer = NULL; 5677 5678 // 5679 // Save the device object and irp in a private stack location. 5680 // 5681 5682 irpStack = IoGetCurrentIrpStackLocation(irp); 5683 irpStack->DeviceObject = deviceExtension->DeviceObject; 5684 5685 // 5686 // Construct the IRP stack for the lower level driver. 5687 // 5688 5689 irpStack = IoGetNextIrpStackLocation(irp); 5690 irpStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL; 5691 irpStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_SCSI_EXECUTE_OUT; 5692 irpStack->Parameters.Scsi.Srb = srb; 5693 5694 IoSetCompletionRoutine(irp, 5695 ToshibaProcessErrorCompletion, 5696 srb, 5697 TRUE, 5698 TRUE, 5699 TRUE); 5700 5701 srb->Length = SCSI_REQUEST_BLOCK_SIZE; 5702 srb->PathId = deviceExtension->PathId; 5703 srb->TargetId = deviceExtension->TargetId; 5704 srb->Lun = deviceExtension->Lun; 5705 srb->Function = SRB_FUNCTION_EXECUTE_SCSI; 5706 srb->Cdb[1] |= deviceExtension->Lun << 5; 5707 srb->SrbStatus = srb->ScsiStatus = 0; 5708 srb->NextSrb = 0; 5709 srb->OriginalRequest = irp; 5710 srb->SenseInfoBufferLength = 0; 5711 5712 // 5713 // Set the transfer length. 5714 // 5715 5716 srb->DataTransferLength = length; 5717 srb->SrbFlags = SRB_FLAGS_DATA_OUT | SRB_FLAGS_DISABLE_AUTOSENSE | SRB_FLAGS_DISABLE_SYNCH_TRANSFER; 5718 5719 5720 srb->CdbLength = 6; 5721 cdb->MODE_SELECT.OperationCode = SCSIOP_MODE_SELECT; 5722 cdb->MODE_SELECT.PFBit = 1; 5723 cdb->MODE_SELECT.ParameterListLength = (UCHAR)length; 5724 5725 // 5726 // Copy the Mode page into the databuffer. 5727 // 5728 5729 RtlCopyMemory(srb->DataBuffer, &cdData->u1.Header, length); 5730 5731 // 5732 // Set the density code. 5733 // 5734 5735 ((PERROR_RECOVERY_DATA)srb->DataBuffer)->BlockDescriptor.DensityCode = 0x83; 5736 5737 IoCallDriver(deviceExtension->PortDeviceObject, irp); 5738 } 5739 } 5740 5741 BOOLEAN 5742 NTAPI 5743 CdRomIsPlayActive( 5744 IN PDEVICE_OBJECT DeviceObject 5745 ) 5746 5747 /*++ 5748 5749 Routine Description: 5750 5751 This routine determines if the cd is currently playing music. 5752 5753 Arguments: 5754 5755 DeviceObject - Device object to test. 5756 5757 Return Value: 5758 5759 TRUE if the device is playing music. 5760 5761 --*/ 5762 { 5763 PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension; 5764 PIRP irp; 5765 IO_STATUS_BLOCK ioStatus; 5766 KEVENT event; 5767 NTSTATUS status; 5768 PSUB_Q_CURRENT_POSITION currentBuffer; 5769 5770 if (!PLAY_ACTIVE(deviceExtension)) { 5771 return(FALSE); 5772 } 5773 5774 currentBuffer = ExAllocatePool(NonPagedPoolCacheAligned, sizeof(SUB_Q_CURRENT_POSITION)); 5775 5776 if (currentBuffer == NULL) { 5777 return(FALSE); 5778 } 5779 5780 ((PCDROM_SUB_Q_DATA_FORMAT) currentBuffer)->Format = IOCTL_CDROM_CURRENT_POSITION; 5781 ((PCDROM_SUB_Q_DATA_FORMAT) currentBuffer)->Track = 0; 5782 5783 // 5784 // Create notification event object to be used to signal the 5785 // request completion. 5786 // 5787 5788 KeInitializeEvent(&event, NotificationEvent, FALSE); 5789 5790 // 5791 // Build the synchronous request to be sent to the port driver 5792 // to perform the request. 5793 // 5794 5795 irp = IoBuildDeviceIoControlRequest(IOCTL_CDROM_READ_Q_CHANNEL, 5796 deviceExtension->DeviceObject, 5797 currentBuffer, 5798 sizeof(CDROM_SUB_Q_DATA_FORMAT), 5799 currentBuffer, 5800 sizeof(SUB_Q_CURRENT_POSITION), 5801 FALSE, 5802 &event, 5803 &ioStatus); 5804 5805 if (irp == NULL) { 5806 ExFreePool(currentBuffer); 5807 return FALSE; 5808 } 5809 5810 // 5811 // Pass request to port driver and wait for request to complete. 5812 // 5813 5814 status = IoCallDriver(deviceExtension->DeviceObject, irp); 5815 5816 if (status == STATUS_PENDING) { 5817 KeWaitForSingleObject(&event, Suspended, KernelMode, FALSE, NULL); 5818 status = ioStatus.Status; 5819 } 5820 5821 if (!NT_SUCCESS(status)) { 5822 ExFreePool(currentBuffer); 5823 return FALSE; 5824 } 5825 5826 ExFreePool(currentBuffer); 5827 5828 return(PLAY_ACTIVE(deviceExtension)); 5829 5830 } 5831 5832 IO_COMPLETION_ROUTINE CdRomMediaChangeCompletion; 5833 NTSTATUS 5834 NTAPI 5835 CdRomMediaChangeCompletion( 5836 PDEVICE_OBJECT DeviceObject, 5837 PIRP Irp, 5838 PVOID Context 5839 ) 5840 5841 /*++ 5842 5843 Routine Description: 5844 5845 This routine handles the completion of the test unit ready irps 5846 used to determine if the media has changed. If the media has 5847 changed, this code signals the named event to wake up other 5848 system services that react to media change (aka AutoPlay). 5849 5850 Arguments: 5851 5852 DeviceObject - the object for the completion 5853 Irp - the IRP being completed 5854 Context - the SRB from the IRP 5855 5856 Return Value: 5857 5858 NTSTATUS 5859 5860 --*/ 5861 5862 { 5863 PSCSI_REQUEST_BLOCK srb = (PSCSI_REQUEST_BLOCK) Context; 5864 PIO_STACK_LOCATION cdStack = IoGetCurrentIrpStackLocation(Irp); 5865 PIO_STACK_LOCATION irpNextStack = IoGetNextIrpStackLocation(Irp); 5866 PDEVICE_EXTENSION deviceExtension; 5867 PDEVICE_EXTENSION physicalExtension; 5868 PSENSE_DATA senseBuffer; 5869 PCDROM_DATA cddata; 5870 5871 ASSERT(Irp); 5872 ASSERT(cdStack); 5873 DeviceObject = cdStack->DeviceObject; 5874 ASSERT(DeviceObject); 5875 5876 deviceExtension = DeviceObject->DeviceExtension; 5877 physicalExtension = deviceExtension->PhysicalDevice->DeviceExtension; 5878 cddata = (PCDROM_DATA)(deviceExtension + 1); 5879 5880 ASSERT(cddata->MediaChangeIrp == NULL); 5881 5882 // 5883 // If the sense data field is valid, look for a media change. 5884 // otherwise this iteration of the polling will just assume nothing 5885 // changed. 5886 // 5887 5888 DebugPrint((3, "CdRomMediaChangeHandler: Completing Autorun Irp 0x%lx " 5889 "for device %d\n", 5890 Irp, deviceExtension->DeviceNumber)); 5891 5892 if (srb->SrbStatus & SRB_STATUS_AUTOSENSE_VALID) { 5893 if (srb->SenseInfoBufferLength >= FIELD_OFFSET(SENSE_DATA, CommandSpecificInformation)) { 5894 5895 // 5896 // See if this is a media change. 5897 // 5898 5899 senseBuffer = srb->SenseInfoBuffer; 5900 if ((senseBuffer->SenseKey & 0x0f) == SCSI_SENSE_UNIT_ATTENTION) { 5901 if (senseBuffer->AdditionalSenseCode == SCSI_ADSENSE_MEDIUM_CHANGED) { 5902 5903 DebugPrint((1, "CdRomMediaChangeCompletion: New media inserted " 5904 "into CdRom%d [irp = 0x%lx]\n", 5905 deviceExtension->DeviceNumber, Irp)); 5906 5907 // 5908 // Media change event occurred - signal the named event. 5909 // 5910 5911 KeSetEvent(deviceExtension->MediaChangeEvent, 5912 (KPRIORITY) 0, 5913 FALSE); 5914 5915 deviceExtension->MediaChangeNoMedia = FALSE; 5916 5917 } 5918 5919 if (DeviceObject->Vpb->Flags & VPB_MOUNTED) { 5920 5921 // 5922 // Must remember the media changed and force the 5923 // file system to verify on next access 5924 // 5925 5926 DeviceObject->Flags |= DO_VERIFY_VOLUME; 5927 } 5928 5929 physicalExtension->MediaChangeCount++; 5930 5931 } else if(((senseBuffer->SenseKey & 0x0f) == SCSI_SENSE_NOT_READY)&& 5932 (senseBuffer->AdditionalSenseCode == SCSI_ADSENSE_NO_MEDIA_IN_DEVICE)&& 5933 (!deviceExtension->MediaChangeNoMedia)){ 5934 5935 // 5936 // If there was no media in the device then signal the waiters if 5937 // we haven't already done so before. 5938 // 5939 5940 DebugPrint((1, "CdRomMediaChangeCompletion: No media in device" 5941 "CdRom%d [irp = 0x%lx]\n", 5942 deviceExtension->DeviceNumber, Irp)); 5943 5944 KeSetEvent(deviceExtension->MediaChangeEvent, 5945 (KPRIORITY) 0, 5946 FALSE); 5947 5948 deviceExtension->MediaChangeNoMedia = TRUE; 5949 5950 } 5951 } 5952 } else if((srb->SrbStatus == SRB_STATUS_SUCCESS)&& 5953 (deviceExtension->MediaChangeNoMedia)) { 5954 // 5955 // We didn't have any media before and now the requests are succeeding 5956 // we probably missed the Media change somehow. Signal the change 5957 // anyway 5958 // 5959 5960 DebugPrint((1, "CdRomMediaChangeCompletion: Request completed normally" 5961 "for CdRom%d which was marked w/NoMedia [irp = 0x%lx]\n", 5962 deviceExtension->DeviceNumber, Irp)); 5963 5964 KeSetEvent(deviceExtension->MediaChangeEvent, 5965 (KPRIORITY) 0, 5966 FALSE); 5967 5968 deviceExtension->MediaChangeNoMedia = FALSE; 5969 5970 } 5971 5972 if (srb->SrbStatus & SRB_STATUS_QUEUE_FROZEN) { 5973 ScsiClassReleaseQueue(deviceExtension->DeviceObject); 5974 } 5975 5976 // 5977 // Remember the IRP and SRB for use the next time. 5978 // 5979 5980 irpNextStack->Parameters.Scsi.Srb = srb; 5981 cddata->MediaChangeIrp = Irp; 5982 5983 if (deviceExtension->ClassError) { 5984 5985 NTSTATUS status; 5986 BOOLEAN retry; 5987 5988 // 5989 // Throw away the status and retry values. Just give the error routine a chance 5990 // to do what it needs to. 5991 // 5992 5993 deviceExtension->ClassError(DeviceObject, 5994 srb, 5995 &status, 5996 &retry); 5997 } 5998 5999 IoStartNextPacket(DeviceObject, FALSE); 6000 6001 return STATUS_MORE_PROCESSING_REQUIRED; 6002 } 6003 6004 VOID 6005 NTAPI 6006 CdRomTickHandler( 6007 IN PDEVICE_OBJECT DeviceObject, 6008 IN PVOID Context 6009 ) 6010 6011 /*++ 6012 6013 Routine Description: 6014 6015 This routine handles the once per second timer provided by the 6016 Io subsystem. It is only used when the cdrom device itself is 6017 a candidate for autoplay support. It should never be called if 6018 the cdrom device is a changer device. 6019 6020 Arguments: 6021 6022 DeviceObject - what to check. 6023 Context - not used. 6024 6025 Return Value: 6026 6027 None. 6028 6029 --*/ 6030 6031 { 6032 PIRP irp; 6033 PIRP heldIrpList; 6034 PIRP nextIrp; 6035 PLIST_ENTRY listEntry; 6036 PCDROM_DATA cddata; 6037 PIO_STACK_LOCATION irpStack; 6038 PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension; 6039 6040 cddata = (PCDROM_DATA)(deviceExtension + 1); 6041 6042 if (cddata->MediaChange) { 6043 if (cddata->MediaChangeIrp != NULL) { 6044 6045 // 6046 // Media change support is active and the IRP is waiting. 6047 // Decrement the timer. 6048 // There is no MP protection on the timer counter. This 6049 // code is the only code that will manipulate the timer 6050 // and only one instance of it should be running at any 6051 // given time. 6052 // 6053 6054 cddata->MediaChangeCountDown--; 6055 6056 #if DBG 6057 cddata->MediaChangeIrpTimeInUse = 0; 6058 cddata->MediaChangeIrpLost = FALSE; 6059 #endif 6060 6061 if (!cddata->MediaChangeCountDown) { 6062 PSCSI_REQUEST_BLOCK srb; 6063 PIO_STACK_LOCATION irpNextStack; 6064 PCDB cdb; 6065 6066 // 6067 // Reset the timer. 6068 // 6069 6070 cddata->MediaChangeCountDown = MEDIA_CHANGE_DEFAULT_TIME; 6071 6072 // 6073 // Prepare the IRP for the test unit ready 6074 // 6075 6076 irp = cddata->MediaChangeIrp; 6077 cddata->MediaChangeIrp = NULL; 6078 6079 irp->IoStatus.Status = STATUS_SUCCESS; 6080 irp->IoStatus.Information = 0; 6081 irp->Flags = 0; 6082 irp->UserBuffer = NULL; 6083 6084 // 6085 // If the irp is sent down when the volume needs to be 6086 // verified, CdRomUpdateGeometryCompletion won't complete 6087 // it since it's not associated with a thread. Marking 6088 // it to override the verify causes it always be sent 6089 // to the port driver 6090 // 6091 6092 irpStack = IoGetCurrentIrpStackLocation(irp); 6093 irpStack->Flags |= SL_OVERRIDE_VERIFY_VOLUME; 6094 6095 irpNextStack = IoGetNextIrpStackLocation(irp); 6096 irpNextStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL; 6097 irpNextStack->Parameters.DeviceIoControl.IoControlCode = 6098 IOCTL_SCSI_EXECUTE_NONE; 6099 6100 // 6101 // Prepare the SRB for execution. 6102 // 6103 6104 srb = irpNextStack->Parameters.Scsi.Srb; 6105 srb->SrbStatus = srb->ScsiStatus = 0; 6106 srb->NextSrb = 0; 6107 srb->Length = SCSI_REQUEST_BLOCK_SIZE; 6108 srb->PathId = deviceExtension->PathId; 6109 srb->TargetId = deviceExtension->TargetId; 6110 srb->Lun = deviceExtension->Lun; 6111 srb->Function = SRB_FUNCTION_EXECUTE_SCSI; 6112 srb->SrbFlags = SRB_FLAGS_NO_DATA_TRANSFER | 6113 SRB_FLAGS_DISABLE_SYNCH_TRANSFER; 6114 srb->DataTransferLength = 0; 6115 srb->OriginalRequest = irp; 6116 6117 RtlZeroMemory(srb->SenseInfoBuffer, SENSE_BUFFER_SIZE); 6118 srb->SenseInfoBufferLength = SENSE_BUFFER_SIZE; 6119 6120 cdb = (PCDB) &srb->Cdb[0]; 6121 cdb->CDB6GENERIC.OperationCode = SCSIOP_TEST_UNIT_READY; 6122 cdb->CDB6GENERIC.LogicalUnitNumber = srb->Lun; 6123 6124 // 6125 // Setup the IRP to perform a test unit ready. 6126 // 6127 6128 IoSetCompletionRoutine(irp, 6129 CdRomMediaChangeCompletion, 6130 srb, 6131 TRUE, 6132 TRUE, 6133 TRUE); 6134 6135 // 6136 // Issue the request. 6137 // 6138 6139 IoStartPacket(DeviceObject, irp, NULL, NULL); 6140 } 6141 } else { 6142 6143 #if DBG 6144 if(cddata->MediaChangeIrpLost == FALSE) { 6145 if(cddata->MediaChangeIrpTimeInUse++ > 6146 MEDIA_CHANGE_TIMEOUT_TIME) { 6147 6148 DebugPrint((0, "CdRom%d: AutoPlay has lost it's irp and " 6149 "doesn't know where to find it. Leave it " 6150 "alone and it'll come home dragging it's " 6151 "stack behind it.\n", 6152 deviceExtension->DeviceNumber)); 6153 cddata->MediaChangeIrpLost = TRUE; 6154 } 6155 } 6156 6157 #endif 6158 } 6159 } 6160 6161 // 6162 // Process all generic timer IRPS in the timer list. As IRPs are pulled 6163 // off of the TimerIrpList they must be remembered in the first loop 6164 // if they are not sent to the lower driver. After all items have 6165 // been pulled off the list, it is possible to put the held IRPs back 6166 // into the TimerIrpList. 6167 // 6168 6169 heldIrpList = NULL; 6170 if (IsListEmpty(&cddata->TimerIrpList)) { 6171 listEntry = NULL; 6172 } else { 6173 listEntry = ExInterlockedRemoveHeadList(&cddata->TimerIrpList, 6174 &cddata->TimerIrpSpinLock); 6175 } 6176 while (listEntry) { 6177 6178 // 6179 // There is something in the timer list. Pick up the IRP and 6180 // see if it is ready to be submitted. 6181 // 6182 6183 irp = CONTAINING_RECORD(listEntry, IRP, Tail.Overlay.ListEntry); 6184 irpStack = IoGetCurrentIrpStackLocation(irp); 6185 6186 if (irpStack->Parameters.Others.Argument3) { 6187 ULONG_PTR count; 6188 6189 // 6190 // Decrement the countdown timer and put the IRP back in the list. 6191 // 6192 6193 count = (ULONG_PTR) irpStack->Parameters.Others.Argument3; 6194 count--; 6195 irpStack->Parameters.Others.Argument3 = (PVOID) count; 6196 6197 ASSERT(irp->AssociatedIrp.MasterIrp == NULL); 6198 if (heldIrpList) { 6199 irp->AssociatedIrp.MasterIrp = (PVOID) heldIrpList; 6200 } 6201 heldIrpList = irp; 6202 6203 } else { 6204 6205 // 6206 // Submit this IRP to the lower driver. This IRP does not 6207 // need to be remembered here. It will be handled again when 6208 // it completes. 6209 // 6210 6211 DebugPrint((1, "CdRomTickHandler: Reissuing request %lx (thread = %lx)\n", irp, irp->Tail.Overlay.Thread)); 6212 6213 // 6214 // feed this to the appropriate port driver 6215 // 6216 6217 IoCallDriver (deviceExtension->PortDeviceObject, irp); 6218 6219 } 6220 6221 // 6222 // Pick up the next IRP from the timer list. 6223 // 6224 6225 listEntry = ExInterlockedRemoveHeadList(&cddata->TimerIrpList, 6226 &cddata->TimerIrpSpinLock); 6227 } 6228 6229 // 6230 // Move all held IRPs back onto the timer list. 6231 // 6232 6233 while (heldIrpList) { 6234 6235 // 6236 // Save the single list pointer before queueing this IRP. 6237 // 6238 6239 nextIrp = (PIRP) heldIrpList->AssociatedIrp.MasterIrp; 6240 heldIrpList->AssociatedIrp.MasterIrp = NULL; 6241 6242 // 6243 // Return the held IRP to the timer list. 6244 // 6245 6246 ExInterlockedInsertTailList(&cddata->TimerIrpList, 6247 &heldIrpList->Tail.Overlay.ListEntry, 6248 &cddata->TimerIrpSpinLock); 6249 6250 // 6251 // Continue processing the held IRPs 6252 // 6253 6254 heldIrpList = nextIrp; 6255 } 6256 } 6257 6258 BOOLEAN 6259 NTAPI 6260 CdRomCheckRegistryForMediaChangeValue( 6261 IN PUNICODE_STRING RegistryPath, 6262 IN ULONG DeviceNumber 6263 ) 6264 6265 /*++ 6266 6267 Routine Description: 6268 6269 The user must specify that AutoPlay is to run on the platform 6270 by setting the registry value HKEY_LOCAL_MACHINE\System\CurrentControlSet\ 6271 Services\Cdrom\Autorun:REG_DWORD:1. 6272 6273 The user can override the global setting to enable or disable Autorun on a 6274 specific cdrom device by setting the key HKEY_LOCAL_MACHINE\System\ 6275 CurrentControlSet\Services\Cdrom\Device<N>\Autorun:REG_DWORD to one or zero. 6276 (CURRENTLY UNIMPLEMENTED) 6277 6278 If this registry value does not exist or contains the value zero then 6279 the timer to check for media change does not run. 6280 6281 Arguments: 6282 6283 RegistryPath - pointer to the unicode string inside 6284 ...\CurrentControlSet\Services\Cdrom 6285 DeviceNumber - The number of the device object 6286 6287 Return Value: 6288 6289 TRUE - Autorun is enabled. 6290 FALSE - no autorun. 6291 6292 --*/ 6293 6294 { 6295 #define ITEMS_TO_QUERY 2 /* always 1 greater than what is searched */ 6296 PRTL_QUERY_REGISTRY_TABLE parameters = NULL; 6297 NTSTATUS status; 6298 LONG zero = 0; 6299 6300 LONG tmp = 0; 6301 LONG doRun = 0; 6302 6303 CHAR buf[32]; 6304 ANSI_STRING paramNum; 6305 6306 UNICODE_STRING paramStr; 6307 6308 UNICODE_STRING paramSuffix; 6309 UNICODE_STRING paramPath; 6310 UNICODE_STRING paramDevPath; 6311 6312 // 6313 // First append \Parameters to the passed in registry path 6314 // 6315 6316 RtlInitUnicodeString(¶mStr, L"\\Parameters"); 6317 6318 RtlInitUnicodeString(¶mPath, NULL); 6319 6320 paramPath.MaximumLength = RegistryPath->Length + 6321 paramStr.Length + 6322 sizeof(WCHAR); 6323 6324 paramPath.Buffer = ExAllocatePool(PagedPool, paramPath.MaximumLength); 6325 6326 if(!paramPath.Buffer) { 6327 6328 DebugPrint((1,"CdRomCheckRegAP: couldn't allocate paramPath\n")); 6329 6330 return FALSE; 6331 } 6332 6333 RtlZeroMemory(paramPath.Buffer, paramPath.MaximumLength); 6334 RtlAppendUnicodeToString(¶mPath, RegistryPath->Buffer); 6335 RtlAppendUnicodeToString(¶mPath, paramStr.Buffer); 6336 6337 DebugPrint((2, "CdRomCheckRegAP: paramPath [%d] = %ws\n", 6338 paramPath.Length, 6339 paramPath.Buffer)); 6340 6341 // 6342 // build a counted ANSI string that contains 6343 // the suffix for the path 6344 // 6345 6346 sprintf(buf, "\\Device%lu", DeviceNumber); 6347 RtlInitAnsiString(¶mNum, buf); 6348 6349 // 6350 // Next convert this into a unicode string 6351 // 6352 6353 status = RtlAnsiStringToUnicodeString(¶mSuffix, ¶mNum, TRUE); 6354 6355 if(!NT_SUCCESS(status)) { 6356 DebugPrint((1,"CdRomCheckRegAP: couldn't convert paramNum to paramSuffix\n")); 6357 ExFreePool(paramPath.Buffer); 6358 return FALSE; 6359 } 6360 6361 RtlInitUnicodeString(¶mDevPath, NULL); 6362 6363 // 6364 // now build the device specific path 6365 // 6366 6367 paramDevPath.MaximumLength = paramPath.Length + 6368 paramSuffix.Length + 6369 sizeof(WCHAR); 6370 paramDevPath.Buffer = ExAllocatePool(PagedPool, paramDevPath.MaximumLength); 6371 6372 if(!paramDevPath.Buffer) { 6373 RtlFreeUnicodeString(¶mSuffix); 6374 ExFreePool(paramPath.Buffer); 6375 return FALSE; 6376 } 6377 6378 RtlZeroMemory(paramDevPath.Buffer, paramDevPath.MaximumLength); 6379 RtlAppendUnicodeToString(¶mDevPath, paramPath.Buffer); 6380 RtlAppendUnicodeToString(¶mDevPath, paramSuffix.Buffer); 6381 6382 DebugPrint((2, "CdRomCheckRegAP: paramDevPath [%d] = %ws\n", 6383 paramPath.Length, 6384 paramPath.Buffer)); 6385 6386 parameters = ExAllocatePool(NonPagedPool, 6387 sizeof(RTL_QUERY_REGISTRY_TABLE)*ITEMS_TO_QUERY); 6388 6389 if (parameters) { 6390 6391 // 6392 // Check for the Autorun value. 6393 // 6394 6395 RtlZeroMemory(parameters, 6396 (sizeof(RTL_QUERY_REGISTRY_TABLE)*ITEMS_TO_QUERY)); 6397 6398 parameters[0].Flags = RTL_QUERY_REGISTRY_DIRECT; 6399 parameters[0].Name = L"Autorun"; 6400 parameters[0].EntryContext = &doRun; 6401 parameters[0].DefaultType = REG_DWORD; 6402 parameters[0].DefaultData = &zero; 6403 parameters[0].DefaultLength = sizeof(ULONG); 6404 6405 status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE | RTL_REGISTRY_OPTIONAL, 6406 RegistryPath->Buffer, 6407 parameters, 6408 NULL, 6409 NULL); 6410 6411 DebugPrint((2, "CdRomCheckRegAP: cdrom/Autorun flag = %d\n", doRun)); 6412 6413 RtlZeroMemory(parameters, 6414 (sizeof(RTL_QUERY_REGISTRY_TABLE)*ITEMS_TO_QUERY)); 6415 6416 parameters[0].Flags = RTL_QUERY_REGISTRY_DIRECT; 6417 parameters[0].Name = L"Autorun"; 6418 parameters[0].EntryContext = &tmp; 6419 parameters[0].DefaultType = REG_DWORD; 6420 parameters[0].DefaultData = &doRun; 6421 parameters[0].DefaultLength = sizeof(ULONG); 6422 6423 status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE | RTL_REGISTRY_OPTIONAL, 6424 paramPath.Buffer, 6425 parameters, 6426 NULL, 6427 NULL); 6428 6429 DebugPrint((2, "CdRomCheckRegAP: cdrom/parameters/autorun flag = %d\n", tmp)); 6430 6431 RtlZeroMemory(parameters, 6432 (sizeof(RTL_QUERY_REGISTRY_TABLE) * ITEMS_TO_QUERY)); 6433 6434 parameters[0].Flags = RTL_QUERY_REGISTRY_DIRECT; 6435 parameters[0].Name = L"Autorun"; 6436 parameters[0].EntryContext = &doRun; 6437 parameters[0].DefaultType = REG_DWORD; 6438 parameters[0].DefaultData = &tmp; 6439 parameters[0].DefaultLength = sizeof(ULONG); 6440 6441 status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE | RTL_REGISTRY_OPTIONAL, 6442 paramDevPath.Buffer, 6443 parameters, 6444 NULL, 6445 NULL); 6446 6447 DebugPrint((1, "CdRomCheckRegAP: cdrom/parameters/device%d/autorun flag = %d\n", DeviceNumber, doRun)); 6448 6449 ExFreePool(parameters); 6450 6451 } 6452 6453 ExFreePool(paramPath.Buffer); 6454 ExFreePool(paramDevPath.Buffer); 6455 RtlFreeUnicodeString(¶mSuffix); 6456 6457 DebugPrint((1, "CdRomCheckRegAP: Autoplay for device %d is %s\n", 6458 DeviceNumber, 6459 (doRun ? "on" : "off"))); 6460 6461 if(doRun) { 6462 return TRUE; 6463 } 6464 6465 return FALSE; 6466 } 6467 6468 6469 BOOLEAN 6470 NTAPI 6471 IsThisASanyo( 6472 IN PDEVICE_OBJECT DeviceObject, 6473 IN UCHAR PathId, 6474 IN UCHAR TargetId 6475 ) 6476 6477 /*++ 6478 6479 Routine Description: 6480 6481 This routine is called by DriverEntry to determine whether a Sanyo 3-CD 6482 changer device is present. 6483 6484 Arguments: 6485 6486 DeviceObject - Supplies the device object for the 'real' device. 6487 6488 PathId - 6489 6490 Return Value: 6491 6492 TRUE - if an Atapi changer device is found. 6493 6494 --*/ 6495 6496 { 6497 KEVENT event; 6498 PIRP irp; 6499 PCHAR inquiryBuffer; 6500 IO_STATUS_BLOCK ioStatus; 6501 NTSTATUS status; 6502 PSCSI_ADAPTER_BUS_INFO adapterInfo; 6503 ULONG scsiBus; 6504 PINQUIRYDATA inquiryData; 6505 PSCSI_INQUIRY_DATA lunInfo; 6506 6507 inquiryBuffer = ExAllocatePool(NonPagedPool, 2048); 6508 KeInitializeEvent(&event, NotificationEvent, FALSE); 6509 irp = IoBuildDeviceIoControlRequest(IOCTL_SCSI_GET_INQUIRY_DATA, 6510 DeviceObject, 6511 NULL, 6512 0, 6513 inquiryBuffer, 6514 2048, 6515 FALSE, 6516 &event, 6517 &ioStatus); 6518 if (!irp) { 6519 return FALSE; 6520 } 6521 6522 status = IoCallDriver(DeviceObject, irp); 6523 6524 if (status == STATUS_PENDING) { 6525 KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL); 6526 status = ioStatus.Status; 6527 } 6528 6529 if (!NT_SUCCESS(status)) { 6530 return FALSE; 6531 } 6532 6533 adapterInfo = (PVOID) inquiryBuffer; 6534 6535 for (scsiBus=0; scsiBus < (ULONG)adapterInfo->NumberOfBuses; scsiBus++) { 6536 6537 // 6538 // Get the SCSI bus scan data for this bus. 6539 // 6540 6541 lunInfo = (PVOID) (inquiryBuffer + adapterInfo->BusData[scsiBus].InquiryDataOffset); 6542 6543 for (;;) { 6544 6545 if (lunInfo->PathId == PathId && lunInfo->TargetId == TargetId) { 6546 6547 inquiryData = (PVOID) lunInfo->InquiryData; 6548 6549 if (RtlCompareMemory(inquiryData->VendorId, "TORiSAN CD-ROM CDR-C", 20) == 20) { 6550 ExFreePool(inquiryBuffer); 6551 return TRUE; 6552 } 6553 6554 ExFreePool(inquiryBuffer); 6555 return FALSE; 6556 } 6557 6558 if (!lunInfo->NextInquiryDataOffset) { 6559 break; 6560 } 6561 6562 lunInfo = (PVOID) (inquiryBuffer + lunInfo->NextInquiryDataOffset); 6563 } 6564 } 6565 6566 ExFreePool(inquiryBuffer); 6567 return FALSE; 6568 } 6569 6570 BOOLEAN 6571 NTAPI 6572 IsThisAnAtapiChanger( 6573 IN PDEVICE_OBJECT DeviceObject, 6574 OUT PULONG DiscsPresent 6575 ) 6576 6577 /*++ 6578 6579 Routine Description: 6580 6581 This routine is called by DriverEntry to determine whether an Atapi 6582 changer device is present. 6583 6584 Arguments: 6585 6586 DeviceObject - Supplies the device object for the 'real' device. 6587 6588 DiscsPresent - Supplies a pointer to the number of Discs supported by the changer. 6589 6590 Return Value: 6591 6592 TRUE - if an Atapi changer device is found. 6593 6594 --*/ 6595 6596 { 6597 PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension; 6598 PMECHANICAL_STATUS_INFORMATION_HEADER mechanicalStatusBuffer; 6599 NTSTATUS status; 6600 SCSI_REQUEST_BLOCK srb; 6601 PCDB cdb = (PCDB) &srb.Cdb[0]; 6602 BOOLEAN retVal = FALSE; 6603 6604 *DiscsPresent = 0; 6605 6606 // 6607 // Some devices can't handle 12 byte CDB's gracefully 6608 // 6609 6610 if(deviceExtension->DeviceFlags & DEV_NO_12BYTE_CDB) { 6611 6612 return FALSE; 6613 6614 } 6615 6616 // 6617 // Build and issue the mechanical status command. 6618 // 6619 6620 mechanicalStatusBuffer = ExAllocatePool(NonPagedPoolCacheAligned, 6621 sizeof(MECHANICAL_STATUS_INFORMATION_HEADER)); 6622 6623 if (!mechanicalStatusBuffer) { 6624 retVal = FALSE; 6625 } else { 6626 6627 // 6628 // Build and send the Mechanism status CDB. 6629 // 6630 6631 RtlZeroMemory(&srb, sizeof(srb)); 6632 6633 srb.CdbLength = 12; 6634 srb.TimeOutValue = 20; 6635 6636 cdb->MECH_STATUS.OperationCode = SCSIOP_MECHANISM_STATUS; 6637 cdb->MECH_STATUS.AllocationLength[1] = sizeof(MECHANICAL_STATUS_INFORMATION_HEADER); 6638 6639 status = ScsiClassSendSrbSynchronous(DeviceObject, 6640 &srb, 6641 mechanicalStatusBuffer, 6642 sizeof(MECHANICAL_STATUS_INFORMATION_HEADER), 6643 FALSE); 6644 6645 6646 if (status == STATUS_SUCCESS) { 6647 6648 // 6649 // Indicate number of slots available 6650 // 6651 6652 *DiscsPresent = mechanicalStatusBuffer->NumberAvailableSlots; 6653 if (*DiscsPresent > 1) { 6654 retVal = TRUE; 6655 } else { 6656 6657 // 6658 // If only one disc, no need for this driver. 6659 // 6660 6661 retVal = FALSE; 6662 } 6663 } else { 6664 6665 // 6666 // Device doesn't support this command. 6667 // 6668 6669 retVal = FALSE; 6670 } 6671 6672 ExFreePool(mechanicalStatusBuffer); 6673 } 6674 6675 return retVal; 6676 } 6677 6678 BOOLEAN 6679 NTAPI 6680 IsThisAMultiLunDevice( 6681 IN PDEVICE_OBJECT DeviceObject, 6682 IN PDEVICE_OBJECT PortDeviceObject 6683 ) 6684 /*++ 6685 6686 Routine Description: 6687 6688 This routine is called to determine whether a multi-lun 6689 device is present. 6690 6691 Arguments: 6692 6693 DeviceObject - Supplies the device object for the 'real' device. 6694 6695 Return Value: 6696 6697 TRUE - if a Multi-lun device is found. 6698 6699 --*/ 6700 { 6701 PCHAR buffer; 6702 PSCSI_INQUIRY_DATA lunInfo; 6703 PSCSI_ADAPTER_BUS_INFO adapterInfo; 6704 PDEVICE_EXTENSION deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension; 6705 PINQUIRYDATA inquiryData; 6706 ULONG scsiBus; 6707 NTSTATUS status; 6708 UCHAR lunCount = 0; 6709 6710 status = ScsiClassGetInquiryData(PortDeviceObject, (PSCSI_ADAPTER_BUS_INFO *) &buffer); 6711 6712 if (!NT_SUCCESS(status)) { 6713 DebugPrint((1,"IsThisAMultiLunDevice: ScsiClassGetInquiryData failed\n")); 6714 return FALSE; 6715 } 6716 6717 adapterInfo = (PVOID) buffer; 6718 6719 // 6720 // For each SCSI bus this adapter supports ... 6721 // 6722 6723 for (scsiBus=0; scsiBus < adapterInfo->NumberOfBuses; scsiBus++) { 6724 6725 // 6726 // Get the SCSI bus scan data for this bus. 6727 // 6728 6729 lunInfo = (PVOID) (buffer + adapterInfo->BusData[scsiBus].InquiryDataOffset); 6730 6731 while (adapterInfo->BusData[scsiBus].InquiryDataOffset) { 6732 6733 inquiryData = (PVOID)lunInfo->InquiryData; 6734 6735 if ((lunInfo->PathId == deviceExtension->PathId) && 6736 (lunInfo->TargetId == deviceExtension->TargetId) && 6737 (inquiryData->DeviceType == READ_ONLY_DIRECT_ACCESS_DEVICE)) { 6738 6739 DebugPrint((1,"IsThisAMultiLunDevice: Vendor string is %.24s\n", 6740 inquiryData->VendorId)); 6741 6742 // 6743 // If this device has more than one cdrom-type lun then we 6744 // won't support autoplay on it 6745 // 6746 6747 if (lunCount++) { 6748 ExFreePool(buffer); 6749 return TRUE; 6750 } 6751 } 6752 6753 // 6754 // Get next LunInfo. 6755 // 6756 6757 if (lunInfo->NextInquiryDataOffset == 0) { 6758 break; 6759 } 6760 6761 lunInfo = (PVOID) (buffer + lunInfo->NextInquiryDataOffset); 6762 } 6763 } 6764 6765 ExFreePool(buffer); 6766 return FALSE; 6767 6768 } 6769 6770 IO_COMPLETION_ROUTINE CdRomUpdateGeometryCompletion; 6771 NTSTATUS 6772 NTAPI 6773 CdRomUpdateGeometryCompletion( 6774 PDEVICE_OBJECT DeviceObject, 6775 PIRP Irp, 6776 PVOID Context 6777 ) 6778 6779 /*++ 6780 6781 Routine Description: 6782 6783 This routine andles the completion of the test unit ready irps 6784 used to determine if the media has changed. If the media has 6785 changed, this code signals the named event to wake up other 6786 system services that react to media change (aka AutoPlay). 6787 6788 Arguments: 6789 6790 DeviceObject - the object for the completion 6791 Irp - the IRP being completed 6792 Context - the SRB from the IRP 6793 6794 Return Value: 6795 6796 NTSTATUS 6797 6798 --*/ 6799 6800 { 6801 PSCSI_REQUEST_BLOCK srb = (PSCSI_REQUEST_BLOCK) Context; 6802 PREAD_CAPACITY_DATA readCapacityBuffer; 6803 PDEVICE_EXTENSION deviceExtension; 6804 PIO_STACK_LOCATION irpStack; 6805 NTSTATUS status; 6806 BOOLEAN retry; 6807 ULONG_PTR retryCount; 6808 ULONG lastSector; 6809 PIRP originalIrp; 6810 PCDROM_DATA cddata; 6811 6812 // 6813 // Get items saved in the private IRP stack location. 6814 // 6815 6816 irpStack = IoGetCurrentIrpStackLocation(Irp); 6817 retryCount = (ULONG_PTR) irpStack->Parameters.Others.Argument1; 6818 originalIrp = (PIRP) irpStack->Parameters.Others.Argument2; 6819 6820 if (!DeviceObject) { 6821 DeviceObject = irpStack->DeviceObject; 6822 } 6823 ASSERT(DeviceObject); 6824 6825 deviceExtension = DeviceObject->DeviceExtension; 6826 cddata = (PCDROM_DATA) (deviceExtension + 1); 6827 readCapacityBuffer = srb->DataBuffer; 6828 6829 if ((NT_SUCCESS(Irp->IoStatus.Status)) && (SRB_STATUS(srb->SrbStatus) == SRB_STATUS_SUCCESS)) { 6830 PFOUR_BYTE from; 6831 PFOUR_BYTE to; 6832 6833 DebugPrint((2, "CdRomUpdateCapacityCompletion: [%lx] successful completion of buddy-irp %lx\n", originalIrp, Irp)); 6834 // 6835 // Copy sector size from read capacity buffer to device extension 6836 // in reverse byte order. 6837 // 6838 6839 from = (PFOUR_BYTE) &readCapacityBuffer->BytesPerBlock; 6840 to = (PFOUR_BYTE) &deviceExtension->DiskGeometry->Geometry.BytesPerSector; 6841 to->Byte0 = from->Byte3; 6842 to->Byte1 = from->Byte2; 6843 to->Byte2 = from->Byte1; 6844 to->Byte3 = from->Byte0; 6845 6846 // 6847 // Using the new BytesPerBlock, calculate and store the SectorShift. 6848 // 6849 6850 WHICH_BIT(deviceExtension->DiskGeometry->Geometry.BytesPerSector, deviceExtension->SectorShift); 6851 6852 // 6853 // Copy last sector in reverse byte order. 6854 // 6855 6856 from = (PFOUR_BYTE) &readCapacityBuffer->LogicalBlockAddress; 6857 to = (PFOUR_BYTE) &lastSector; 6858 to->Byte0 = from->Byte3; 6859 to->Byte1 = from->Byte2; 6860 to->Byte2 = from->Byte1; 6861 to->Byte3 = from->Byte0; 6862 deviceExtension->PartitionLength.QuadPart = (LONGLONG)(lastSector + 1); 6863 6864 // 6865 // Calculate number of cylinders. 6866 // 6867 6868 deviceExtension->DiskGeometry->Geometry.Cylinders.QuadPart = (LONGLONG)((lastSector + 1)/(32 * 64)); 6869 deviceExtension->PartitionLength.QuadPart = 6870 (deviceExtension->PartitionLength.QuadPart << deviceExtension->SectorShift); 6871 deviceExtension->DiskGeometry->Geometry.MediaType = RemovableMedia; 6872 6873 // 6874 // Assume sectors per track are 32; 6875 // 6876 6877 deviceExtension->DiskGeometry->Geometry.SectorsPerTrack = 32; 6878 6879 // 6880 // Assume tracks per cylinder (number of heads) is 64. 6881 // 6882 6883 deviceExtension->DiskGeometry->Geometry.TracksPerCylinder = 64; 6884 6885 } else { 6886 6887 DebugPrint((1, "CdRomUpdateCapacityCompletion: [%lx] unsuccessful completion of buddy-irp %lx (status - %lx)\n", originalIrp, Irp, Irp->IoStatus.Status)); 6888 6889 if (srb->SrbStatus & SRB_STATUS_QUEUE_FROZEN) { 6890 ScsiClassReleaseQueue(DeviceObject); 6891 } 6892 6893 retry = ScsiClassInterpretSenseInfo(DeviceObject, 6894 srb, 6895 IRP_MJ_SCSI, 6896 0, 6897 retryCount, 6898 &status); 6899 if (retry) { 6900 retryCount--; 6901 if (retryCount) { 6902 PCDB cdb; 6903 6904 DebugPrint((1, "CdRomUpdateCapacityCompletion: [%lx] Retrying request %lx .. thread is %lx\n", originalIrp, Irp, Irp->Tail.Overlay.Thread)); 6905 // 6906 // set up a one shot timer to get this process started over 6907 // 6908 6909 irpStack->Parameters.Others.Argument1 = (PVOID) retryCount; 6910 irpStack->Parameters.Others.Argument2 = (PVOID) originalIrp; 6911 irpStack->Parameters.Others.Argument3 = (PVOID) 2; 6912 6913 // 6914 // Setup the IRP to be submitted again in the timer routine. 6915 // 6916 6917 irpStack = IoGetNextIrpStackLocation(Irp); 6918 irpStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL; 6919 irpStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_SCSI_EXECUTE_IN; 6920 irpStack->Parameters.Scsi.Srb = srb; 6921 IoSetCompletionRoutine(Irp, 6922 CdRomUpdateGeometryCompletion, 6923 srb, 6924 TRUE, 6925 TRUE, 6926 TRUE); 6927 6928 // 6929 // Set up the SRB for read capacity. 6930 // 6931 6932 srb->CdbLength = 10; 6933 srb->TimeOutValue = deviceExtension->TimeOutValue; 6934 srb->SrbStatus = srb->ScsiStatus = 0; 6935 srb->NextSrb = 0; 6936 srb->Length = SCSI_REQUEST_BLOCK_SIZE; 6937 srb->PathId = deviceExtension->PathId; 6938 srb->TargetId = deviceExtension->TargetId; 6939 srb->Lun = deviceExtension->Lun; 6940 srb->Function = SRB_FUNCTION_EXECUTE_SCSI; 6941 srb->SrbFlags = SRB_FLAGS_DATA_IN | SRB_FLAGS_DISABLE_SYNCH_TRANSFER; 6942 srb->DataTransferLength = sizeof(READ_CAPACITY_DATA); 6943 6944 // 6945 // Set up the CDB 6946 // 6947 6948 cdb = (PCDB) &srb->Cdb[0]; 6949 cdb->CDB10.OperationCode = SCSIOP_READ_CAPACITY; 6950 cdb->CDB10.LogicalUnitNumber = deviceExtension->Lun; 6951 6952 // 6953 // Requests queued onto this list will be sent to the 6954 // lower level driver during CdRomTickHandler 6955 // 6956 6957 ExInterlockedInsertHeadList(&cddata->TimerIrpList, 6958 &Irp->Tail.Overlay.ListEntry, 6959 &cddata->TimerIrpSpinLock); 6960 6961 return STATUS_MORE_PROCESSING_REQUIRED; 6962 } else { 6963 6964 // 6965 // This has been bounced for a number of times. Error the 6966 // original request. 6967 // 6968 6969 originalIrp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; 6970 RtlZeroMemory(deviceExtension->DiskGeometry, sizeof(DISK_GEOMETRY_EX)); 6971 deviceExtension->DiskGeometry->Geometry.BytesPerSector = 2048; 6972 deviceExtension->SectorShift = 11; 6973 deviceExtension->PartitionLength.QuadPart = (LONGLONG)(0x7fffffff); 6974 deviceExtension->DiskGeometry->Geometry.MediaType = RemovableMedia; 6975 } 6976 } else { 6977 6978 // 6979 // Set up reasonable defaults 6980 // 6981 6982 RtlZeroMemory(deviceExtension->DiskGeometry, sizeof(DISK_GEOMETRY_EX)); 6983 deviceExtension->DiskGeometry->Geometry.BytesPerSector = 2048; 6984 deviceExtension->SectorShift = 11; 6985 deviceExtension->PartitionLength.QuadPart = (LONGLONG)(0x7fffffff); 6986 deviceExtension->DiskGeometry->Geometry.MediaType = RemovableMedia; 6987 } 6988 } 6989 6990 // 6991 // Free resources held. 6992 // 6993 6994 ExFreePool(srb->SenseInfoBuffer); 6995 ExFreePool(srb->DataBuffer); 6996 ExFreePool(srb); 6997 if (Irp->MdlAddress) { 6998 IoFreeMdl(Irp->MdlAddress); 6999 } 7000 IoFreeIrp(Irp); 7001 if (originalIrp->Tail.Overlay.Thread) { 7002 7003 DebugPrint((2, "CdRomUpdateCapacityCompletion: [%lx] completing original IRP\n", originalIrp)); 7004 IoCompleteRequest(originalIrp, IO_DISK_INCREMENT); 7005 7006 } else { 7007 DebugPrint((1, "CdRomUpdateCapacityCompletion: [%lx] original irp has " 7008 "no thread\n", 7009 originalIrp 7010 )); 7011 } 7012 7013 // 7014 // It's now safe to either start the next request or let the waiting ioctl 7015 // request continue along it's merry way 7016 // 7017 7018 IoStartNextPacket(DeviceObject, FALSE); 7019 7020 return STATUS_MORE_PROCESSING_REQUIRED; 7021 } 7022 7023 NTSTATUS 7024 NTAPI 7025 CdRomUpdateCapacity( 7026 IN PDEVICE_EXTENSION DeviceExtension, 7027 IN PIRP IrpToComplete, 7028 IN OPTIONAL PKEVENT IoctlEvent 7029 ) 7030 7031 /*++ 7032 7033 Routine Description: 7034 7035 This routine updates the capacity of the disk as recorded in the device extension. 7036 It also completes the IRP given with STATUS_VERIFY_REQUIRED. This routine is called 7037 when a media change has occurred and it is necessary to determine the capacity of the 7038 new media prior to the next access. 7039 7040 Arguments: 7041 7042 DeviceExtension - the device to update 7043 IrpToComplete - the request that needs to be completed when done. 7044 7045 Return Value: 7046 7047 NTSTATUS 7048 7049 --*/ 7050 7051 { 7052 PCDB cdb; 7053 PIRP irp; 7054 PSCSI_REQUEST_BLOCK srb; 7055 PREAD_CAPACITY_DATA capacityBuffer; 7056 PIO_STACK_LOCATION irpStack; 7057 PUCHAR senseBuffer; 7058 7059 irp = IoAllocateIrp((CCHAR)(DeviceExtension->DeviceObject->StackSize+1), 7060 FALSE); 7061 7062 if (irp) { 7063 7064 srb = ExAllocatePool(NonPagedPool, sizeof(SCSI_REQUEST_BLOCK)); 7065 if (srb) { 7066 capacityBuffer = ExAllocatePool(NonPagedPoolCacheAligned, 7067 sizeof(READ_CAPACITY_DATA)); 7068 7069 if (capacityBuffer) { 7070 7071 7072 senseBuffer = ExAllocatePool(NonPagedPoolCacheAligned, SENSE_BUFFER_SIZE); 7073 7074 if (senseBuffer) { 7075 7076 irp->MdlAddress = IoAllocateMdl(capacityBuffer, 7077 sizeof(READ_CAPACITY_DATA), 7078 FALSE, 7079 FALSE, 7080 (PIRP) NULL); 7081 7082 if (irp->MdlAddress) { 7083 7084 // 7085 // Have all resources. Set up the IRP to send for the capacity. 7086 // 7087 7088 IoSetNextIrpStackLocation(irp); 7089 irp->IoStatus.Status = STATUS_SUCCESS; 7090 irp->IoStatus.Information = 0; 7091 irp->Flags = 0; 7092 irp->UserBuffer = NULL; 7093 7094 // 7095 // Save the device object and retry count in a private stack location. 7096 // 7097 7098 irpStack = IoGetCurrentIrpStackLocation(irp); 7099 irpStack->DeviceObject = DeviceExtension->DeviceObject; 7100 irpStack->Parameters.Others.Argument1 = (PVOID) MAXIMUM_RETRIES; 7101 irpStack->Parameters.Others.Argument2 = (PVOID) IrpToComplete; 7102 7103 // 7104 // Construct the IRP stack for the lower level driver. 7105 // 7106 7107 irpStack = IoGetNextIrpStackLocation(irp); 7108 irpStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL; 7109 irpStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_SCSI_EXECUTE_IN; 7110 irpStack->Parameters.Scsi.Srb = srb; 7111 IoSetCompletionRoutine(irp, 7112 CdRomUpdateGeometryCompletion, 7113 srb, 7114 TRUE, 7115 TRUE, 7116 TRUE); 7117 // 7118 // Prepare the MDL 7119 // 7120 7121 MmBuildMdlForNonPagedPool(irp->MdlAddress); 7122 7123 7124 // 7125 // Set up the SRB for read capacity. 7126 // 7127 7128 RtlZeroMemory(srb, sizeof(SCSI_REQUEST_BLOCK)); 7129 RtlZeroMemory(senseBuffer, SENSE_BUFFER_SIZE); 7130 srb->CdbLength = 10; 7131 srb->TimeOutValue = DeviceExtension->TimeOutValue; 7132 srb->SrbStatus = srb->ScsiStatus = 0; 7133 srb->NextSrb = 0; 7134 srb->Length = SCSI_REQUEST_BLOCK_SIZE; 7135 srb->PathId = DeviceExtension->PathId; 7136 srb->TargetId = DeviceExtension->TargetId; 7137 srb->Lun = DeviceExtension->Lun; 7138 srb->Function = SRB_FUNCTION_EXECUTE_SCSI; 7139 srb->SrbFlags = SRB_FLAGS_DATA_IN | SRB_FLAGS_DISABLE_SYNCH_TRANSFER; 7140 srb->DataBuffer = capacityBuffer; 7141 srb->DataTransferLength = sizeof(READ_CAPACITY_DATA); 7142 srb->OriginalRequest = irp; 7143 srb->SenseInfoBuffer = senseBuffer; 7144 srb->SenseInfoBufferLength = SENSE_BUFFER_SIZE; 7145 7146 // 7147 // Set up the CDB 7148 // 7149 7150 cdb = (PCDB) &srb->Cdb[0]; 7151 cdb->CDB10.OperationCode = SCSIOP_READ_CAPACITY; 7152 cdb->CDB10.LogicalUnitNumber = DeviceExtension->Lun; 7153 7154 // 7155 // Set the return value in the IRP that will be completed 7156 // upon completion of the read capacity. 7157 // 7158 7159 IrpToComplete->IoStatus.Status = STATUS_IO_DEVICE_ERROR; 7160 IoMarkIrpPending(IrpToComplete); 7161 7162 IoCallDriver(DeviceExtension->PortDeviceObject, irp); 7163 7164 // 7165 // status is not checked because the completion routine for this 7166 // IRP will always get called and it will free the resources. 7167 // 7168 7169 return STATUS_PENDING; 7170 7171 } else { 7172 ExFreePool(senseBuffer); 7173 ExFreePool(capacityBuffer); 7174 ExFreePool(srb); 7175 IoFreeIrp(irp); 7176 } 7177 } else { 7178 ExFreePool(capacityBuffer); 7179 ExFreePool(srb); 7180 IoFreeIrp(irp); 7181 } 7182 } else { 7183 ExFreePool(srb); 7184 IoFreeIrp(irp); 7185 } 7186 } else { 7187 IoFreeIrp(irp); 7188 } 7189 } 7190 7191 return STATUS_INSUFFICIENT_RESOURCES; 7192 } 7193 7194 NTSTATUS 7195 NTAPI 7196 CdRomClassIoctlCompletion( 7197 IN PDEVICE_OBJECT DeviceObject, 7198 IN PIRP Irp, 7199 IN PVOID Context 7200 ) 7201 7202 /*++ 7203 7204 Routine Description: 7205 7206 This routine signals the event used by CdRomDeviceControl to synchronize 7207 class driver (and lower level driver) ioctls with cdrom's startio routine. 7208 The irp completion is short-circuited so that CdRomDeviceControl can 7209 reissue it once it wakes up. 7210 7211 Arguments: 7212 7213 DeviceObject - the device object 7214 Irp - the request we are synchronizing 7215 Context - a PKEVENT that we need to signal 7216 7217 Return Value: 7218 7219 NTSTATUS 7220 7221 --*/ 7222 7223 { 7224 PKEVENT syncEvent = (PKEVENT) Context; 7225 7226 DebugPrint((2, "CdRomClassIoctlCompletion: setting event for irp %#08lx\n", 7227 Irp 7228 )); 7229 7230 KeSetEvent(syncEvent, IO_DISK_INCREMENT, FALSE); 7231 7232 return STATUS_MORE_PROCESSING_REQUIRED; 7233 } 7234