ReactOS 0.4.17-dev-1190-g4c812f4
pata_generic.c
Go to the documentation of this file.
1/*
2 * PROJECT: ReactOS ATA Bus Driver
3 * LICENSE: MIT (https://spdx.org/licenses/MIT)
4 * PURPOSE: Generic PCI IDE controller minidriver
5 * COPYRIGHT: Copyright 2026 Dmitry Borisov <di.sean@protonmail.com>
6 */
7
8/* INCLUDES *******************************************************************/
9
10#include "pciidex.h"
11
12/* GLOBALS ********************************************************************/
13
14static const ULONG AtapModeToCycleTime[] =
15{
16 /* 0 1 2 3 4 PIO_MODE */
17 600, 383, 240, 180, 120,
18
19 /* 0 1 2 SWDMA_MODE */
20 960, 480, 240,
21
22 /* 0 1 2 MWDMA_MODE */
23 480, 150, 120,
24
25 /* 0 1 2 3 4 5 6 UDMA_MODE */
26 120, 80, 60, 45, 30, 20, 15
27};
28
30{
31 /* PIO_MODE */
32 { 70, 290, 240, 165, 150 }, // 0
33 { 50, 290, 93, 125, 100 }, // 1
34 { 30, 290, 40, 100, 90 }, // 2
35 { 30, 80, 70, 80, 70 }, // 3
36 { 25, 70, 25, 70, 25 }, // 4
37
38 /* SWDMA_MODE */
39 { 120, 0, 0, 480, 480 }, // 0
40 { 90, 0, 0, 240, 240 }, // 1
41 { 60, 0, 0, 120, 120 }, // 2
42
43 /* MWDMA_MODE */
44 { 60, 0, 0, 215, 215 }, // 0
45 { 45, 0, 0, 80, 50 }, // 1
46 { 25, 0, 0, 70, 25 }, // 2
47};
48
49/* FUNCTIONS ******************************************************************/
50
51static
54 _In_ ATATIM TimingValueNs,
55 _In_ ULONG ClockPeriodPs)
56{
57 return ((TimingValueNs * 1000) + ClockPeriodPs - 1) / ClockPeriodPs;
58}
59
60static
61VOID
64 _Out_ PATA_TIMING Timing,
66 _In_ ULONG ClockPeriodPs)
67{
68 ATATIM DataCycleTime, CmdCycleTime;
69
71
72 Timing->AddressSetup = AtaGetClocks(AtapTimingTable[Mode].AddressSetup, ClockPeriodPs);
73 Timing->CmdActive = AtaGetClocks(AtapTimingTable[Mode].CmdActive, ClockPeriodPs);
74 Timing->CmdRecovery = AtaGetClocks(AtapTimingTable[Mode].CmdRecovery, ClockPeriodPs);
75 Timing->DataActive = AtaGetClocks(AtapTimingTable[Mode].DataActive, ClockPeriodPs);
76 Timing->DataRecovery = AtaGetClocks(AtapTimingTable[Mode].DataRecovery, ClockPeriodPs);
77
78 if (Mode >= MWDMA_MODE(0))
79 DataCycleTime = Device->MinMwDmaCycleTime;
80 else if (Mode >= SWDMA_MODE(0))
81 DataCycleTime = Device->MinSwDmaCycleTime;
82 else
83 {
84 DataCycleTime = Device->MinPioCycleTime;
85
86 /* The t0 for register transfer is the same except for mode 2 */
87 if (Mode == PIO_MODE(2))
88 CmdCycleTime = max(DataCycleTime, 330);
89 else
90 CmdCycleTime = max(DataCycleTime, AtapModeToCycleTime[Mode]);
91 }
92 DataCycleTime = max(DataCycleTime, AtapModeToCycleTime[Mode]);
93
94 /*
95 * The minimum total cycle time requirement t0
96 * should be equal to or greater than the sum of t2 and t2i.
97 */
98 DataCycleTime = AtaGetClocks(DataCycleTime, ClockPeriodPs);
99 if ((Timing->DataActive + Timing->DataRecovery) < DataCycleTime)
100 {
101 Timing->DataActive += (DataCycleTime - (Timing->DataActive + Timing->DataRecovery)) / 2;
102 Timing->DataRecovery = DataCycleTime - Timing->DataActive;
103 }
104 if (Mode < SWDMA_MODE(0)) // PIO modes
105 {
106 CmdCycleTime = AtaGetClocks(CmdCycleTime, ClockPeriodPs);
107 if ((Timing->CmdActive + Timing->CmdRecovery) < CmdCycleTime)
108 {
109 Timing->CmdActive += (CmdCycleTime - (Timing->CmdActive + Timing->CmdRecovery)) / 2;
110 Timing->CmdRecovery = CmdCycleTime - Timing->CmdActive;
111 }
112 }
113}
114
115VOID
119 _In_range_(>, 0) ULONG ClockPeriodPs,
121{
122 ULONG i;
123
124 for (i = 0; i < MAX_IDE_DEVICE; ++i)
125 {
127 PATA_TIMING Timing = &Timings[i];
128 ATA_TIMING DmaTiming;
129
130 if (!Device)
131 {
132 RtlZeroMemory(Timing, sizeof(*Timing));
133 continue;
134 }
135
136 /* PIO mode */
137 AtaCalculateTimings(Device, Timing, Device->PioMode, ClockPeriodPs);
138
139 /* UDMA works independently of any PIO mode */
140 if (Device->DmaMode == PIO_MODE(0) || Device->DmaMode >= UDMA_MODE(0))
141 continue;
142
143 /* DMA mode */
144 AtaCalculateTimings(Device, &DmaTiming, Device->DmaMode, ClockPeriodPs);
145
146 /*
147 * Typically, the ATA port driver uses PIO commands along with DMA ones.
148 * Given that we program the chipset only once after device enumeration,
149 * we want to make sure the PIO commands would always work.
150 */
151 Timing->AddressSetup = max(Timing->AddressSetup, DmaTiming.AddressSetup);
152 Timing->CmdActive = max(Timing->CmdActive, DmaTiming.CmdActive);
153 Timing->CmdRecovery = max(Timing->CmdRecovery, DmaTiming.CmdRecovery);
154 Timing->DataActive = max(Timing->DataActive, DmaTiming.DataActive);
155 Timing->DataRecovery = max(Timing->DataRecovery, DmaTiming.DataRecovery);
156 }
157
158 /* Merge timings shared between both drives */
160 {
161 Timings[0].AddressSetup = max(Timings[0].AddressSetup, Timings[1].AddressSetup);
162
163 Timings[1].AddressSetup = Timings[0].AddressSetup;
164 }
166 {
167 Timings[0].CmdActive = max(Timings[0].CmdActive, Timings[1].CmdActive);
168 Timings[0].CmdRecovery = max(Timings[0].CmdRecovery, Timings[1].CmdRecovery);
169
170 Timings[1].CmdActive = Timings[0].CmdActive;
171 Timings[1].CmdRecovery = Timings[0].CmdRecovery;
172 }
174 {
175 Timings[0].DataActive = max(Timings[0].DataActive, Timings[1].DataActive);
176 Timings[0].DataRecovery = max(Timings[0].DataRecovery, Timings[1].DataRecovery);
177
178 Timings[1].DataActive = Timings[0].DataActive;
179 Timings[1].DataRecovery = Timings[0].DataRecovery;
180 }
181}
182
183VOID
188{
192
193 /*
194 * Nothing to do here, just keep the selected Device->PioMode and Device->DmaMode
195 * because SATA hardware snoops the SET FEATURES command.
196 */
197 NOTHING;
198}
199
200static
201VOID
203 _In_ ULONG GtmCycleTime,
204 _In_ ULONG SupportedModesBitmap,
205 _In_ ULONG CurrentModesBitmap,
206 _In_ ULONG MinimumMode,
208 _Out_ PULONG BestCycleTime,
209 _Out_ PULONG BestMode)
210{
211 LONG i;
212
213 if (GtmCycleTime == IDE_ACPI_TIMING_MODE_NOT_SUPPORTED)
214 {
215 *BestCycleTime = IDE_ACPI_TIMING_MODE_NOT_SUPPORTED;
216 *BestMode = PIO_MODE(0);
217 return;
218 }
219
220 for (i = MaximumMode; i >= MinimumMode; i--)
221 {
222 if ((SupportedModesBitmap & (1 << i)) && (AtapModeToCycleTime[i] >= GtmCycleTime))
223 {
224 *BestCycleTime = AtapModeToCycleTime[i];
225 *BestMode = i;
226 return;
227 }
228 }
229
230 /*
231 * This method can fail due to the first _GTM result
232 * may return compatible timings for a device,
233 * although the DMA mode is currently enabled by BIOS.
234 * For instance, this has been observed on a VPC 2007 ACPI firmware:
235 * Drive[0].PioSpeed 900 ns
236 * Drive[0].DmaSpeed 900 ns
237 * So we try to determine the transfer mode by other means below.
238 */
239 INFO("Failed to find mode for %ld ns cycle time from %lu in 0x%08lX\n",
240 (LONG)GtmCycleTime,
242 SupportedModesBitmap);
243
244 /* Search for the best enabled mode */
245 if (_BitScanReverse(BestMode, CurrentModesBitmap))
246 {
248 *BestCycleTime = AtapModeToCycleTime[*BestMode];
249 }
250 else
251 {
252 *BestCycleTime = IDE_ACPI_TIMING_MODE_NOT_SUPPORTED;
253 *BestMode = PIO_MODE(0);
254 }
255}
256
257static
258VOID
260 _In_ PCHANNEL_DATA_PATA ChanData,
262{
263 PIDE_ACPI_TIMING_MODE_BLOCK CurrentMode = &ChanData->CurrentTimingMode;
266 ULONG i;
267
268 ASSERT(ChanData->ChanInfo & CHANNEL_FLAG_HAS_ACPI_GTM);
269
270 NewMode.ModeFlags = CurrentMode->ModeFlags;
271
272 for (i = 0; i < MAX_IDE_DEVICE; ++i)
273 {
275 BOOLEAN HasUltraDMA;
276
277 if (!Device)
278 {
279 NewMode.Drive[i].PioSpeed = IDE_ACPI_TIMING_MODE_NOT_SUPPORTED;
280 NewMode.Drive[i].DmaSpeed = IDE_ACPI_TIMING_MODE_NOT_SUPPORTED;
281 continue;
282 }
283
284 /* PIO timing */
285 AtaAcpiFindModeForCycleTime(CurrentMode->Drive[i].PioSpeed,
286 Device->SupportedModes,
287 Device->CurrentModes & PIO_ALL,
288 PIO_MODE(0),
289 PIO_MODE(4),
290 &NewMode.Drive[i].PioSpeed,
291 &Device->PioMode);
292
293 /* DMA timing */
294 HasUltraDMA = !!(CurrentMode->ModeFlags & (IDE_ACPI_TIMING_MODE_FLAG_UDMA(i)));
295 AtaAcpiFindModeForCycleTime(CurrentMode->Drive[i].DmaSpeed,
296 Device->SupportedModes,
297 Device->CurrentModes & ~(PIO_ALL | SWDMA_ALL),
298 MWDMA_MODE(0),
299 HasUltraDMA ? UDMA_MODE(6) : MWDMA_MODE(2),
300 &NewMode.Drive[i].DmaSpeed,
301 &Device->DmaMode);
302
303 if (Device->DmaMode >= UDMA_MODE(0))
305 else
306 NewMode.ModeFlags &= ~IDE_ACPI_TIMING_MODE_FLAG_UDMA(i);
307 }
308
309 /*
310 * The underlying chipset might not allow the devices to be independently configured.
311 *
312 * For example, the Intel PIIX (0x8086:0x1230) cannot specify separate device timings.
313 * Please refer to PchSata.asi (PSIT bit)
314 * from the edk2-platforms repository for an example ASL implementation.
315 *
316 * It is possible to snoop an ATA command by software and run _STM each time
317 * the command being executed but an ACPI evaluation request can fail.
318 * For this reason, the timing setup only needs to be done once.
319 */
321 DeviceList[0] && DeviceList[1])
322 {
323 /* If we have a common timing mode for all devices use it, otherwise take the lower mode */
324 if (NewMode.Drive[0].DmaSpeed != IDE_ACPI_TIMING_MODE_NOT_SUPPORTED &&
325 NewMode.Drive[1].DmaSpeed != IDE_ACPI_TIMING_MODE_NOT_SUPPORTED)
326 {
327 NewMode.Drive[0].DmaSpeed = max(NewMode.Drive[0].DmaSpeed, NewMode.Drive[1].DmaSpeed);
328 DeviceList[0]->DmaMode = min(DeviceList[0]->DmaMode, DeviceList[1]->DmaMode);
329
330 NewMode.Drive[1].DmaSpeed = NewMode.Drive[0].DmaSpeed;
331 DeviceList[1]->DmaMode = DeviceList[0]->DmaMode;
332 }
333 NewMode.Drive[0].PioSpeed = max(NewMode.Drive[0].PioSpeed, NewMode.Drive[1].PioSpeed);
334 DeviceList[0]->PioMode = min(DeviceList[0]->PioMode, DeviceList[1]->PioMode);
335
336 NewMode.Drive[1].PioSpeed = NewMode.Drive[0].PioSpeed;
337 DeviceList[1]->PioMode = DeviceList[0]->PioMode;
338 }
339
340 INFO("CH %lu: Old timings %-2lX 0:%-3ld 0:%-3ld 1:%-3ld 1:%-3ld\n",
341 ChanData->Channel,
342 CurrentMode->ModeFlags,
343 (LONG)CurrentMode->Drive[0].PioSpeed,
344 (LONG)CurrentMode->Drive[0].DmaSpeed,
345 (LONG)CurrentMode->Drive[1].PioSpeed,
346 (LONG)CurrentMode->Drive[1].DmaSpeed);
347
348 INFO("CH %lu: New timings %-2lX 0:%-3ld 0:%-3ld 1:%-3ld 1:%-3ld\n",
349 ChanData->Channel,
350 NewMode.ModeFlags,
351 (LONG)NewMode.Drive[0].PioSpeed,
352 (LONG)NewMode.Drive[0].DmaSpeed,
353 (LONG)NewMode.Drive[1].PioSpeed,
354 (LONG)NewMode.Drive[1].DmaSpeed);
355
356 /* Evaluate _STM */
357 Status = AtaAcpiSetTimingMode(ChanData->PdoExt->Common.Self,
358 &NewMode,
359 DeviceList[0] ? DeviceList[0]->IdentifyDeviceData : NULL,
360 DeviceList[1] ? DeviceList[1]->IdentifyDeviceData : NULL);
361 if (!NT_SUCCESS(Status))
362 {
363 /* ACPI request failed, fall back to PIO */
364 for (i = 0; i < MAX_IDE_DEVICE; ++i)
365 {
367
368 if (!Device)
369 continue;
370
371 Device->DmaMode = PIO_MODE(0);
372 NT_VERIFY(_BitScanReverse(&Device->PioMode, Device->CurrentModes & PIO_ALL));
373 }
374 return;
375 }
376
377 /* Save the result */
378 AtaAcpiGetTimingMode(ChanData->PdoExt->Common.Self, CurrentMode);
379}
380
381static
382VOID
384 _In_ PCHANNEL_DATA_PATA ChanData,
386{
387 ULONG i;
388
389 /* Update manually using BIOS boot settings */
390 for (i = 0; i < MAX_IDE_DEVICE; ++i)
391 {
393 ULONG DmaFlags;
394
395 if (!Device)
396 continue;
397
398 /* Get the PIO and DMA modes set by BIOS */
399 if (!_BitScanReverse(&Device->DmaMode, Device->CurrentModes & ~PIO_ALL))
400 Device->DmaMode = PIO_MODE(0);
401 NT_VERIFY(_BitScanReverse(&Device->PioMode, Device->CurrentModes & PIO_ALL));
402
403 if (i == 0)
405 else
407
408 /* Disable DMA when when it is not supported */
409 if (!(ChanData->ChanInfo & DmaFlags))
410 Device->DmaMode = PIO_MODE(0);
411 }
412}
413
414VOID
419{
420 PCHANNEL_DATA_PATA ChanData = Controller->Channels[Channel];
421
422 /* Set the PATA transfer timings through ACPI if possible */
423 if (ChanData->ChanInfo & CHANNEL_FLAG_HAS_ACPI_GTM)
425 else
427}
428
429static
430CODE_SEG("PAGE")
431VOID
433 _In_ PCHANNEL_DATA_PATA ChanData)
434{
436
437 PAGED_CODE();
438
439 if (ChanData->ChanInfo & CHANNEL_FLAG_PRIMARY_ADDRESS_CLAIMED)
441 if (ChanData->ChanInfo & CHANNEL_FLAG_SECONDARY_ADDRESS_CLAIMED)
443
444 ChanData->ChanInfo &= ~(CHANNEL_FLAG_PRIMARY_ADDRESS_CLAIMED |
446}
447
448static
449CODE_SEG("PAGE")
450VOID
452 _In_ PCHANNEL_DATA_PATA ChanData)
453{
455
456 PAGED_CODE();
457
458 if (IsNEC_98)
459 {
460 if (ChanData->ChanInfo & CHANNEL_FLAG_CBUS)
461 {
462 ConfigInfo->AtDiskPrimaryAddressClaimed = TRUE;
464
465 ChanData->ChanInfo |= CHANNEL_FLAG_PRIMARY_ADDRESS_CLAIMED |
467 }
468 }
469 else if (ChanData->Regs.Data == UlongToPtr(PCIIDE_LEGACY_PRIMARY_COMMAND_BASE))
470 {
471 ConfigInfo->AtDiskPrimaryAddressClaimed = TRUE;
472 ChanData->ChanInfo |= CHANNEL_FLAG_PRIMARY_ADDRESS_CLAIMED;
473 }
474 else if (ChanData->Regs.Data == UlongToPtr(PCIIDE_LEGACY_SECONDARY_COMMAND_BASE))
475 {
477 ChanData->ChanInfo |= CHANNEL_FLAG_SECONDARY_ADDRESS_CLAIMED;
478 }
479}
480
481static
482CODE_SEG("PAGE")
483VOID
485 _In_ PVOID ChannelContext)
486{
487 PCHANNEL_DATA_PATA ChanData = ChannelContext;
488 PDMA_ADAPTER DmaAdapter = ChanData->DmaAdapter;
489 PDMA_OPERATIONS DmaOperations = ChanData->DmaAdapter->DmaOperations;
490 PHYSICAL_ADDRESS PrdTablePhysicalAddress;
491
492 PAGED_CODE();
493
494 if (!ChanData->PrdTable)
495 return;
496
497 PrdTablePhysicalAddress.QuadPart = ChanData->PrdTablePhysicalAddress;
498
499 DmaOperations->FreeCommonBuffer(DmaAdapter,
500 sizeof(*ChanData->PrdTable) * ChanData->MaximumPhysicalPages,
501 PrdTablePhysicalAddress,
502 ChanData->PrdTable,
503 TRUE); // Cached
504 ChanData->PrdTable = NULL;
505}
506
507static
508CODE_SEG("PAGE")
511 _In_ PVOID ChannelContext)
512{
513 PCHANNEL_DATA_PATA ChanData = ChannelContext;
514 PDMA_OPERATIONS DmaOperations = ChanData->DmaAdapter->DmaOperations;
515 PHYSICAL_ADDRESS LogicalAddress;
517
518 PAGED_CODE();
519
520 BlockSize = sizeof(*ChanData->PrdTable) * ChanData->MaximumPhysicalPages;
521 ChanData->PrdTable = DmaOperations->AllocateCommonBuffer(ChanData->DmaAdapter,
522 BlockSize,
523 &LogicalAddress,
524 TRUE); // Cached
525 if (!ChanData->PrdTable)
527 RtlZeroMemory(ChanData->PrdTable, BlockSize);
528
529 ChanData->PrdTablePhysicalAddress = LogicalAddress.LowPart;
530
531 /* 32-bit DMA */
532 ASSERT(LogicalAddress.HighPart == 0);
533
534 /* The descriptor table must be 4 byte aligned */
535 ASSERT((LogicalAddress.LowPart % sizeof(ULONG)) == 0);
536
537 return STATUS_SUCCESS;
538}
539
540static
541CODE_SEG("PAGE")
544 _In_ UCHAR DmaStatus)
545{
546 PAGED_CODE();
547
548 /* The status bits [3:4] must return 0 on reads */
550 {
551 /*
552 * Not a PCI IDE DMA device. This may happen when the channel is disabled
553 * (e.g. 8086:8C00 returns 0xFF for disabled SATA channels).
554 */
555 return FALSE;
556 }
557
558 return TRUE;
559}
560
561static
562CODE_SEG("PAGE")
566{
567 ULONG i;
568
569 PAGED_CODE();
570
571 if (!(Controller->Pci.Command & PCI_ENABLE_BUS_MASTER))
572 {
573 WARN("%04X:%04X.%02X: PCI bus mastering disabled\n",
574 Controller->Pci.VendorID,
575 Controller->Pci.DeviceID,
576 Controller->Pci.RevisionID);
577 return FALSE;
578 }
579
580 /*
581 * Assume that all RAID controllers are DMA capable.
582 * (ProgIF can be initialized to 0 on VIA VT6421)
583 */
584 if ((Controller->Pci.BaseClass == PCI_CLASS_MASS_STORAGE_CTLR) &&
585 (Controller->Pci.SubClass == PCI_SUBCLASS_MSC_IDE_CTLR) &&
586 !(Controller->Pci.ProgIf & PCIIDE_PROGIF_DMA_CAPABLE))
587 {
588 WARN("%04X:%04X.%02X: Non DMA capable controller detected\n",
589 Controller->Pci.VendorID,
590 Controller->Pci.DeviceID,
591 Controller->Pci.RevisionID);
592 return FALSE;
593 }
594
595 /* Assign DMA resources */
596 if (!(Controller->Flags & CTRL_FLAG_MANUAL_RES))
597 {
598 PUCHAR IoBase;
599
600 /* Check if BAR4 is available */
602 if (!IoBase)
603 {
604 if (Controller->AccessRange[PCIIDE_DMA_IO_BAR].Flags & RANGE_IS_VALID)
605 ERR("Failed to map bus master registers");
606 else
607 INFO("No bus master registers");
608 return FALSE;
609 }
610
611 for (i = 0; i < Controller->MaxChannels; ++i)
612 {
613 PCHANNEL_DATA_PATA ChanData = Controller->Channels[i];
614
615 if (Controller->AccessRange[PCIIDE_DMA_IO_BAR].Flags & RANGE_IS_MAPPED)
616 ChanData->ChanInfo |= CHANNEL_FLAG_MRES_DMA;
617
618 if (!IS_PRIMARY_CHANNEL(ChanData))
620
621 /*
622 * Save the DMA I/O address *in any case*. Some PATA controllers (Intel ICH)
623 * assert the DMA interrupt even if the current command is a PIO command,
624 * so we have to always clear the DMA interrupt.
625 */
626 ChanData->Regs.Dma = IoBase;
627
630 }
631 }
632
633 for (i = 0; i < Controller->MaxChannels; ++i)
634 {
635 PCHANNEL_DATA_PATA ChanData = Controller->Channels[i];
636 UCHAR DmaStatus;
637
638 /* This channel does not support DMA */
639 if (!(ChanData->TransferModeSupported & ~PIO_ALL))
640 continue;
641
642 ASSERT(ChanData->Regs.Dma != NULL);
643
644 DmaStatus = ATA_READ(ChanData->Regs.Dma + PCIIDE_DMA_STATUS, ChanData, MRES_DMA);
645 if (!PciIdeIsDmaStatusValid(DmaStatus))
646 {
647 WARN("CH %lu: %p DMA 0x%02X\n", ChanData->Channel, ChanData->Regs.Dma, DmaStatus);
648 ChanData->TransferModeSupported &= PIO_ALL;
649 continue;
650 }
651
652 INFO("CH %lu: %p DMA 0x%02X\n", ChanData->Channel, ChanData->Regs.Dma, DmaStatus);
653
654 /* We look at the primary channel status register to determine the simplex mode */
655 if ((i == 0) && (Controller->MaxChannels > 1))
656 {
657 if (DmaStatus & PCIIDE_DMA_STATUS_SIMPLEX)
659 }
660
661 /* The status bits 5:6 are set by the BIOS firmware at boot */
663 ChanData->ChanInfo |= CHANNEL_FLAG_DRIVE0_DMA_CAPABLE;
665 ChanData->ChanInfo |= CHANNEL_FLAG_DRIVE1_DMA_CAPABLE;
666 }
667
668 return TRUE;
669}
670
671CODE_SEG("PAGE")
672VOID
674 _In_ PCHANNEL_DATA_PATA ChanData,
675 _In_ ULONG_PTR CommandPortBase,
676 _In_ ULONG_PTR ControlPortBase,
677 _In_ ULONG CommandBlockSpare)
678{
679 PIDE_REGISTERS Registers = &ChanData->Regs;
680
681 PAGED_CODE();
682
683 /* Standard PATA register layout */
684 Registers->Data = (PVOID)(CommandPortBase + 0 * CommandBlockSpare);
685 Registers->Error = (PVOID)(CommandPortBase + 1 * CommandBlockSpare);
686 Registers->SectorCount = (PVOID)(CommandPortBase + 2 * CommandBlockSpare);
687 Registers->LbaLow = (PVOID)(CommandPortBase + 3 * CommandBlockSpare);
688 Registers->LbaMid = (PVOID)(CommandPortBase + 4 * CommandBlockSpare);
689 Registers->LbaHigh = (PVOID)(CommandPortBase + 5 * CommandBlockSpare);
690 Registers->Device = (PVOID)(CommandPortBase + 6 * CommandBlockSpare);
691 Registers->Status = (PVOID)(CommandPortBase + 7 * CommandBlockSpare);
692
693 Registers->Control = (PVOID)ControlPortBase;
694}
695
696static
697CODE_SEG("PAGE")
701 _In_ PCHANNEL_DATA_PATA ChanData)
702{
703 PVOID CommandPortBase, ControlPortBase;
704 const ULONG BarIndex = ChanData->Channel * 2;
705
706 PAGED_CODE();
707
708 CommandPortBase = AtaCtrlPciMapBar(Controller, BarIndex, PCIIDE_COMMAND_IO_RANGE_LENGTH);
709 if (!CommandPortBase)
711
712 ControlPortBase = AtaCtrlPciMapBar(Controller, BarIndex + 1, PCIIDE_CONTROL_IO_RANGE_LENGTH);
713 if (!ControlPortBase)
715
716 if (Controller->AccessRange[BarIndex].Flags & RANGE_IS_MAPPED)
717 ChanData->ChanInfo |= CHANNEL_FLAG_MRES_TF;
718
719 if (Controller->AccessRange[BarIndex + 1].Flags & RANGE_IS_MAPPED)
720 ChanData->ChanInfo |= CHANNEL_FLAG_MRES_CTRL;
721
723 (ULONG_PTR)CommandPortBase,
724 (ULONG_PTR)ControlPortBase + PCIIDE_CONTROL_IO_BAR_OFFSET,
725 1);
726
727 return STATUS_SUCCESS;
728}
729
730static
731CODE_SEG("PAGE")
734 _In_ PCHANNEL_DATA_PATA ChanData,
736{
737 PCM_PARTIAL_RESOURCE_DESCRIPTOR CommandPortDesc = NULL;
738 PCM_PARTIAL_RESOURCE_DESCRIPTOR ControlPortDesc = NULL;
740 ULONG i, Spare;
741
742 PAGED_CODE();
743
746
747 for (i = 0; i < ResourcesTranslated->List[0].PartialResourceList.Count; ++i)
748 {
750
751 Desc = &ResourcesTranslated->List[0].PartialResourceList.PartialDescriptors[i];
752 switch (Desc->Type)
753 {
756 {
757 if (IsNEC_98 && (ResourcesTranslated->List[0].PartialResourceList.Count >= 12))
758 {
759 if ((Desc->u.Port.Start.QuadPart == 0x640))
760 {
761 CommandPortDesc = Desc;
762 ChanData->ChanInfo |= CHANNEL_FLAG_CBUS;
763 }
764 else if ((Desc->u.Port.Start.QuadPart == 0x74C))
765 {
766 ControlPortDesc = Desc;
767 ChanData->ChanInfo |= CHANNEL_FLAG_CBUS;
768 }
769 }
770 else if (Desc->u.Port.Length == PCIIDE_LEGACY_CONTROL_IO_RANGE_LENGTH)
771 {
772 if (!ControlPortDesc)
773 ControlPortDesc = Desc;
774 }
775 else if (Desc->u.Port.Length == PCIIDE_LEGACY_COMMAND_IO_RANGE_LENGTH)
776 {
777 if (!CommandPortDesc)
778 CommandPortDesc = Desc;
779 }
780
781 break;
782 }
783
785 {
786 if (!InterruptDesc)
787 InterruptDesc = Desc;
788 break;
789 }
790
791 default:
792 break;
793 }
794 }
795
796 if (!CommandPortDesc || !ControlPortDesc || !InterruptDesc)
798
799 if (CommandPortDesc->Type == CmResourceTypeMemory)
800 ChanData->ChanInfo |= CHANNEL_FLAG_MRES_TF;
801
802 if (ControlPortDesc->Type == CmResourceTypeMemory)
803 ChanData->ChanInfo |= CHANNEL_FLAG_MRES_CTRL;
804
805 RtlCopyMemory(&ChanData->InterruptDesc, InterruptDesc, sizeof(*InterruptDesc));
806
807#if defined(_M_IX86)
808 if (ChanData->ChanInfo & CHANNEL_FLAG_CBUS)
809 {
810 Spare = 2;
811 }
812 else
813#endif
814 {
815 Spare = 1;
816 }
818 (ULONG_PTR)CommandPortDesc->u.Port.Start.QuadPart,
819 (ULONG_PTR)ControlPortDesc->u.Port.Start.QuadPart,
820 Spare);
821
822 return STATUS_SUCCESS;
823}
824
825/*
826 * PCI IDE Notes:
827 *
828 * When the PCI IDE controller operates in compatibility mode,
829 * the pciidex driver assigns a list of boot resources to each IDE channel.
830 *
831 * _GTM, _STM _GTF
832 * PCI0-->IDE0---------------------------+-->CHN0---------------------------+-->DRV0
833 * IO: Start 0:FFA0, Len 10 | IO: Start 0:1F0, Len 8 |
834 * | IO: Start 0:3F6, Len 1 \-->DRV1
835 * | INT: Lev A Vec A Aff FFFFFFFF
836 * |
837 * \-->CHN1---------------------------+-->DRV0
838 * IO: Start 0:170, Len 8 |
839 * IO: Start 0:376, Len 1 \-->DRV1
840 * INT: Lvl F Vec F Aff FFFFFFFF
841 *
842 * In native-PCI mode, the PCI IDE controller acts as a true PCI device
843 * and no resources are assigned to the channel device object at all.
844 *
845 * _GTM, _STM _GTF
846 * PCI0-->IDE0---------------------------+-->CHN0---------------------------+-->DRV0
847 * IO: Start 0:FFC0, Len 8 | |
848 * IO: Start 0:FF8C, Len 4 | \-->DRV1
849 * IO: Start 0:FF80, Len 8 |
850 * IO: Start 0:FF88, Len 4 |
851 * IO: Start 0:FFA0, Len 10 \-->CHN1---------------------------+-->DRV0
852 * INT: Lvl B Vec B Aff FFFFFFFF |
853 * \-->DRV1
854 *
855 * Note that the NT architecture does not support switching only one IDE channel to native mode.
856 */
857CODE_SEG("PAGE")
860 _In_ PCHANNEL_DATA_PATA ChanData,
862{
863 PATA_CONTROLLER Controller = ChanData->Controller;
865
866 PAGED_CODE();
867
868 ASSERT(ChanData->Channel < 2);
869
870 if (Controller->Flags & CTRL_FLAG_NATIVE_PCI)
872 else
874 if (!NT_SUCCESS(Status))
875 {
876 ERR("CH %lu: Failed to assign I/O resources 0x%lx\n", ChanData->Channel, Status);
877 return Status;
878 }
879
881
882 return STATUS_SUCCESS;
883}
884
885CODE_SEG("PAGE")
886VOID
888 _In_ PVOID ChannelContext)
889{
890 PCHANNEL_DATA_PATA ChanData = ChannelContext;
891
892 PAGED_CODE();
893
894 if (ChanData->InterruptObject)
895 {
897
898 IoDisconnectInterrupt(ChanData->InterruptObject);
899 ChanData->InterruptObject = NULL;
900 }
901
902 ChanData->Regs.Dma = NULL;
903
904 ChanData->ChanInfo &= ~(CHANNEL_FLAG_DRIVE0_DMA_CAPABLE |
906
908}
909
910CODE_SEG("PAGE")
915{
916 PAGED_CODE();
917
918 /* SFF-8038i compliant hardware */
919 if (Controller->Flags & CTRL_FLAG_NATIVE_PCI)
920 {
921 /*
922 * If any native PCI IDE channel is enabled,
923 * its PCI I/O resources should be allocated as well:
924 *
925 * [BAR 0] I/O ports at FFC0 [size=8] Channel 0 task file registers
926 * [BAR 1] I/O ports at FF8C [size=4] Channel 0 device control
927 * [BAR 2] I/O ports at FF80 [size=8] Channel 1 task file registers
928 * [BAR 3] I/O ports at FF88 [size=4] Channel 1 device control
929 * [BAR 4] I/O ports at FFA0 [size=16] Bus Mastering registers
930 * [BAR 5] Memory at FE780000 Aux registers
931 */
932 if (!(Controller->Flags & CTRL_FLAG_MANUAL_RES))
933 {
934 const ULONG BarIndex = Channel * 2;
935
936 ASSERT(Channel < 2);
937
938 /* Check task file registers */
939 if (!(Controller->AccessRange[BarIndex].Flags & RANGE_IS_VALID))
940 return ChannelDisabled;
941
942 /* Check device control */
943 if (!(Controller->AccessRange[BarIndex + 1].Flags & RANGE_IS_VALID))
944 return ChannelDisabled;
945 }
946 }
947
948 if (Controller->ChannelEnableBits)
949 {
951 {
952 /* Device-specific test */
953 return Controller->ChannelEnabledTest(Controller, Channel);
954 }
955 else
956 {
957 const ATA_PCI_ENABLE_BITS* EnableBits = &Controller->ChannelEnableBits[Channel];
958 UCHAR RegisterValue;
959
960 /* Test PCI bits */
961 RegisterValue = PciRead8(Controller, EnableBits->Register);
962 if ((RegisterValue & EnableBits->Mask) == EnableBits->ValueEnabled)
963 return ChannelEnabled;
964 else
965 return ChannelDisabled;
966 }
967 }
968
969 /* This channel is always enabled */
970 return ChannelStateUnknown;
971}
972
973static
974VOID
976 _In_ PVOID ChannelContext,
978{
979 PCHANNEL_DATA_PATA ChanData = ChannelContext;
981
982 INFO("CH %lu: %sable interrupts\n", ChanData->Channel, Enable ? "En" : "Dis");
983
985 if (Enable)
987 else
989
990#if defined(_M_IX86)
991 if (ChanData->ChanInfo & CHANNEL_FLAG_CBUS)
992 {
994 ATA_WRITE(ChanData->Regs.Control, Control, ChanData, MRES_CTRL);
995
996 /* Clear interrupts */
997 if (ChanData->CheckInterrupt)
998 ChanData->CheckInterrupt(ChanData);
999 ChanData->ReadStatus(ChanData);
1000
1002 ChanData->LastAtaBankId = 0xFF;
1003 }
1004#endif
1005 ATA_WRITE(ChanData->Regs.Control, Control, ChanData, MRES_CTRL);
1006
1007 /* Clear interrupts */
1008 if (ChanData->CheckInterrupt)
1009 ChanData->CheckInterrupt(ChanData);
1010 ChanData->ReadStatus(ChanData);
1011
1012 if (ChanData->Regs.Dma != NULL)
1013 {
1014 UCHAR Status = ATA_READ(ChanData->Regs.Dma + PCIIDE_DMA_STATUS, ChanData, MRES_DMA);
1015
1016 ATA_WRITE(ChanData->Regs.Dma + PCIIDE_DMA_STATUS, Status, ChanData, MRES_DMA);
1017 }
1018}
1019
1020CODE_SEG("PAGE")
1023 _In_ PVOID ChannelContext)
1024{
1025 PCHANNEL_DATA_PATA ChanData = ChannelContext;
1026 PATA_CONTROLLER Controller = ChanData->Controller;
1027 PCM_PARTIAL_RESOURCE_DESCRIPTOR InterruptDesc;
1028 PKSERVICE_ROUTINE IsrHandler;
1030
1031 PAGED_CODE();
1032
1033 if (Controller->Flags & CTRL_FLAG_NATIVE_PCI)
1034 InterruptDesc = &Controller->InterruptDesc;
1035 else
1036 InterruptDesc = &ChanData->InterruptDesc;
1037 ASSERT(InterruptDesc);
1038
1039 if (ChanData->Regs.Dma != NULL)
1040 IsrHandler = PciIdeChannelIsr;
1041 else
1042 IsrHandler = PataChannelIsr;
1043 Status = IoConnectInterrupt(&ChanData->InterruptObject,
1044 IsrHandler,
1045 ChanData,
1046 NULL,
1047 InterruptDesc->u.Interrupt.Vector,
1048 InterruptDesc->u.Interrupt.Level,
1049 InterruptDesc->u.Interrupt.Level,
1050 (InterruptDesc->Flags & CM_RESOURCE_INTERRUPT_LATCHED)
1052 (InterruptDesc->ShareDisposition == CmResourceShareShared),
1053 InterruptDesc->u.Interrupt.Affinity,
1054 FALSE);
1055 if (!NT_SUCCESS(Status))
1056 {
1057 ERR("Could not connect to interrupt %lu, status 0x%lx\n",
1058 InterruptDesc->u.Interrupt.Vector, Status);
1059 return Status;
1060 }
1061
1062 return STATUS_SUCCESS;
1063}
1064
1065CODE_SEG("PAGE")
1068 _In_ PVOID ChannelContext,
1069 _In_ BOOLEAN Attach)
1070{
1071 PCHANNEL_DATA_PATA ChanData = ChannelContext;
1072
1073 PAGED_CODE();
1074
1075 AtaChanEnableInterruptsSync(ChanData, Attach);
1076
1077 return STATUS_SUCCESS;
1078}
1079
1080CODE_SEG("PAGE")
1084 _In_ ULONG HwExtensionSize)
1085{
1086 PCHANNEL_DATA_PATA ChanData;
1087 ULONG i, Size;
1088
1089 PAGED_CODE();
1090 ASSERT(Controller->MaxChannels != 0);
1091
1092 Size = FIELD_OFFSET(CHANNEL_DATA_PATA, HwExt) + HwExtensionSize;
1093 ChanData = ExAllocatePoolZero(NonPagedPool, Size * Controller->MaxChannels, TAG_PCIIDEX);
1094 if (!ChanData)
1096
1097 Controller->ChanDataBlock = ChanData;
1098 Controller->ChannelBitmap = NUM_TO_BITMAP(Controller->MaxChannels);
1099
1100 for (i = 0; i < Controller->MaxChannels; ++i)
1101 {
1102 Controller->Channels[i] = ChanData;
1103
1104 ChanData->Channel = i;
1105 ChanData->Controller = Controller;
1106
1107 /* Set default values */
1108 ChanData->ChanInfo = CHANNEL_FLAG_IO32;
1109 ChanData->AllocateMemory = PciIdeAllocateMemory;
1110 ChanData->FreeMemory = PciIdeFreeMemory;
1111 ChanData->EnableInterrupts = PataEnableInterrupts;
1112 ChanData->PreparePrdTable = PciIdePreparePrdTable;
1113 ChanData->PrepareIo = PataPrepareIo;
1114 ChanData->StartIo = PataStartIo;
1115 ChanData->LoadTaskFile = PataLoadTaskFile;
1116 ChanData->SaveTaskFile = PataSaveTaskFile;
1117 ChanData->ReadStatus = PataReadStatus;
1118 ChanData->SetTransferMode = PciIdeGenericSetTransferMode;
1119 ChanData->TransferModeSupported = PIO_ALL | SWDMA_ALL | MWDMA_ALL | UDMA_ALL;
1120
1122
1123 ChanData = (PVOID)((ULONG_PTR)ChanData + Size);
1124 }
1125
1126 return STATUS_SUCCESS;
1127}
1128
1129CODE_SEG("PAGE")
1133{
1135 ULONG i;
1136
1137 PAGED_CODE();
1138
1139 Controller->MaxChannels = MAX_IDE_CHANNEL;
1140
1141 /* Match the controller through the PCI ID */
1142 switch (Controller->Pci.VendorID)
1143 {
1144 case PCI_VEN_ATI:
1146 break;
1147 case PCI_VEN_AMD:
1148 case PCI_VEN_NVIDIA:
1150 break;
1151 case PCI_VEN_CMD:
1153 if (Status == STATUS_NO_MATCH)
1155 break;
1156 case PCI_VEN_HIGHPOINT:
1158 break;
1159 case PCI_VEN_INTEL:
1161 break;
1162 case PCI_VEN_PC_TECH:
1164 break;
1167 if (Status == STATUS_NO_MATCH)
1169 break;
1170 case PCI_VEN_TOSHIBA:
1172 break;
1173 case PCI_VEN_VIA:
1175 break;
1176
1177 default:
1179 break;
1180 }
1181
1182 /* Try to use the generic PCI IDE minidriver */
1183 if (Status == STATUS_NO_MATCH)
1184 {
1185 if ((Controller->Pci.BaseClass != PCI_CLASS_MASS_STORAGE_CTLR) ||
1186 ((Controller->Pci.SubClass != PCI_SUBCLASS_MSC_IDE_CTLR) &&
1187 (Controller->Pci.SubClass != PCI_SUBCLASS_MSC_RAID_CTLR)))
1188 {
1189 ERR("%04X:%04X.%02X: Unsupported controller\n",
1190 Controller->Pci.VendorID,
1191 Controller->Pci.DeviceID,
1192 Controller->Pci.RevisionID);
1193 return Status;
1194 }
1195
1196 WARN("%04X:%04X.%02X: Using generic PCI IDE minidriver\n",
1197 Controller->Pci.VendorID,
1198 Controller->Pci.DeviceID,
1199 Controller->Pci.RevisionID);
1200
1202 if (!NT_SUCCESS(Status))
1203 return Status;
1204
1205 /* Disable 32-bit I/O for unknown controllers */
1206 for (i = 0; i < Controller->MaxChannels; ++i)
1207 {
1208 PCHANNEL_DATA_PATA ChanData = Controller->Channels[i];
1209
1210 ChanData->ChanInfo &= ~CHANNEL_FLAG_IO32;
1211 }
1212 }
1213
1214 if (!NT_SUCCESS(Status))
1215 return Status;
1216
1217 /*
1218 * Check for a legacy PCI IDE device.
1219 * NOTE: NT architecture does not support switching only one IDE channel to native mode.
1220 */
1221 if ((Controller->Pci.BaseClass == PCI_CLASS_MASS_STORAGE_CTLR) &&
1222 (Controller->Pci.SubClass == PCI_SUBCLASS_MSC_IDE_CTLR))
1223 {
1226 {
1227 Controller->Flags &= ~CTRL_FLAG_NATIVE_PCI;
1228 }
1229 }
1230
1231 if (Controller->Flags & CTRL_FLAG_NATIVE_PCI)
1232 {
1233 if (Controller->InterruptDesc.Type != CmResourceTypeInterrupt)
1234 {
1235 ERR("No interrupt resource\n");
1237 }
1238 }
1239
1241 {
1242 for (i = 0; i < Controller->MaxChannels; ++i)
1243 {
1244 PCHANNEL_DATA_PATA ChanData = Controller->Channels[i];
1245
1246 ChanData->TransferModeSupported &= PIO_ALL;
1247 }
1248 }
1249
1250 if (Controller->Flags & CTRL_FLAG_IS_SIMPLEX)
1251 {
1252 WARN("Sync access for hardware is required\n");
1253
1254 Controller->HwSyncObject = IoCreateController(0);
1255 if (!Controller->HwSyncObject)
1257 }
1258
1259 return STATUS_SUCCESS;
1260}
#define PAGED_CODE()
#define CODE_SEG(...)
#define RTL_NUMBER_OF(x)
Definition: RtlRegistry.c:12
BOOLEAN AtaAcpiGetTimingMode(_In_ PDEVICE_OBJECT DeviceObject, _Out_ PIDE_ACPI_TIMING_MODE_BLOCK TimingMode)
Definition: acpi.c:119
NTSTATUS AtaAcpiSetTimingMode(_In_ PDEVICE_OBJECT DeviceObject, _In_ PIDE_ACPI_TIMING_MODE_BLOCK TimingMode, _In_opt_ PIDENTIFY_DEVICE_DATA IdBlock1, _In_opt_ PIDENTIFY_DEVICE_DATA IdBlock2)
Definition: acpi.c:168
unsigned char BOOLEAN
Definition: actypes.h:127
NTSTATUS AmdGetControllerProperties(_Inout_ PATA_CONTROLLER Controller)
Definition: amd.c:329
#define IDE_ACPI_TIMING_MODE_NOT_SUPPORTED
Definition: ata_shared.h:42
#define IDE_ACPI_TIMING_MODE_FLAG_UDMA(Drive)
Definition: ata_shared.h:47
#define IDE_ACPI_TIMING_MODE_FLAG_INDEPENDENT_TIMINGS
Definition: ata_shared.h:53
#define UDMA_ALL
Definition: ata_user.h:31
#define MWDMA_ALL
Definition: ata_user.h:27
#define PIO_MODE(n)
Definition: ata_user.h:36
#define SWDMA_ALL
Definition: ata_user.h:23
#define MWDMA_MODE(n)
Definition: ata_user.h:38
#define SWDMA_MODE(n)
Definition: ata_user.h:37
#define PIO_ALL
Definition: ata_user.h:19
#define UDMA_MODE(n)
Definition: ata_user.h:39
#define NUM_TO_BITMAP(num)
Definition: atapi.h:179
#define IDE_DC_DISABLE_INTERRUPTS
Definition: atapi.h:145
#define IDE_DC_REENABLE_CONTROLLER
Definition: atapi.h:147
NTSTATUS AtiGetControllerProperties(_Inout_ PATA_CONTROLLER Controller)
Definition: ati.c:36
LONG NTSTATUS
Definition: precomp.h:26
#define WARN(fmt,...)
Definition: precomp.h:61
#define ERR(fmt,...)
Definition: precomp.h:57
PCONTROLLER_OBJECT NTAPI IoCreateController(IN ULONG Size)
Definition: controller.c:57
D3D12_VIDEO_MOTION_ESTIMATOR_SEARCH_BLOCK_SIZE BlockSize
Definition: d3d12video.idl:529
_In_ D3DDDI_VIDEO_PRESENT_TARGET_ID _In_ ULONG _In_ ULONG Flags
Definition: dispmprt.h:245
#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
PDEVICE_LIST DeviceList
Definition: utils.c:27
VOID NTAPI KeInitializeDpc(IN PKDPC Dpc, IN PKDEFERRED_ROUTINE DeferredRoutine, IN PVOID DeferredContext)
Definition: dpc.c:712
#define INFO
Definition: debug.h:89
NTSTATUS CmdGetControllerProperties(_Inout_ PATA_CONTROLLER Controller)
Definition: cmd.c:460
#define UlongToPtr(u)
Definition: config.h:106
#define NonPagedPool
Definition: env_spec_w32.h:307
Status
Definition: gdiplustypes.h:24
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
NTSTATUS HptGetControllerProperties(_Inout_ PATA_CONTROLLER Controller)
Definition: hpt.c:316
_In_ ULONG Mode
Definition: hubbusif.h:303
_Must_inspect_result_ _In_ PUCXHUB_DEVICE_CREATE_INFO _Out_ UCXUSBDEVICE * Device
Definition: hubucx.h:258
#define ATA_WRITE(Port, Value)
Definition: hwidep.h:80
#define IDE_DC_ALWAYS
Definition: hwidep.h:54
#define ATA_READ(Port)
Definition: hwidep.h:89
#define MAX_IDE_DEVICE
Definition: ide.h:32
IDE_CHANNEL_STATE
Definition: ide.h:196
@ ChannelDisabled
Definition: ide.h:197
@ ChannelStateUnknown
Definition: ide.h:199
@ ChannelEnabled
Definition: ide.h:198
#define MAX_IDE_CHANNEL
Definition: ide.h:30
#define NOTHING
Definition: input_list.c:10
NTSTATUS IntelGetControllerProperties(_Inout_ PATA_CONTROLLER Controller)
Definition: intel.c:969
PCONFIGURATION_INFORMATION NTAPI IoGetConfigurationInformation(VOID)
Returns a pointer to the I/O manager's global configuration information structure.
Definition: iorsrce.c:998
#define ASSERT(a)
Definition: mode.c:44
static PVOID ExAllocatePoolZero(ULONG PoolType, SIZE_T NumberOfBytes, ULONG Tag)
Definition: precomp.h:45
#define min(a, b)
Definition: monoChain.cc:55
#define _In_reads_(s)
Definition: no_sal2.h:168
#define _Inout_
Definition: no_sal2.h:162
#define _Out_
Definition: no_sal2.h:160
#define _In_
Definition: no_sal2.h:158
#define _In_range_(l, h)
Definition: no_sal2.h:368
#define _Out_writes_all_(s)
Definition: no_sal2.h:192
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:329
_In_ ULONGLONG _In_ ULONGLONG _In_ BOOLEAN Enable
Definition: ntddpcm.h:142
VOID NTAPI IoDisconnectInterrupt(PKINTERRUPT InterruptObject)
Definition: irq.c:142
NTSTATUS NTAPI IoConnectInterrupt(OUT PKINTERRUPT *InterruptObject, IN PKSERVICE_ROUTINE ServiceRoutine, IN PVOID ServiceContext, IN PKSPIN_LOCK SpinLock, IN ULONG Vector, IN KIRQL Irql, IN KIRQL SynchronizeIrql, IN KINTERRUPT_MODE InterruptMode, IN BOOLEAN ShareVector, IN KAFFINITY ProcessorEnableMask, IN BOOLEAN FloatingSave)
Definition: irq.c:23
#define STATUS_NO_MATCH
Definition: ntstatus.h:873
#define STATUS_DEVICE_CONFIGURATION_ERROR
Definition: ntstatus.h:713
#define PCI_VEN_CMD
Definition: pata.h:14
#define PCIIDE_DMA_STATUS_RESERVED1
Definition: pata.h:129
#define PCIIDE_PROGIF_SECONDARY_CHANNEL_NATIVE_MODE
Definition: pata.h:98
#define PCI_VEN_INTEL
Definition: pata.h:20
#define PCI_VEN_ATI
Definition: pata.h:10
#define PCI_VEN_TOSHIBA
Definition: pata.h:18
#define PCIIDE_DMA_STATUS
Definition: pata.h:108
#define SHARED_DATA_TIMINGS
Definition: pata.h:232
#define PCIIDE_DMA_STATUS_RESERVED2
Definition: pata.h:130
#define PCIIDE_DMA_STATUS_DRIVE1_DMA_CAPABLE
Definition: pata.h:132
#define SHARED_CMD_TIMINGS
Definition: pata.h:231
#define PCI_VEN_NVIDIA
Definition: pata.h:12
#define PCI_VEN_AMD
Definition: pata.h:11
#define PCIIDE_LEGACY_SECONDARY_COMMAND_BASE
Definition: pata.h:78
#define PCIIDE_PROGIF_DMA_CAPABLE
Definition: pata.h:100
#define PCIIDE_DMA_SECONDARY_CHANNEL_OFFSET
Definition: pata.h:90
#define PCIIDE_DMA_IO_BAR
Definition: pata.h:86
#define PCIIDE_COMMAND_IO_RANGE_LENGTH
Definition: pata.h:83
#define PCI_VEN_VIA
Definition: pata.h:16
#define PCI_VEN_PC_TECH
Definition: pata.h:13
#define PCIIDE_PROGIF_PRIMARY_CHANNEL_NATIVE_MODE
Definition: pata.h:96
#define PC98_ATA_BANK
Definition: pata.h:29
#define PCIIDE_LEGACY_COMMAND_IO_RANGE_LENGTH
Definition: pata.h:73
#define PCIIDE_LEGACY_CONTROL_IO_RANGE_LENGTH
Definition: pata.h:74
#define PCIIDE_CONTROL_IO_RANGE_LENGTH
Definition: pata.h:84
#define PCIIDE_DMA_STATUS_SIMPLEX
Definition: pata.h:133
#define PCIIDE_DMA_IO_RANGE_LENGTH
Definition: pata.h:87
#define PCIIDE_CONTROL_IO_BAR_OFFSET
Definition: pata.h:85
#define PCIIDE_DMA_STATUS_DRIVE0_DMA_CAPABLE
Definition: pata.h:131
#define SHARED_ADDR_TIMINGS
Definition: pata.h:233
#define PCIIDE_LEGACY_PRIMARY_COMMAND_BASE
Definition: pata.h:75
#define PCI_VEN_SERVERWORKS
Definition: pata.h:17
#define PCI_VEN_HIGHPOINT
Definition: pata.h:15
USHORT ATATIM
Definition: pata.h:218
static VOID PataClaimLegacyAddressRanges(_In_ PCHANNEL_DATA_PATA ChanData)
Definition: pata_generic.c:451
VOID AtaSelectTimings(_In_reads_(MAX_IDE_DEVICE) PCHANNEL_DEVICE_CONFIG *DeviceList, _Out_writes_all_(MAX_IDE_DEVICE) PATA_TIMING Timings, _In_range_(>, 0) ULONG ClockPeriodPs, _In_ ULONG Flags)
Definition: pata_generic.c:116
NTSTATUS PciIdeParseResources(_In_ PCHANNEL_DATA_PATA ChanData, _In_ PCM_RESOURCE_LIST ResourcesTranslated)
Definition: pata_generic.c:859
static ATATIM AtaGetClocks(_In_ ATATIM TimingValueNs, _In_ ULONG ClockPeriodPs)
Definition: pata_generic.c:53
static const ULONG AtapModeToCycleTime[]
Definition: pata_generic.c:14
static BOOLEAN PciIdeControllerInitDma(_In_ PATA_CONTROLLER Controller)
Definition: pata_generic.c:564
static const ATA_TIMING AtapTimingTable[]
Definition: pata_generic.c:29
IDE_CHANNEL_STATE PciIdeGetChannelState(_In_ PATA_CONTROLLER Controller, _In_ ULONG Channel)
Definition: pata_generic.c:912
static VOID PciIdeAcpiSetTransferMode(_In_ PCHANNEL_DATA_PATA ChanData, _In_reads_(MAX_IDE_DEVICE) PCHANNEL_DEVICE_CONFIG *DeviceList)
Definition: pata_generic.c:259
static NTSTATUS PciIdeAssignNativeResources(_In_ PATA_CONTROLLER Controller, _In_ PCHANNEL_DATA_PATA ChanData)
Definition: pata_generic.c:699
NTSTATUS PciIdeConnectInterrupt(_In_ PVOID ChannelContext)
VOID PciIdeFreeResources(_In_ PVOID ChannelContext)
Definition: pata_generic.c:887
static VOID AtaCalculateTimings(_In_ PCHANNEL_DEVICE_CONFIG Device, _Out_ PATA_TIMING Timing, _In_ ULONG Mode, _In_ ULONG ClockPeriodPs)
Definition: pata_generic.c:62
static NTSTATUS PciIdeAllocateMemory(_In_ PVOID ChannelContext)
Definition: pata_generic.c:510
static VOID PataReleaseLegacyAddressRanges(_In_ PCHANNEL_DATA_PATA ChanData)
Definition: pata_generic.c:432
static VOID PciIdeFreeMemory(_In_ PVOID ChannelContext)
Definition: pata_generic.c:484
static VOID AtaAcpiFindModeForCycleTime(_In_ ULONG GtmCycleTime, _In_ ULONG SupportedModesBitmap, _In_ ULONG CurrentModesBitmap, _In_ ULONG MinimumMode, _In_ ULONG MaximumMode, _Out_ PULONG BestCycleTime, _Out_ PULONG BestMode)
Definition: pata_generic.c:202
NTSTATUS PciIdeCreateChannelData(_In_ PATA_CONTROLLER Controller, _In_ ULONG HwExtensionSize)
static NTSTATUS PciIdeAssignLegacyResources(_In_ PCHANNEL_DATA_PATA ChanData, _In_ PCM_RESOURCE_LIST ResourcesTranslated)
Definition: pata_generic.c:733
static VOID PciIdeBiosSetTransferMode(_In_ PCHANNEL_DATA_PATA ChanData, _In_reads_(MAX_IDE_DEVICE) PCHANNEL_DEVICE_CONFIG *DeviceList)
Definition: pata_generic.c:383
static VOID PataEnableInterrupts(_In_ PVOID ChannelContext, _In_ BOOLEAN Enable)
Definition: pata_generic.c:975
static BOOLEAN PciIdeIsDmaStatusValid(_In_ UCHAR DmaStatus)
Definition: pata_generic.c:543
NTSTATUS PciIdeGetControllerProperties(_Inout_ PATA_CONTROLLER Controller)
VOID PciIdeInitTaskFileIoResources(_In_ PCHANNEL_DATA_PATA ChanData, _In_ ULONG_PTR CommandPortBase, _In_ ULONG_PTR ControlPortBase, _In_ ULONG CommandBlockSpare)
Definition: pata_generic.c:673
#define WRITE_PORT_UCHAR(p, d)
Definition: pc98vid.h:21
CHANNEL_PREPARE_IO PataPrepareIo
Definition: pciidex.h:708
#define CTRL_FLAG_NATIVE_PCI
Definition: pciidex.h:224
FORCEINLINE UCHAR PciRead8(_In_ PATA_CONTROLLER Controller, _In_ ULONG ConfigDataOffset)
Definition: pciidex.h:860
#define CHANNEL_FLAG_MRES_TF
Definition: pciidex.h:281
CHANNEL_LOAD_TASK_FILE PataLoadTaskFile
Definition: pciidex.h:713
#define CHANNEL_FLAG_MRES_DMA
Definition: pciidex.h:282
#define CHANNEL_FLAG_MRES_CTRL
Definition: pciidex.h:283
KDEFERRED_ROUTINE PataPollingTimerDpc
Definition: pciidex.h:716
CHANNEL_START_IO PataStartIo
Definition: pciidex.h:709
#define RANGE_IS_MAPPED
Definition: pciidex.h:192
#define CTRL_FLAG_USE_TEST_FUNCTION
Definition: pciidex.h:227
_In_ ULONG Channel
Definition: pciidex.h:74
#define CHANNEL_FLAG_IO32
Definition: pciidex.h:261
#define CHANNEL_FLAG_DRIVE0_DMA_CAPABLE
Definition: pciidex.h:262
#define CHANNEL_FLAG_PRIMARY_ADDRESS_CLAIMED
Definition: pciidex.h:268
#define IS_PRIMARY_CHANNEL(PdoExtension)
Definition: pciidex.h:43
KSERVICE_ROUTINE PciIdeChannelIsr
Definition: pciidex.h:711
CHANNEL_SAVE_TASK_FILE PataSaveTaskFile
Definition: pciidex.h:714
#define CTRL_FLAG_MANUAL_RES
Definition: pciidex.h:230
CONTROLLER_ATTACH_CHANNEL_EX PciIdeAttachChannel
Definition: pciidex.h:644
KSERVICE_ROUTINE PataChannelIsr
Definition: pciidex.h:710
#define CHANNEL_FLAG_SECONDARY_ADDRESS_CLAIMED
Definition: pciidex.h:269
#define CHANNEL_FLAG_CBUS
Definition: pciidex.h:284
#define CHANNEL_FLAG_DRIVE1_DMA_CAPABLE
Definition: pciidex.h:263
#define CTRL_FLAG_DMA_INTERRUPT
Definition: pciidex.h:231
CHANNEL_SET_MODE_EX SataSetTransferMode
Definition: pciidex.h:640
CHANNEL_CHECK_INTERRUPT PciIdeCheckInterrupt
Definition: pciidex.h:712
CHANNEL_READ_STATUS PataReadStatus
Definition: pciidex.h:715
CHANNEL_PREPARE_PRD_TABLE PciIdePreparePrdTable
Definition: pciidex.h:707
CHANNEL_SET_MODE_EX PciIdeGenericSetTransferMode
Definition: pciidex.h:641
#define CHANNEL_FLAG_HAS_ACPI_GTM
Definition: pciidex.h:276
#define TAG_PCIIDEX
Definition: pciidex.h:32
#define RANGE_IS_VALID
Definition: pciidex.h:190
#define CTRL_FLAG_IS_SIMPLEX
Definition: pciidex.h:225
NTSTATUS PcTechGetControllerProperties(_Inout_ PATA_CONTROLLER Controller)
Definition: pctech.c:41
long LONG
Definition: pedump.c:60
#define CmResourceTypeMemory
Definition: restypes.h:106
#define CmResourceTypePort
Definition: restypes.h:104
#define CM_RESOURCE_INTERRUPT_LATCHED
Definition: restypes.h:117
#define CmResourceTypeInterrupt
Definition: restypes.h:105
@ Latched
Definition: miniport.h:81
@ LevelSensitive
Definition: miniport.h:80
unsigned char _BitScanReverse(unsigned long *_Index, unsigned long _Mask)
Definition: intrin_arm.h:180
#define STATUS_SUCCESS
Definition: shellext.h:65
NTSTATUS Sil680GetControllerProperties(_Inout_ PATA_CONTROLLER Controller)
Definition: sil680.c:214
DECLSPEC_NOINLINE_FROM_PAGED VOID AtaChanEnableInterruptsSync(_In_ PVOID ChannelContext, _In_ BOOLEAN Enable)
Definition: fdo.c:62
PVOID AtaCtrlPciMapBar(_In_ PATA_CONTROLLER Controller, _In_range_(0, PCI_TYPE0_ADDRESSES) ULONG Index, _In_ ULONG MinimumIoLength)
Definition: fdo.c:254
ATATIM CmdRecovery
Definition: pata.h:225
ATATIM CmdActive
Definition: pata.h:224
ATATIM DataRecovery
Definition: pata.h:228
ATATIM AddressSetup
Definition: pata.h:222
ATATIM DataActive
Definition: pata.h:227
PCHANNEL_CHECK_INTERRUPT CheckInterrupt
Definition: pciidex.h:304
PCHANNEL_READ_STATUS ReadStatus
Definition: pciidex.h:300
ULONG PrdTablePhysicalAddress
Definition: pciidex.h:302
KDPC PollingTimerDpc
Definition: pciidex.h:313
PPCIIDE_PRD_TABLE_ENTRY PrdTable
Definition: pciidex.h:301
PCHANNEL_SAVE_TASK_FILE SaveTaskFile
Definition: pciidex.h:299
PCHANNEL_LOAD_TASK_FILE LoadTaskFile
Definition: pciidex.h:298
IDE_REGISTERS Regs
Definition: pciidex.h:303
struct _CM_PARTIAL_RESOURCE_DESCRIPTOR::@494::@496 Port
union _CM_PARTIAL_RESOURCE_DESCRIPTOR::@494 u
struct _CM_PARTIAL_RESOURCE_DESCRIPTOR::@494::@497 Interrupt
BOOLEAN AtDiskPrimaryAddressClaimed
Definition: iotypes.h:4498
BOOLEAN AtDiskSecondaryAddressClaimed
Definition: iotypes.h:4499
PALLOCATE_COMMON_BUFFER AllocateCommonBuffer
Definition: iotypes.h:2650
PFREE_COMMON_BUFFER FreeCommonBuffer
Definition: iotypes.h:2651
struct _IDE_ACPI_TIMING_MODE_BLOCK::@1817 Drive[2]
IDE_REG Error
Definition: hwidep.h:111
IDE_REG Control
Definition: hwidep.h:139
IDE_REG LbaLow
LBA bits 0-7, 24-31.
Definition: hwidep.h:118
IDE_REG LbaMid
LBA bits 8-15, 32-39.
Definition: hwidep.h:121
IDE_REG Data
Definition: hwidep.h:107
IDE_REG Status
Definition: hwidep.h:135
IDE_REG LbaHigh
LBA bits 16-23, 40-47.
Definition: hwidep.h:127
IDE_REG Device
Definition: hwidep.h:131
IDE_REG SectorCount
Definition: hwidep.h:115
#define max(a, b)
Definition: svc.c:63
NTSTATUS SvwPataGetControllerProperties(_Inout_ PATA_CONTROLLER Controller)
Definition: svw_pata.c:288
NTSTATUS SvwSataGetControllerProperties(_Inout_ PATA_CONTROLLER Controller)
Definition: svw_sata.c:215
NTSTATUS ToshibaGetControllerProperties(_Inout_ PATA_CONTROLLER Controller)
Definition: toshiba.c:102
uint32_t * PULONG
Definition: typedefs.h:59
unsigned char UCHAR
Definition: typedefs.h:53
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
void * PVOID
Definition: typedefs.h:50
#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
_Must_inspect_result_ _In_ WDFDEVICE _In_ PUCX_CONTROLLER_CONFIG _In_opt_ PWDF_OBJECT_ATTRIBUTES _Out_ UCXCONTROLLER * Controller
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
LONGLONG QuadPart
Definition: typedefs.h:114
ULONG LowPart
Definition: typedefs.h:106
NTSTATUS ViaGetControllerProperties(_Inout_ PATA_CONTROLLER Controller)
Definition: via.c:859
_In_ WDFCMRESLIST _In_ WDFCMRESLIST ResourcesTranslated
Definition: wdfdevice.h:891
_Must_inspect_result_ _In_ WDFDEVICE _In_ PWDF_DEVICE_PROPERTY_DATA _In_ DEVPROPTYPE _In_ ULONG Size
Definition: wdfdevice.h:4539
_In_ WDF_WMI_PROVIDER_CONTROL Control
Definition: wdfwmi.h:166
@ CmResourceShareShared
Definition: cmtypes.h:243
#define PCI_ENABLE_BUS_MASTER
Definition: iotypes.h:3633
#define PCI_CLASS_MASS_STORAGE_CTLR
Definition: iotypes.h:4119
#define PCI_SUBCLASS_MSC_IDE_CTLR
Definition: iotypes.h:4144
#define PCI_SUBCLASS_MSC_RAID_CTLR
Definition: iotypes.h:4147
KSERVICE_ROUTINE * PKSERVICE_ROUTINE
Definition: ketypes.h:580
@ MaximumMode
Definition: ketypes.h:13
#define IsNEC_98
Definition: ketypes.h:979
#define NT_VERIFY(exp)
Definition: rtlfuncs.h:3311