ReactOS 0.4.16-dev-2633-g8dc9e50
ioctl.c
Go to the documentation of this file.
1/*
2 * PROJECT: ReactOS ATA Port Driver
3 * LICENSE: MIT (https://spdx.org/licenses/MIT)
4 * PURPOSE: I/O control handling
5 * COPYRIGHT: Copyright 2026 Dmitry Borisov <di.sean@protonmail.com>
6 */
7
8/* INCLUDES *******************************************************************/
9
10#include "atapi.h"
11
12/* GLOBALS ********************************************************************/
13
14#define AtaVerifyInBuffer(IoStack, Length) \
15 ((IoStack)->Parameters.DeviceIoControl.InputBufferLength >= (Length))
16
17#define AtaVerifyOutBuffer(IoStack, Length) \
18 ((IoStack)->Parameters.DeviceIoControl.OutputBufferLength >= (Length))
19
20/* FUNCTIONS ******************************************************************/
21
22static
23CODE_SEG("PAGE")
29{
30 PSTORAGE_PROPERTY_QUERY PropertyQuery = Irp->AssociatedIrp.SystemBuffer;
31 PSTORAGE_DESCRIPTOR_HEADER DescriptorHeader;
32 PIO_STACK_LOCATION IoStack;
33
34 PAGED_CODE();
35
37
38 if (!AtaVerifyInBuffer(IoStack, sizeof(*PropertyQuery)))
39 {
41 return FALSE;
42 }
43
44 /* Check the type of a property query */
45 if (PropertyQuery->QueryType != PropertyStandardQuery &&
46 PropertyQuery->QueryType != PropertyExistsQuery)
47 {
49 return FALSE;
50 }
51
52 /* The requested property is supported */
53 if (PropertyQuery->QueryType == PropertyExistsQuery)
54 {
56 return FALSE;
57 }
58
59 if (!AtaVerifyOutBuffer(IoStack, sizeof(*DescriptorHeader)))
60 {
62 return FALSE;
63 }
64
65 /* Caller can determine required size based upon DescriptorHeader */
67 {
68 DescriptorHeader = (PSTORAGE_DESCRIPTOR_HEADER)PropertyQuery;
69 DescriptorHeader->Version = DescriptorSize;
70 DescriptorHeader->Size = DescriptorSize;
71
72 Irp->IoStatus.Information = sizeof(*DescriptorHeader);
73
75 return FALSE;
76 }
77
78 return TRUE;
79}
80
81static
82CODE_SEG("PAGE")
87{
88 PINQUIRYDATA InquiryData = &DevExt->InquiryData;
91 ULONG DescriptorSize, RawPropertiesLength, Length1, Length2, Length3;
92
93 PAGED_CODE();
94
95 Length1 = (ULONG)strlen(DevExt->FriendlyName) + sizeof(ANSI_NULL);
96 Length2 = (ULONG)strlen(DevExt->RevisionNumber) + sizeof(ANSI_NULL);
97 Length3 = (ULONG)strlen(DevExt->SerialNumber) + sizeof(ANSI_NULL);
98 RawPropertiesLength = Length1 + Length2 + Length3;
99
101 RawPropertiesLength;
102
104 return Status;
105
106 DeviceDescriptor = Irp->AssociatedIrp.SystemBuffer;
107 DeviceDescriptor->RawPropertiesLength = RawPropertiesLength;
108 DeviceDescriptor->Version = sizeof(*DeviceDescriptor);
110 DeviceDescriptor->DeviceType = InquiryData->DeviceType;
111 DeviceDescriptor->DeviceTypeModifier = InquiryData->DeviceTypeModifier;
112 DeviceDescriptor->RemovableMedia = InquiryData->RemovableMedia;
113 DeviceDescriptor->CommandQueueing = FALSE; // Disable request tagging
114 if (DevExt->Device.PortData->PortFlags & PORT_FLAG_IS_AHCI)
115 DeviceDescriptor->BusType = BusTypeSata;
116 else
117 DeviceDescriptor->BusType = BusTypeAta;
118
119 /* Property 1: The vendor ID. We return a NULL string here */
120 DeviceDescriptor->VendorIdOffset = 0;
121
122 /* Property 2: The product ID */
123 DeviceDescriptor->ProductIdOffset =
124 FIELD_OFFSET(STORAGE_DEVICE_DESCRIPTOR, RawDeviceProperties);
126 DevExt->FriendlyName,
127 Length1);
128
129 /* Property 3: The product revision */
130 DeviceDescriptor->ProductRevisionOffset = DeviceDescriptor->ProductIdOffset + Length1;
132 DevExt->RevisionNumber,
133 Length2);
134
135 /* Property 4: The serial number */
136 DeviceDescriptor->SerialNumberOffset = DeviceDescriptor->ProductRevisionOffset + Length2;
138 DevExt->SerialNumber,
139 Length3);
140
141 Irp->IoStatus.Information = DescriptorSize;
142 return STATUS_SUCCESS;
143}
144
145static
146CODE_SEG("PAGE")
150 _In_ PIRP Irp)
151{
152 PSTORAGE_ACCESS_ALIGNMENT_DESCRIPTOR AccessAlignmentDescriptor;
153 ULONG LogicalSectorsPerPhysicalSector, Dummy;
155
156 PAGED_CODE();
157
158 if (IS_ATAPI(&DevExt->Device))
160
161 if (!AtaCheckPropertyQuery(Irp, sizeof(*AccessAlignmentDescriptor), &Status))
162 return Status;
163
164 AccessAlignmentDescriptor = Irp->AssociatedIrp.SystemBuffer;
165 AccessAlignmentDescriptor->Version = sizeof(*AccessAlignmentDescriptor);
166 AccessAlignmentDescriptor->Size = sizeof(*AccessAlignmentDescriptor);
167 AccessAlignmentDescriptor->BytesPerCacheLine = 0;
168 AccessAlignmentDescriptor->BytesOffsetForCacheAlignment = 0;
169 AccessAlignmentDescriptor->BytesPerLogicalSector = DevExt->Device.SectorSize;
170
171 LogicalSectorsPerPhysicalSector =
172 AtaDevLogicalSectorsPerPhysicalSector(&DevExt->IdentifyDeviceData, &Dummy);
173
174 AccessAlignmentDescriptor->BytesPerPhysicalSector =
175 DevExt->Device.SectorSize * LogicalSectorsPerPhysicalSector;
176
177 AccessAlignmentDescriptor->BytesOffsetForSectorAlignment =
178 DevExt->Device.SectorSize * AtaDevLogicalSectorAlignment(&DevExt->IdentifyDeviceData);
179
180 Irp->IoStatus.Information = sizeof(*AccessAlignmentDescriptor);
181 return STATUS_SUCCESS;
182}
183
184static
185CODE_SEG("PAGE")
189 _In_ PIRP Irp)
190{
191 PDEVICE_SEEK_PENALTY_DESCRIPTOR PenaltyDescriptor;
194
195 PAGED_CODE();
196
197 if (!AtaCheckPropertyQuery(Irp, sizeof(*PenaltyDescriptor), &Status))
198 return Status;
199
200 if (AtaDevIsRotatingDevice(&DevExt->IdentifyDeviceData))
202 else if (AtaDevIsSsd(&DevExt->IdentifyDeviceData))
204 else
205 return STATUS_UNSUCCESSFUL; // Undetermined
206
207 PenaltyDescriptor = Irp->AssociatedIrp.SystemBuffer;
208 PenaltyDescriptor->Version = sizeof(*PenaltyDescriptor);
209 PenaltyDescriptor->Size = sizeof(*PenaltyDescriptor);
210 PenaltyDescriptor->IncursSeekPenalty = IncursSeekPenalty;
211
212 Irp->IoStatus.Information = sizeof(*PenaltyDescriptor);
213 return STATUS_SUCCESS;
214}
215
216static
217CODE_SEG("PAGE")
221 _In_ PIRP Irp)
222{
223 PDEVICE_TRIM_DESCRIPTOR TrimDescriptor;
225
226 PAGED_CODE();
227
228 if (IS_ATAPI(&DevExt->Device))
230
231 if (!AtaCheckPropertyQuery(Irp, sizeof(*TrimDescriptor), &Status))
232 return Status;
233
234 TrimDescriptor = Irp->AssociatedIrp.SystemBuffer;
235 TrimDescriptor->Version = sizeof(*TrimDescriptor);
236 TrimDescriptor->Size = sizeof(*TrimDescriptor);
237 TrimDescriptor->TrimEnabled = AtaDevHasTrimFunction(&DevExt->IdentifyDeviceData);
238
239 Irp->IoStatus.Information = sizeof(*TrimDescriptor);
240 return STATUS_SUCCESS;
241}
242
243static
245CODE_SEG("PAGE")
249 _In_ PIRP Irp,
250 _In_ PIO_STACK_LOCATION IoStack,
251 _Out_ PBOOLEAN ForwardToFdo)
252{
253 PSTORAGE_PROPERTY_QUERY PropertyQuery;
255
256 PAGED_CODE();
257
258 if (!AtaVerifyInBuffer(IoStack, sizeof(*PropertyQuery)))
259 {
260 ERR("Buffer too small\n");
262 }
263
264 PropertyQuery = Irp->AssociatedIrp.SystemBuffer;
265 switch (PropertyQuery->PropertyId)
266 {
269 break;
270
273 break;
274
277 break;
278
281 break;
282
283 default:
284 *ForwardToFdo = TRUE;
286 }
287
288 *ForwardToFdo = FALSE;
289 return Status;
290}
291
292static
294CODE_SEG("PAGE")
298 _In_ PIRP Irp,
299 _In_ PIO_STACK_LOCATION IoStack)
300{
302 PSCSI_ADDRESS ScsiAddress;
303 ATA_SCSI_ADDRESS AtaScsiAddress;
304
305 PAGED_CODE();
306
307 if (!AtaVerifyOutBuffer(IoStack, sizeof(*ScsiAddress)))
308 {
309 ERR("Buffer too small\n");
311 }
312
313 ChanExt = DevExt->Common.FdoExt;
314 AtaScsiAddress = DevExt->Device.AtaScsiAddress;
315
316 ScsiAddress = Irp->AssociatedIrp.SystemBuffer;
317 ScsiAddress->Length = sizeof(*ScsiAddress);
318 ScsiAddress->PortNumber = ChanExt->ScsiPortNumber;
319 ScsiAddress->PathId = AtaScsiAddress.PathId;
320 ScsiAddress->TargetId = AtaScsiAddress.TargetId;
321 ScsiAddress->Lun = AtaScsiAddress.Lun;
322
323 Irp->IoStatus.Information = sizeof(*ScsiAddress);
324 return STATUS_SUCCESS;
325}
326
327static
328CODE_SEG("PAGE")
332 _In_ PSRB_IO_CONTROL SrbControl,
334{
337 PIRP Irp;
340 LARGE_INTEGER LargeInt;
341 PIO_STACK_LOCATION IoStack;
342
343 PAGED_CODE();
344
346 if (!Srb)
348
350
351 LargeInt.QuadPart = 1; // For compatibility only
353 DevExt->Common.Self,
354 SrbControl,
356 &LargeInt,
357 &Event,
359 if (!Irp)
360 {
362 goto Cleanup;
363 }
364
366
368 Srb->Length = sizeof(*Srb);
369
370 Srb->TargetId = DevExt->Device.AtaScsiAddress.TargetId;
371 Srb->Lun = DevExt->Device.AtaScsiAddress.Lun;
372 Srb->PathId = DevExt->Device.AtaScsiAddress.PathId;
373
374 Srb->TimeOutValue = SrbControl->Timeout;
375
377
378 Srb->DataBuffer = SrbControl;
380
382 IoStack->Parameters.Scsi.Srb = Srb;
383
384 Status = IoCallDriver(DevExt->Common.Self, Irp);
385 if (Status == STATUS_PENDING)
386 {
389 }
390
391Cleanup:
393 return Status;
394}
395
396static
398CODE_SEG("PAGE")
402 _In_ PIRP Irp,
403 _In_ PIO_STACK_LOCATION IoStack)
404{
405 PAGED_CODE();
406
407 // TODO: Implement
408 return Irp->IoStatus.Status;
409}
410
411static
413CODE_SEG("PAGE")
418 _In_ PIO_STACK_LOCATION IoStack)
419{
420 PSRB_IO_CONTROL SrbControl;
422 ULONG CmdBufferSize, BufferSize;
423
424 PAGED_CODE();
425
426 if (!AtaVerifyInBuffer(IoStack, sizeof(*SrbControl)))
427 {
428 ERR("Buffer too small\n");
430 }
431
432 SrbControl = Irp->AssociatedIrp.SystemBuffer;
433 if (SrbControl->HeaderLength != sizeof(*SrbControl))
434 {
435 ERR("Unknown structure size %lu\n", SrbControl->HeaderLength);
437 }
438
439 Status = RtlULongAdd(SrbControl->Length, sizeof(*SrbControl), &BufferSize);
440 if (!NT_SUCCESS(Status))
441 {
442 ERR("Too large buffer 0x%lx\n", SrbControl->Length);
443 return Status;
444 }
445
446 CmdBufferSize = IoStack->Parameters.DeviceIoControl.InputBufferLength;
447 CmdBufferSize = max(CmdBufferSize, IoStack->Parameters.DeviceIoControl.OutputBufferLength);
448 if (CmdBufferSize < BufferSize)
449 {
450 ERR("Cmd buffer too small\n");
452 }
453
454 if (RtlEqualMemory(SrbControl->Signature, "SCSIDISK", sizeof("SCSIDISK") - 1))
455 Status = AtaPdoSendHbaControl(DevExt, SrbControl, BufferSize);
456 else
458
459 return Status;
460}
461
462static
464CODE_SEG("PAGE")
469{
470 PATAPORT_CHANNEL_EXTENSION ChanExt = DevExt->Common.FdoExt;
471
472 PAGED_CODE();
473
474 return SptiHandleAtaPassthru(DevExt->Common.Self,
475 Irp,
478}
479
480static
482CODE_SEG("PAGE")
487 _In_ PIO_STACK_LOCATION IoStack)
488{
490
491 PAGED_CODE();
492
493 /* Skip requests that bypassed the class driver. See also cdrom!RequestHandleScsiPassThrough */
494 if ((IoStack->MinorFunction == 0) && DevExt->DeviceClaimed)
496
497 ChanExt = DevExt->Common.FdoExt;
498
499 return SptiHandleScsiPassthru(DevExt->Common.Self,
500 Irp,
503}
504
505static
510{
511 PIO_STACK_LOCATION IoStack;
513 BOOLEAN ForwardToFdo = FALSE;
514
515 Status = IoAcquireRemoveLock(&DevExt->Common.RemoveLock, Irp);
516 if (!NT_SUCCESS(Status))
517 {
518 Irp->IoStatus.Information = 0;
519 Irp->IoStatus.Status = Status;
521
522 return Status;
523 }
524
526 switch (IoStack->Parameters.DeviceIoControl.IoControlCode)
527 {
529 Status = AtaPdoHandleStorageQueryProperty(DevExt, Irp, IoStack, &ForwardToFdo);
530 break;
531
533 Status = AtaPdoHandleGetScsiAddress(DevExt, Irp, IoStack);
534 break;
535
537 Status = AtaPdoHandleScsiMiniport(DevExt, Irp, IoStack);
538 break;
539
542 break;
543
547 break;
548
551 Status = AtaPdoHandleScsiPassthrough(DevExt, Irp, IoStack);
552 break;
553
556 ForwardToFdo = TRUE;
557 break;
558
559 default:
561 break;
562 }
563
564 if (ForwardToFdo)
565 {
566 PATAPORT_CHANNEL_EXTENSION ChanExt = DevExt->Common.FdoExt;
567
569 Status = IoCallDriver(ChanExt->Common.Self, Irp);
570 }
571 else
572 {
573 Irp->IoStatus.Status = Status;
575 }
576
577 IoReleaseRemoveLock(&DevExt->Common.RemoveLock, Irp);
578
579 return Status;
580}
581
582static
583CODE_SEG("PAGE")
587 _In_ PIRP Irp)
588{
589 PSTORAGE_ADAPTER_DESCRIPTOR AdapterDescriptor;
591
592 PAGED_CODE();
593
594 if (!AtaCheckPropertyQuery(Irp, sizeof(*AdapterDescriptor), &Status))
595 return Status;
596
597 AdapterDescriptor = Irp->AssociatedIrp.SystemBuffer;
598
599 /*
600 * This structure has to be zeroed out first
601 * in order to not confuse the upper storage class drivers.
602 * Also the new version of the descriptor structure (NT6.2+)
603 * has two extra fields instead of the unnamed "padding" fields.
604 */
605 RtlZeroMemory(AdapterDescriptor, sizeof(*AdapterDescriptor));
606
607 AdapterDescriptor->Version = sizeof(*AdapterDescriptor);
608 AdapterDescriptor->Size = sizeof(*AdapterDescriptor);
609 AdapterDescriptor->MaximumTransferLength = ChanExt->PortData.MaximumTransferLength;
610 AdapterDescriptor->MaximumPhysicalPages = ChanExt->PortData.MaximumPhysicalPages;
611 AdapterDescriptor->AlignmentMask = ChanExt->Common.Self->AlignmentRequirement;
612 AdapterDescriptor->AdapterUsesPio = !!(ChanExt->PortData.PortFlags && PORT_FLAG_PIO_ONLY);
613 AdapterDescriptor->AdapterScansDown = FALSE;
614 AdapterDescriptor->CommandQueueing = FALSE; // Disable request tagging
615 AdapterDescriptor->AcceleratedTransfer = FALSE;
616 if (ChanExt->PortData.PortFlags & PORT_FLAG_IS_AHCI)
617 AdapterDescriptor->BusType = BusTypeSata;
618 else
619 AdapterDescriptor->BusType = BusTypeAta;
620 AdapterDescriptor->BusMajorVersion = 1;
621 AdapterDescriptor->BusMinorVersion = 0;
622#if (NTDDI_VERSION >= NTDDI_WIN8)
623 AdapterDescriptor->SrbType = SRB_TYPE_SCSI_REQUEST_BLOCK;
624 AdapterDescriptor->AddressType = STORAGE_ADDRESS_TYPE_BTL8;
625#endif
626
627 Irp->IoStatus.Information = sizeof(*AdapterDescriptor);
628 return STATUS_SUCCESS;
629}
630
631static
633CODE_SEG("PAGE")
637 _In_ PIRP Irp,
638 _In_ PIO_STACK_LOCATION IoStack)
639{
640 PSTORAGE_PROPERTY_QUERY PropertyQuery;
642
643 PAGED_CODE();
644
645 if (!AtaVerifyInBuffer(IoStack, sizeof(*PropertyQuery)))
646 {
647 ERR("Buffer too small\n");
649 }
650
651 PropertyQuery = Irp->AssociatedIrp.SystemBuffer;
652 switch (PropertyQuery->PropertyId)
653 {
656 break;
657
658 default:
660 break;
661 }
662
663 return Status;
664}
665
666static
668CODE_SEG("PAGE")
672 _In_ PIRP Irp,
673 _In_ PIO_STACK_LOCATION IoStack)
674{
676
677 PAGED_CODE();
678
679 if (!AtaVerifyOutBuffer(IoStack, sizeof(*Capabilities)))
680 {
681 ERR("Buffer too small\n");
683 }
684
685 Capabilities = Irp->AssociatedIrp.SystemBuffer;
686 Capabilities->Length = sizeof(*Capabilities);
687 Capabilities->MaximumTransferLength = ChanExt->PortData.MaximumTransferLength;
688 Capabilities->MaximumPhysicalPages = ChanExt->PortData.MaximumPhysicalPages;
689 Capabilities->SupportedAsynchronousEvents = FALSE;
690 Capabilities->AlignmentMask = ChanExt->Common.Self->AlignmentRequirement;
691 Capabilities->TaggedQueuing = FALSE;
692 Capabilities->AdapterScansDown = FALSE;
693 Capabilities->AdapterUsesPio = !!(ChanExt->PortData.PortFlags && PORT_FLAG_PIO_ONLY);
694
695 Irp->IoStatus.Information = sizeof(*Capabilities);
696 return STATUS_SUCCESS;
697}
698
699static
701CODE_SEG("PAGE")
705 _In_ PIRP Irp,
706 _In_ PIO_STACK_LOCATION IoStack)
707{
708 PSCSI_INQUIRY_DATA ScsiInquiryData;
709 PSCSI_ADAPTER_BUS_INFO ScsiAdapterBusInfo;
710 ULONG PdoCount, EntrySize, TotalSize;
711 ATA_SCSI_ADDRESS AtaScsiAddress;
712
713 PAGED_CODE();
714
715 PdoCount = 0;
716 AtaScsiAddress.AsULONG = 0;
717 while (TRUE)
718 {
720
721 DevExt = AtaFdoFindNextDeviceByPath(ChanExt, &AtaScsiAddress, FALSE, NULL);
722 if (!DevExt)
723 break;
724
725 ++PdoCount;
726 }
727
728 EntrySize = ALIGN_UP(sizeof(*ScsiInquiryData) - 1 + INQUIRYDATABUFFERSIZE, ULONG);
729 TotalSize = sizeof(*ScsiAdapterBusInfo) + EntrySize * PdoCount;
730 TRACE("Total size %lu\n", TotalSize);
731
732 if (!AtaVerifyOutBuffer(IoStack, TotalSize))
734
735 Irp->IoStatus.Information = TotalSize;
736
737 ScsiAdapterBusInfo = Irp->AssociatedIrp.SystemBuffer;
738 ScsiAdapterBusInfo->NumberOfBuses = 1;
739 ScsiAdapterBusInfo->BusData[0].NumberOfLogicalUnits = 0;
740 ScsiAdapterBusInfo->BusData[0].InitiatorBusId = 0xFF;
741 ScsiAdapterBusInfo->BusData[0].InquiryDataOffset = sizeof(*ScsiAdapterBusInfo);
742
743 ScsiInquiryData = (PSCSI_INQUIRY_DATA)(ScsiAdapterBusInfo + 1);
744
745 AtaScsiAddress.AsULONG = 0;
746 while (TRUE)
747 {
749 PINQUIRYDATA InquiryData;
750
751 DevExt = AtaFdoFindNextDeviceByPath(ChanExt, &AtaScsiAddress, FALSE, Irp);
752 if (!DevExt)
753 break;
754
755 AtaScsiAddress = DevExt->Device.AtaScsiAddress;
756
757 ScsiInquiryData->PathId = AtaScsiAddress.PathId;
758 ScsiInquiryData->TargetId = AtaScsiAddress.TargetId;
759 ScsiInquiryData->Lun = AtaScsiAddress.Lun;
760 ScsiInquiryData->InquiryDataLength = INQUIRYDATABUFFERSIZE;
761 ScsiInquiryData->DeviceClaimed = DevExt->DeviceClaimed;
762 ScsiInquiryData->NextInquiryDataOffset =
763 (ULONG)((ULONG_PTR)ScsiInquiryData + EntrySize - (ULONG_PTR)ScsiAdapterBusInfo);
764
765 RtlCopyMemory(ScsiInquiryData->InquiryData,
766 &DevExt->InquiryData,
768
769 /* This is a legacy IOCTL, limit the standard INQUIRY data to 36 bytes */
770 InquiryData = (PINQUIRYDATA)ScsiInquiryData->InquiryData;
771 InquiryData->AdditionalLength =
773
775
776 ScsiInquiryData = (PSCSI_INQUIRY_DATA)((ULONG_PTR)ScsiInquiryData + EntrySize);
777
778 if (++ScsiAdapterBusInfo->BusData[0].NumberOfLogicalUnits >= PdoCount)
779 break;
780 }
781
782 /* Terminate the last entry */
783 if (ScsiAdapterBusInfo->BusData[0].NumberOfLogicalUnits != 0)
784 {
785 ScsiInquiryData = ((PSCSI_INQUIRY_DATA)((ULONG_PTR)ScsiInquiryData - EntrySize));
786 ScsiInquiryData->NextInquiryDataOffset = 0;
787 }
788 else
789 {
790 ScsiAdapterBusInfo->BusData[0].InquiryDataOffset = 0;
791 }
792
793 return STATUS_SUCCESS;
794}
795
796static
798CODE_SEG("PAGE")
802 _In_ PIRP Irp,
803 _In_ PIO_STACK_LOCATION IoStack)
804{
807
808 PAGED_CODE();
809
810 /* FDO requests are routed directly to 0:0:0 */
811 DevExt = AtaFdoFindDeviceByPath(ChanExt, AtaMarshallScsiAddress(0, 0, 0), Irp);
812 if (!DevExt)
814
815 Status = AtaPdoHandleScsiMiniport(DevExt, Irp, IoStack);
816
818
819 return Status;
820}
821
822static
824CODE_SEG("PAGE")
828 _In_ PIRP Irp,
829 _In_ PIO_STACK_LOCATION IoStack)
830{
834
835 PAGED_CODE();
836
838 {
839 ERR("Buffer too small\n");
841 }
842
843 Spt = Irp->AssociatedIrp.SystemBuffer;
844
845 DevExt = AtaFdoFindDeviceByPath(ChanExt,
846 AtaMarshallScsiAddress(Spt->PathId, Spt->TargetId, Spt->Lun),
847 Irp);
848 if (!DevExt)
850
851 Status = AtaPdoHandleScsiPassthrough(DevExt, Irp, IoStack);
852
854
855 return Status;
856}
857
858static
863{
864 PIO_STACK_LOCATION IoStack;
866
867 Status = IoAcquireRemoveLock(&ChanExt->Common.RemoveLock, Irp);
868 if (!NT_SUCCESS(Status))
869 {
870 Irp->IoStatus.Information = 0;
871 Irp->IoStatus.Status = Status;
873
874 return Status;
875 }
876
878 switch (IoStack->Parameters.DeviceIoControl.IoControlCode)
879 {
881 Status = AtaFdoHandleStorageQueryProperty(ChanExt, Irp, IoStack);
882 break;
883
885 Status = AtaFdoHandleGetScsiCapabilities(ChanExt, Irp, IoStack);
886 break;
887
889 Status = AtaFdoHandleGetScsiInquiryData(ChanExt, Irp, IoStack);
890 break;
891
893 Status = AtaFdoHandleScsiMiniport(ChanExt, Irp, IoStack);
894 break;
895
898 Status = AtaFdoHandleScsiPassthrough(ChanExt, Irp, IoStack);
899 break;
900
904 break;
905
906 default:
907 {
909 Status = IoCallDriver(ChanExt->Common.LowerDeviceObject, Irp);
910
911 IoReleaseRemoveLock(&ChanExt->Common.RemoveLock, Irp);
912
913 return Status;
914 }
915 }
916
917 Irp->IoStatus.Status = Status;
919
920 IoReleaseRemoveLock(&ChanExt->Common.RemoveLock, Irp);
921
922 return Status;
923}
924
925/*
926 * For storage drivers this dispatch function must be not paged,
927 * because it must be present when it is received unknown IOCTL,
928 * otherwise we risk locking up the whole system.
929 */
931NTAPI
935{
936 if (IS_FDO(DeviceObject->DeviceExtension))
937 return AtaFdoDeviceControl(DeviceObject->DeviceExtension, Irp);
938 else
939 return AtaPdoDeviceControl(DeviceObject->DeviceExtension, Irp);
940}
static PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(PIRP Irp)
#define PAGED_CODE()
#define CODE_SEG(...)
INT Length2
Definition: FsRtlDissect.c:16
INT Length1
Definition: FsRtlDissect.c:15
unsigned char BOOLEAN
Definition: actypes.h:127
#define PORT_FLAG_PIO_ONLY
Definition: atapi.h:344
#define IS_FDO(p)
Definition: atapi.h:173
#define PORT_FLAG_IS_AHCI
Definition: atapi.h:340
FORCEINLINE ATA_SCSI_ADDRESS AtaMarshallScsiAddress(_In_ ULONG PathId, _In_ ULONG TargetId, _In_ ULONG Lun)
Definition: atapi.h:585
DECLSPEC_NOINLINE_FROM_PAGED PATAPORT_DEVICE_EXTENSION AtaFdoFindNextDeviceByPath(_In_ PATAPORT_CHANNEL_EXTENSION ChanExt, _Inout_ PATA_SCSI_ADDRESS AtaScsiAddress, _In_ BOOLEAN SearchRemoveDev, _In_ PVOID ReferenceTag)
Definition: fdo.c:654
DECLSPEC_NOINLINE_FROM_PAGED PATAPORT_DEVICE_EXTENSION AtaFdoFindDeviceByPath(_In_ PATAPORT_CHANNEL_EXTENSION ChanExt, _In_ ATA_SCSI_ADDRESS AtaScsiAddress, _In_ PVOID ReferenceTag)
Definition: fdo.c:614
#define ATAPORT_TAG
Definition: atapi.h:171
#define IS_ATAPI(Device)
Definition: atapi.h:176
LONG NTSTATUS
Definition: precomp.h:26
#define ERR(fmt,...)
Definition: precomp.h:57
_In_ PSCSI_REQUEST_BLOCK Srb
Definition: cdrom.h:989
struct _INQUIRYDATA * PINQUIRYDATA
#define INQUIRYDATABUFFERSIZE
Definition: cdrw_hw.h:1113
_In_ ULONG _In_ BOOLEAN _In_ ULONG _In_ UCHAR _In_ UCHAR _In_ UCHAR Lun
Definition: classpnp.h:1315
_In_ PIRP Irp
Definition: csq.h:116
#define STATUS_NOT_SUPPORTED
Definition: d3dkmdt.h:48
#define BufferSize
Definition: mmc.h:75
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
_ACRTIMP size_t __cdecl strlen(const char *)
Definition: string.c:1592
static const WCHAR Cleanup[]
Definition: register.c:80
static NTSTATUS IncursSeekPenalty(_In_ USHORT MediumRotationRate, _In_ PBOOLEAN IncursSeekPenalty)
Definition: utils.c:1888
static DECLSPEC_NOINLINE_FROM_NOT_PAGED NTSTATUS AtaFdoHandleScsiMiniport(_In_ PATAPORT_CHANNEL_EXTENSION ChanExt, _In_ PIRP Irp, _In_ PIO_STACK_LOCATION IoStack)
Definition: ioctl.c:800
static DECLSPEC_NOINLINE_FROM_NOT_PAGED NTSTATUS AtaPdoHandleScsiPassthrough(_In_ PATAPORT_DEVICE_EXTENSION DevExt, _Inout_ PIRP Irp, _In_ PIO_STACK_LOCATION IoStack)
Definition: ioctl.c:484
static DECLSPEC_NOINLINE_FROM_NOT_PAGED NTSTATUS AtaPdoHandleGetScsiAddress(_In_ PATAPORT_DEVICE_EXTENSION DevExt, _In_ PIRP Irp, _In_ PIO_STACK_LOCATION IoStack)
Definition: ioctl.c:296
static DECLSPEC_NOINLINE_FROM_NOT_PAGED NTSTATUS AtaPdoHandleAtaPassthrough(_In_ PATAPORT_DEVICE_EXTENSION DevExt, _Inout_ PIRP Irp)
Definition: ioctl.c:466
static NTSTATUS AtaPdoQueryStorageAccessAlignmentProperty(_In_ PATAPORT_DEVICE_EXTENSION DevExt, _In_ PIRP Irp)
Definition: ioctl.c:148
static DECLSPEC_NOINLINE_FROM_NOT_PAGED NTSTATUS AtaPdoHandleStorageManageDataSetAttributes(_In_ PATAPORT_DEVICE_EXTENSION DevExt, _In_ PIRP Irp, _In_ PIO_STACK_LOCATION IoStack)
Definition: ioctl.c:400
static DECLSPEC_NOINLINE_FROM_NOT_PAGED NTSTATUS AtaFdoHandleStorageQueryProperty(_In_ PATAPORT_CHANNEL_EXTENSION ChanExt, _In_ PIRP Irp, _In_ PIO_STACK_LOCATION IoStack)
Definition: ioctl.c:635
static NTSTATUS AtaFdoQueryStorageAdapterProperty(_In_ PATAPORT_CHANNEL_EXTENSION ChanExt, _In_ PIRP Irp)
Definition: ioctl.c:585
NTSTATUS NTAPI AtaDispatchDeviceControl(_In_ PDEVICE_OBJECT DeviceObject, _Inout_ PIRP Irp)
Definition: ioctl.c:932
static NTSTATUS AtaPdoQueryStorageDeviceTrimProperty(_In_ PATAPORT_DEVICE_EXTENSION DevExt, _In_ PIRP Irp)
Definition: ioctl.c:219
static DECLSPEC_NOINLINE_FROM_NOT_PAGED NTSTATUS AtaFdoHandleGetScsiInquiryData(_In_ PATAPORT_CHANNEL_EXTENSION ChanExt, _In_ PIRP Irp, _In_ PIO_STACK_LOCATION IoStack)
Definition: ioctl.c:703
static NTSTATUS AtaPdoSendHbaControl(_In_ PATAPORT_DEVICE_EXTENSION DevExt, _In_ PSRB_IO_CONTROL SrbControl, _In_ ULONG BufferSize)
Definition: ioctl.c:330
#define AtaVerifyOutBuffer(IoStack, Length)
Definition: ioctl.c:17
static DECLSPEC_NOINLINE_FROM_NOT_PAGED NTSTATUS AtaPdoHandleScsiMiniport(_In_ PATAPORT_DEVICE_EXTENSION DevExt, _Inout_ PIRP Irp, _In_ PIO_STACK_LOCATION IoStack)
Definition: ioctl.c:415
static NTSTATUS AtaPdoQueryStorageDeviceSeekPenaltyProperty(_In_ PATAPORT_DEVICE_EXTENSION DevExt, _In_ PIRP Irp)
Definition: ioctl.c:187
static NTSTATUS AtaPdoQueryStorageDeviceProperty(_In_ PATAPORT_DEVICE_EXTENSION DevExt, _In_ PIRP Irp)
Definition: ioctl.c:84
static DECLSPEC_NOINLINE_FROM_NOT_PAGED NTSTATUS AtaFdoHandleGetScsiCapabilities(_In_ PATAPORT_CHANNEL_EXTENSION ChanExt, _In_ PIRP Irp, _In_ PIO_STACK_LOCATION IoStack)
Definition: ioctl.c:670
#define AtaVerifyInBuffer(IoStack, Length)
Definition: ioctl.c:14
static NTSTATUS AtaFdoDeviceControl(_In_ PATAPORT_CHANNEL_EXTENSION ChanExt, _Inout_ PIRP Irp)
Definition: ioctl.c:860
static NTSTATUS AtaPdoDeviceControl(_In_ PATAPORT_DEVICE_EXTENSION DevExt, _Inout_ PIRP Irp)
Definition: ioctl.c:507
static BOOLEAN AtaCheckPropertyQuery(_Inout_ PIRP Irp, _In_ ULONG DescriptorSize, _Out_ NTSTATUS *Status)
Definition: ioctl.c:25
static DECLSPEC_NOINLINE_FROM_NOT_PAGED NTSTATUS AtaFdoHandleScsiPassthrough(_In_ PATAPORT_CHANNEL_EXTENSION ChanExt, _In_ PIRP Irp, _In_ PIO_STACK_LOCATION IoStack)
Definition: ioctl.c:826
static DECLSPEC_NOINLINE_FROM_NOT_PAGED NTSTATUS AtaPdoHandleStorageQueryProperty(_In_ PATAPORT_DEVICE_EXTENSION DevExt, _In_ PIRP Irp, _In_ PIO_STACK_LOCATION IoStack, _Out_ PBOOLEAN ForwardToFdo)
Definition: ioctl.c:247
#define ULONG_PTR
Definition: config.h:101
#define SRB_FUNCTION_IO_CONTROL
Definition: srb.h:317
#define SRB_FLAGS_DATA_IN
Definition: srb.h:400
#define SRB_FLAGS_NO_QUEUE_FREEZE
Definition: srb.h:404
#define KeWaitForSingleObject(pEvt, foo, a, b, c)
Definition: env_spec_w32.h:478
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
#define NonPagedPool
Definition: env_spec_w32.h:307
Status
Definition: gdiplustypes.h:25
_Must_inspect_result_ typedef _Out_ PHIDP_CAPS Capabilities
Definition: hidclass.h:103
FORCEINLINE ULONG AtaDevLogicalSectorsPerPhysicalSector(_In_ PIDENTIFY_DEVICE_DATA IdentifyData, _Out_ PULONG Exponent)
FORCEINLINE BOOLEAN AtaDevHasTrimFunction(_In_ PIDENTIFY_DEVICE_DATA IdentifyData)
FORCEINLINE BOOLEAN AtaDevIsRotatingDevice(_In_ PIDENTIFY_DEVICE_DATA IdentifyData)
FORCEINLINE BOOLEAN AtaDevIsSsd(_In_ PIDENTIFY_DEVICE_DATA IdentifyData)
FORCEINLINE ULONG AtaDevLogicalSectorAlignment(_In_ PIDENTIFY_DEVICE_DATA IdentifyData)
#define RtlEqualMemory(dst, src, len)
Definition: kdvm.h:18
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1109
static PVOID ExAllocatePoolZero(ULONG PoolType, SIZE_T NumberOfBytes, ULONG Tag)
Definition: precomp.h:45
#define KernelMode
Definition: asm.h:38
#define _Inout_
Definition: no_sal2.h:162
#define _Out_
Definition: no_sal2.h:160
#define _In_
Definition: no_sal2.h:158
#define RTL_SIZEOF_THROUGH_FIELD(type, field)
Definition: ntbasedef.h:684
#define ANSI_NULL
@ NotificationEvent
static OUT PIO_STATUS_BLOCK IoStatusBlock
Definition: pipe.c:75
#define IoSkipCurrentIrpStackLocation(Irp)
Definition: ntifs_ex.h:421
PIRP NTAPI IoBuildSynchronousFsdRequest(IN ULONG MajorFunction, IN PDEVICE_OBJECT DeviceObject, IN PVOID Buffer, IN ULONG Length, IN PLARGE_INTEGER StartingOffset, IN PKEVENT Event, IN PIO_STATUS_BLOCK IoStatusBlock)
Definition: irp.c:1069
#define IoCompleteRequest
Definition: irp.c:1240
#define IoCallDriver
Definition: irp.c:1225
#define STATUS_REVISION_MISMATCH
Definition: ntstatus.h:419
VOID NTAPI IoInvalidateDeviceRelations(IN PDEVICE_OBJECT DeviceObject, IN DEVICE_RELATION_TYPE Type)
Definition: pnpmgr.c:1772
#define IOCTL_STORAGE_QUERY_PROPERTY
Definition: ntddstor.h:178
@ BusTypeSata
Definition: ntddstor.h:449
@ BusTypeAta
Definition: ntddstor.h:441
#define IOCTL_STORAGE_MANAGE_DATA_SET_ATTRIBUTES
Definition: ntddstor.h:181
* PSTORAGE_ACCESS_ALIGNMENT_DESCRIPTOR
Definition: ntddstor.h:609
@ StorageDeviceSeekPenaltyProperty
Definition: ntddstor.h:519
@ StorageAdapterProperty
Definition: ntddstor.h:513
@ StorageDeviceTrimProperty
Definition: ntddstor.h:520
@ StorageAccessAlignmentProperty
Definition: ntddstor.h:518
@ StorageDeviceProperty
Definition: ntddstor.h:512
@ PropertyExistsQuery
Definition: ntddstor.h:506
@ PropertyStandardQuery
Definition: ntddstor.h:505
#define IOCTL_SCSI_PASS_THROUGH
Definition: scsi_port.h:47
#define IOCTL_SCSI_GET_ADDRESS
Definition: scsi_port.h:52
#define IOCTL_SCSI_GET_CAPABILITIES
Definition: scsi_port.h:50
#define IOCTL_SCSI_PASS_THROUGH_DIRECT
Definition: scsi_port.h:51
#define IOCTL_SCSI_MINIPORT
Definition: scsi_port.h:48
struct _SCSI_INQUIRY_DATA * PSCSI_INQUIRY_DATA
#define IOCTL_SCSI_RESCAN_BUS
Definition: scsi_port.h:53
#define IOCTL_SCSI_GET_INQUIRY_DATA
Definition: scsi_port.h:49
#define STORAGE_ADDRESS_TYPE_BTL8
Definition: srb.h:666
#define SRB_TYPE_SCSI_REQUEST_BLOCK
Definition: srb.h:663
#define IOCTL_ATA_PASS_THROUGH_DIRECT
Definition: ntddscsi.h:41
#define IOCTL_ATA_PASS_THROUGH
Definition: ntddscsi.h:40
#define DECLSPEC_NOINLINE_FROM_NOT_PAGED
#define STATUS_MORE_PROCESSING_REQUIRED
Definition: shellext.h:68
#define STATUS_SUCCESS
Definition: shellext.h:65
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:69
#define TRACE(s)
Definition: solgame.cpp:4
const KSDEVICE_DESCRIPTOR DeviceDescriptor
Definition: splitter.c:257
NTSTATUS SptiHandleAtaPassthru(_In_ PDEVICE_OBJECT DeviceObject, _Inout_ PIRP Irp, _In_ ULONG MaximumTransferLength, _In_ ULONG MaximumPhysicalPages)
Handler for the IOCTL_ATA_PASS_THROUGH and IOCTL_ATA_PASS_THROUGH_DIRECT requests.
Definition: sptilib.c:782
NTSTATUS SptiHandleScsiPassthru(_In_ PDEVICE_OBJECT DeviceObject, _Inout_ PIRP Irp, _In_ ULONG MaximumTransferLength, _In_ ULONG MaximumPhysicalPages)
Handler for the IOCTL_SCSI_PASS_THROUGH and IOCTL_SCSI_PASS_THROUGH_DIRECT requests.
Definition: sptilib.c:888
ATAPORT_PORT_DATA PortData
Definition: atapi.h:442
ATAPORT_COMMON_EXTENSION Common
Definition: atapi.h:440
PDEVICE_OBJECT Self
Definition: atapi.h:432
IO_REMOVE_LOCK RemoveLock
Definition: atapi.h:434
ATAPORT_IO_CONTEXT Device
Definition: atapi.h:457
INQUIRYDATA InquiryData
Definition: atapi.h:479
ATAPORT_COMMON_EXTENSION Common
Definition: atapi.h:455
ATA_SCSI_ADDRESS AtaScsiAddress
Definition: atapi.h:100
ULONG MaximumPhysicalPages
Definition: atapi.h:393
ULONG MaximumTransferLength
Definition: atapi.h:392
UCHAR RemovableMedia
Definition: cdrw_hw.h:1119
UCHAR DeviceTypeModifier
Definition: cdrw_hw.h:1118
UCHAR DeviceType
Definition: cdrw_hw.h:1116
UCHAR AdditionalLength
Definition: cdrw_hw.h:1122
union _IO_STACK_LOCATION::@1696 Parameters
struct _IO_STACK_LOCATION::@1696::@1697 DeviceIoControl
struct _IO_STACK_LOCATION::@4366::@4388 Scsi
SCSI_BUS_DATA BusData[1]
Definition: scsi_port.h:106
UCHAR PathId
Definition: scsi_port.h:149
UCHAR TargetId
Definition: scsi_port.h:150
ULONG Length
Definition: scsi_port.h:147
UCHAR PortNumber
Definition: scsi_port.h:148
ULONG InquiryDataOffset
Definition: scsi_port.h:98
UCHAR NumberOfLogicalUnits
Definition: scsi_port.h:96
UCHAR InitiatorBusId
Definition: scsi_port.h:97
UCHAR InquiryData[1]
Definition: scsi_port.h:119
ULONG NextInquiryDataOffset
Definition: scsi_port.h:118
ULONG InquiryDataLength
Definition: scsi_port.h:117
BOOLEAN DeviceClaimed
Definition: scsi_port.h:116
ULONG TimeOutValue
Definition: srb.h:262
UCHAR TargetId
Definition: srb.h:254
PVOID OriginalRequest
Definition: srb.h:266
PVOID DataBuffer
Definition: srb.h:263
UCHAR PathId
Definition: srb.h:253
UCHAR Function
Definition: srb.h:250
ULONG DataTransferLength
Definition: srb.h:261
ULONG SrbFlags
Definition: srb.h:260
USHORT Length
Definition: srb.h:249
UCHAR Signature[8]
Definition: scsi_port.h:126
ULONG HeaderLength
Definition: scsi_port.h:125
STORAGE_QUERY_TYPE QueryType
Definition: ntddstor.h:553
STORAGE_PROPERTY_ID PropertyId
Definition: ntddstor.h:552
_In_ SIZE_T DescriptorSize
Definition: nls.c:40
#define max(a, b)
Definition: svc.c:63
#define STATUS_PENDING
Definition: telnetd.h:14
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
unsigned char * PBOOLEAN
Definition: typedefs.h:53
#define NTAPI
Definition: typedefs.h:36
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
uint32_t ULONG_PTR
Definition: typedefs.h:65
unsigned char * PUCHAR
Definition: typedefs.h:53
uint32_t ULONG
Definition: typedefs.h:59
#define STATUS_INVALID_DEVICE_REQUEST
Definition: udferr_usr.h:138
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define STATUS_NO_SUCH_DEVICE
Definition: udferr_usr.h:136
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
#define STATUS_INFO_LENGTH_MISMATCH
Definition: udferr_usr.h:133
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
#define ALIGN_UP(size, type)
Definition: umtypes.h:91
ULONG AsULONG
Definition: atapi.h:69
UCHAR PathId
Definition: atapi.h:65
UCHAR TargetId
Definition: atapi.h:60
LONGLONG QuadPart
Definition: typedefs.h:114
_In_ PDEVICE_OBJECT DeviceObject
Definition: wdfdevice.h:2061
_In_ WDFMEMORY _Out_opt_ size_t * BufferSize
Definition: wdfmemory.h:254
struct _STORAGE_DESCRIPTOR_HEADER * PSTORAGE_DESCRIPTOR_HEADER
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetNextIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2695
#define IoAcquireRemoveLock(RemoveLock, Tag)
_In_ UCHAR EntrySize
Definition: iofuncs.h:642
#define IoReleaseRemoveLock(_RemoveLock, _Tag)
Definition: iofuncs.h:2764
#define IRP_MJ_SCSI
@ BusRelations
Definition: iotypes.h:2154
#define IO_NO_INCREMENT
Definition: iotypes.h:598
@ Executive
Definition: ketypes.h:467