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