ReactOS 0.4.16-dev-2633-g8dc9e50
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
185 _In_ PATA_CONTROLLER Controller,
188{
189 UNREFERENCED_PARAMETER(Controller);
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
414static
415VOID
417 _In_ PATA_CONTROLLER Controller,
420{
421 PCHANNEL_DATA_PATA ChanData = Controller->Channels[Channel];
422
423 /* Set the PATA transfer timings through ACPI if possible */
424 if (ChanData->ChanInfo & CHANNEL_FLAG_HAS_ACPI_GTM)
426 else
428}
429
430static
431CODE_SEG("PAGE")
432VOID
434 _In_ PCHANNEL_DATA_PATA ChanData)
435{
437
438 PAGED_CODE();
439
440 if (ChanData->ChanInfo & CHANNEL_FLAG_PRIMARY_ADDRESS_CLAIMED)
442 if (ChanData->ChanInfo & CHANNEL_FLAG_SECONDARY_ADDRESS_CLAIMED)
444
445 ChanData->ChanInfo &= ~(CHANNEL_FLAG_PRIMARY_ADDRESS_CLAIMED |
447}
448
449static
450CODE_SEG("PAGE")
451VOID
453 _In_ PCHANNEL_DATA_PATA ChanData)
454{
456
457 PAGED_CODE();
458
459 if (IsNEC_98)
460 {
461 if (ChanData->ChanInfo & CHANNEL_FLAG_CBUS)
462 {
463 ConfigInfo->AtDiskPrimaryAddressClaimed = TRUE;
465
466 ChanData->ChanInfo |= CHANNEL_FLAG_PRIMARY_ADDRESS_CLAIMED |
468 }
469 }
470 else if (ChanData->Regs.Data == UlongToPtr(PCIIDE_LEGACY_PRIMARY_COMMAND_BASE))
471 {
472 ConfigInfo->AtDiskPrimaryAddressClaimed = TRUE;
473 ChanData->ChanInfo |= CHANNEL_FLAG_PRIMARY_ADDRESS_CLAIMED;
474 }
475 else if (ChanData->Regs.Data == UlongToPtr(PCIIDE_LEGACY_SECONDARY_COMMAND_BASE))
476 {
478 ChanData->ChanInfo |= CHANNEL_FLAG_SECONDARY_ADDRESS_CLAIMED;
479 }
480}
481
482static
483CODE_SEG("PAGE")
484VOID
486 _In_ PVOID ChannelContext)
487{
488 PCHANNEL_DATA_PATA ChanData = ChannelContext;
489 PDMA_ADAPTER DmaAdapter = ChanData->DmaAdapter;
490 PDMA_OPERATIONS DmaOperations = ChanData->DmaAdapter->DmaOperations;
491 PHYSICAL_ADDRESS PrdTablePhysicalAddress;
492
493 PAGED_CODE();
494
495 if (!ChanData->PrdTable)
496 return;
497
498 PrdTablePhysicalAddress.QuadPart = ChanData->PrdTablePhysicalAddress;
499
500 DmaOperations->FreeCommonBuffer(DmaAdapter,
501 sizeof(*ChanData->PrdTable) * ChanData->MaximumPhysicalPages,
502 PrdTablePhysicalAddress,
503 ChanData->PrdTable,
504 TRUE); // Cached
505 ChanData->PrdTable = NULL;
506}
507
508static
509CODE_SEG("PAGE")
512 _In_ PVOID ChannelContext)
513{
514 PCHANNEL_DATA_PATA ChanData = ChannelContext;
515 PDMA_OPERATIONS DmaOperations = ChanData->DmaAdapter->DmaOperations;
516 PHYSICAL_ADDRESS LogicalAddress;
517 ULONG BlockSize;
518
519 PAGED_CODE();
520
521 BlockSize = sizeof(*ChanData->PrdTable) * ChanData->MaximumPhysicalPages;
522 ChanData->PrdTable = DmaOperations->AllocateCommonBuffer(ChanData->DmaAdapter,
523 BlockSize,
524 &LogicalAddress,
525 TRUE); // Cached
526 if (!ChanData->PrdTable)
528 RtlZeroMemory(ChanData->PrdTable, BlockSize);
529
530 ChanData->PrdTablePhysicalAddress = LogicalAddress.LowPart;
531
532 /* 32-bit DMA */
533 ASSERT(LogicalAddress.HighPart == 0);
534
535 /* The descriptor table must be 4 byte aligned */
536 ASSERT((LogicalAddress.LowPart % sizeof(ULONG)) == 0);
537
538 return STATUS_SUCCESS;
539}
540
541static
542CODE_SEG("PAGE")
545 _In_ UCHAR DmaStatus)
546{
547 PAGED_CODE();
548
549 /* The status bits [3:4] must return 0 on reads */
551 {
552 /*
553 * Not a PCI IDE DMA device. This may happen when the channel is disabled
554 * (e.g. 8086:8C00 returns 0xFF for disabled SATA channels).
555 */
556 return FALSE;
557 }
558
559 return TRUE;
560}
561
562static
563CODE_SEG("PAGE")
566 _In_ PATA_CONTROLLER Controller)
567{
568 ULONG i;
569
570 PAGED_CODE();
571
572 if (!(Controller->Pci.Command & PCI_ENABLE_BUS_MASTER))
573 {
574 INFO("PCI bus mastering disabled\n");
575 return FALSE;
576 }
577
578 if ((Controller->Pci.BaseClass == PCI_CLASS_MASS_STORAGE_CTLR) &&
579 !(Controller->Pci.ProgIf & PCIIDE_PROGIF_DMA_CAPABLE))
580 {
581 INFO("Non DMA capable controller detected\n");
582 return FALSE;
583 }
584
585 /* Assign DMA resources */
586 if (!(Controller->Flags & CTRL_FLAG_MANUAL_RES))
587 {
588 PUCHAR IoBase;
589
590 /* Check if BAR4 is available */
592 if (!IoBase)
593 {
594 if (Controller->AccessRange[PCIIDE_DMA_IO_BAR].Flags & RANGE_IS_VALID)
595 ERR("Failed to map bus master registers");
596 else
597 INFO("No bus master registers");
598 return FALSE;
599 }
600
601 for (i = 0; i < Controller->MaxChannels; ++i)
602 {
603 PCHANNEL_DATA_PATA ChanData = Controller->Channels[i];
604
605 if (Controller->AccessRange[PCIIDE_DMA_IO_BAR].Flags & RANGE_IS_MAPPED)
606 ChanData->ChanInfo |= CHANNEL_FLAG_MRES_DMA;
607
608 if (!IS_PRIMARY_CHANNEL(ChanData))
610
611 /*
612 * Save the DMA I/O address *in any case*. Some PATA controllers (Intel ICH)
613 * assert the DMA interrupt even if the current command is a PIO command,
614 * so we have to always clear the DMA interrupt.
615 */
616 ChanData->Regs.Dma = IoBase;
617
618 if (Controller->Flags & CTRL_FLAG_DMA_INTERRUPT)
620 }
621 }
622
623 for (i = 0; i < Controller->MaxChannels; ++i)
624 {
625 PCHANNEL_DATA_PATA ChanData = Controller->Channels[i];
626 UCHAR DmaStatus;
627
628 /* This channel does not support DMA */
629 if (!(ChanData->TransferModeSupported & ~PIO_ALL))
630 continue;
631
632 ASSERT(ChanData->Regs.Dma != NULL);
633
634 DmaStatus = ATA_READ(ChanData->Regs.Dma + PCIIDE_DMA_STATUS, ChanData, MRES_DMA);
635 if (!PciIdeIsDmaStatusValid(DmaStatus))
636 {
637 WARN("CH %lu: %p DMA 0x%02X\n", ChanData->Channel, ChanData->Regs.Dma, DmaStatus);
638 ChanData->TransferModeSupported &= PIO_ALL;
639 continue;
640 }
641
642 INFO("CH %lu: %p DMA 0x%02X\n", ChanData->Channel, ChanData->Regs.Dma, DmaStatus);
643
644 /* We look at the primary channel status register to determine the simplex mode */
645 if ((i == 0) && (Controller->MaxChannels > 1))
646 {
647 if (DmaStatus & PCIIDE_DMA_STATUS_SIMPLEX)
648 Controller->Flags |= CTRL_FLAG_IS_SIMPLEX;
649 }
650
651 /* The status bits 5:6 are set by the BIOS firmware at boot */
653 ChanData->ChanInfo |= CHANNEL_FLAG_DRIVE0_DMA_CAPABLE;
655 ChanData->ChanInfo |= CHANNEL_FLAG_DRIVE1_DMA_CAPABLE;
656 }
657
658 return TRUE;
659}
660
661CODE_SEG("PAGE")
662VOID
664 _In_ PCHANNEL_DATA_PATA ChanData,
665 _In_ ULONG_PTR CommandPortBase,
666 _In_ ULONG_PTR ControlPortBase,
667 _In_ ULONG CommandBlockSpare)
668{
669 PIDE_REGISTERS Registers = &ChanData->Regs;
670
671 PAGED_CODE();
672
673 /* Standard PATA register layout */
674 Registers->Data = (PVOID)(CommandPortBase + 0 * CommandBlockSpare);
675 Registers->Error = (PVOID)(CommandPortBase + 1 * CommandBlockSpare);
676 Registers->SectorCount = (PVOID)(CommandPortBase + 2 * CommandBlockSpare);
677 Registers->LbaLow = (PVOID)(CommandPortBase + 3 * CommandBlockSpare);
678 Registers->LbaMid = (PVOID)(CommandPortBase + 4 * CommandBlockSpare);
679 Registers->LbaHigh = (PVOID)(CommandPortBase + 5 * CommandBlockSpare);
680 Registers->Device = (PVOID)(CommandPortBase + 6 * CommandBlockSpare);
681 Registers->Status = (PVOID)(CommandPortBase + 7 * CommandBlockSpare);
682
683 Registers->Control = (PVOID)ControlPortBase;
684}
685
686static
687CODE_SEG("PAGE")
690 _In_ PATA_CONTROLLER Controller,
691 _In_ PCHANNEL_DATA_PATA ChanData)
692{
693 PVOID CommandPortBase, ControlPortBase;
694 const ULONG BarIndex = ChanData->Channel * 2;
695
696 PAGED_CODE();
697
698 CommandPortBase = AtaCtrlPciMapBar(Controller, BarIndex, PCIIDE_COMMAND_IO_RANGE_LENGTH);
699 if (!CommandPortBase)
701
702 ControlPortBase = AtaCtrlPciMapBar(Controller, BarIndex + 1, PCIIDE_CONTROL_IO_RANGE_LENGTH);
703 if (!ControlPortBase)
705
706 if (Controller->AccessRange[BarIndex].Flags & RANGE_IS_MAPPED)
707 ChanData->ChanInfo |= CHANNEL_FLAG_MRES_TF;
708
709 if (Controller->AccessRange[BarIndex + 1].Flags & RANGE_IS_MAPPED)
710 ChanData->ChanInfo |= CHANNEL_FLAG_MRES_CTRL;
711
713 (ULONG_PTR)CommandPortBase,
714 (ULONG_PTR)ControlPortBase + PCIIDE_CONTROL_IO_BAR_OFFSET,
715 1);
716
717 return STATUS_SUCCESS;
718}
719
720static
721CODE_SEG("PAGE")
724 _In_ PCHANNEL_DATA_PATA ChanData,
726{
727 PCM_PARTIAL_RESOURCE_DESCRIPTOR CommandPortDesc = NULL;
728 PCM_PARTIAL_RESOURCE_DESCRIPTOR ControlPortDesc = NULL;
730 ULONG i, Spare;
731
732 PAGED_CODE();
733
736
737 for (i = 0; i < ResourcesTranslated->List[0].PartialResourceList.Count; ++i)
738 {
740
741 Desc = &ResourcesTranslated->List[0].PartialResourceList.PartialDescriptors[i];
742 switch (Desc->Type)
743 {
746 {
747 if (IsNEC_98 && (ResourcesTranslated->List[0].PartialResourceList.Count >= 12))
748 {
749 if ((Desc->u.Port.Start.QuadPart == 0x640))
750 {
751 CommandPortDesc = Desc;
752 ChanData->ChanInfo |= CHANNEL_FLAG_CBUS;
753 }
754 else if ((Desc->u.Port.Start.QuadPart == 0x74C))
755 {
756 ControlPortDesc = Desc;
757 ChanData->ChanInfo |= CHANNEL_FLAG_CBUS;
758 }
759 }
760 else if (Desc->u.Port.Length == PCIIDE_LEGACY_CONTROL_IO_RANGE_LENGTH)
761 {
762 if (!ControlPortDesc)
763 ControlPortDesc = Desc;
764 }
765 else if (Desc->u.Port.Length == PCIIDE_LEGACY_COMMAND_IO_RANGE_LENGTH)
766 {
767 if (!CommandPortDesc)
768 CommandPortDesc = Desc;
769 }
770
771 break;
772 }
773
775 {
776 if (!InterruptDesc)
777 InterruptDesc = Desc;
778 break;
779 }
780
781 default:
782 break;
783 }
784 }
785
786 if (!CommandPortDesc || !ControlPortDesc || !InterruptDesc)
788
789 if (CommandPortDesc->Type == CmResourceTypeMemory)
790 ChanData->ChanInfo |= CHANNEL_FLAG_MRES_TF;
791
792 if (ControlPortDesc->Type == CmResourceTypeMemory)
793 ChanData->ChanInfo |= CHANNEL_FLAG_MRES_CTRL;
794
795 RtlCopyMemory(&ChanData->InterruptDesc, InterruptDesc, sizeof(*InterruptDesc));
796
797#if defined(_M_IX86)
798 if (ChanData->ChanInfo & CHANNEL_FLAG_CBUS)
799 {
800 Spare = 2;
801 }
802 else
803#endif
804 {
805 Spare = 1;
806 }
808 (ULONG_PTR)CommandPortDesc->u.Port.Start.QuadPart,
809 (ULONG_PTR)ControlPortDesc->u.Port.Start.QuadPart,
810 Spare);
811
812 return STATUS_SUCCESS;
813}
814
815/*
816 * PCI IDE Notes:
817 *
818 * When the PCI IDE controller operates in compatibility mode,
819 * the pciidex driver assigns a list of boot resources to each IDE channel.
820 *
821 * _GTM, _STM _GTF
822 * PCI0-->IDE0---------------------------+-->CHN0---------------------------+-->DRV0
823 * IO: Start 0:FFA0, Len 10 | IO: Start 0:1F0, Len 8 |
824 * | IO: Start 0:3F6, Len 1 \-->DRV1
825 * | INT: Lev A Vec A Aff FFFFFFFF
826 * |
827 * \-->CHN1---------------------------+-->DRV0
828 * IO: Start 0:170, Len 8 |
829 * IO: Start 0:376, Len 1 \-->DRV1
830 * INT: Lvl F Vec F Aff FFFFFFFF
831 *
832 * In native-PCI mode, the PCI IDE controller acts as a true PCI device
833 * and no resources are assigned to the channel device object at all.
834 *
835 * _GTM, _STM _GTF
836 * PCI0-->IDE0---------------------------+-->CHN0---------------------------+-->DRV0
837 * IO: Start 0:FFC0, Len 8 | |
838 * IO: Start 0:FF8C, Len 4 | \-->DRV1
839 * IO: Start 0:FF80, Len 8 |
840 * IO: Start 0:FF88, Len 4 |
841 * IO: Start 0:FFA0, Len 10 \-->CHN1---------------------------+-->DRV0
842 * INT: Lvl B Vec B Aff FFFFFFFF |
843 * \-->DRV1
844 *
845 * Note that the NT architecture does not support switching only one IDE channel to native mode.
846 */
847CODE_SEG("PAGE")
850 _In_ PCHANNEL_DATA_PATA ChanData,
852{
853 PATA_CONTROLLER Controller = ChanData->Controller;
855
856 PAGED_CODE();
857
858 ASSERT(ChanData->Channel < 2);
859
860 if (Controller->Flags & CTRL_FLAG_NATIVE_PCI)
861 Status = PciIdeAssignNativeResources(Controller, ChanData);
862 else
864 if (!NT_SUCCESS(Status))
865 {
866 ERR("CH %lu: Failed to assign I/O resources 0x%lx\n", ChanData->Channel, Status);
867 return Status;
868 }
869
871
872 return STATUS_SUCCESS;
873}
874
875CODE_SEG("PAGE")
876VOID
878 _In_ PVOID ChannelContext)
879{
880 PCHANNEL_DATA_PATA ChanData = ChannelContext;
881
882 PAGED_CODE();
883
884 if (ChanData->InterruptObject)
885 {
887
888 IoDisconnectInterrupt(ChanData->InterruptObject);
889 ChanData->InterruptObject = NULL;
890 }
891
892 ChanData->Regs.Dma = NULL;
893
894 ChanData->ChanInfo &= ~(CHANNEL_FLAG_DRIVE0_DMA_CAPABLE |
896
898}
899
900CODE_SEG("PAGE")
903 _In_ PATA_CONTROLLER Controller,
905{
906 PAGED_CODE();
907
908 /* SFF-8038i compliant hardware */
909 if (Controller->Flags & CTRL_FLAG_NATIVE_PCI)
910 {
911 /*
912 * If any native PCI IDE channel is enabled,
913 * its PCI I/O resources should be allocated as well:
914 *
915 * [BAR 0] I/O ports at FFC0 [size=8] Channel 0 task file registers
916 * [BAR 1] I/O ports at FF8C [size=4] Channel 0 device control
917 * [BAR 2] I/O ports at FF80 [size=8] Channel 1 task file registers
918 * [BAR 3] I/O ports at FF88 [size=4] Channel 1 device control
919 * [BAR 4] I/O ports at FFA0 [size=16] Bus Mastering registers
920 * [BAR 5] Memory at FE780000 Aux registers
921 */
922 if (!(Controller->Flags & CTRL_FLAG_MANUAL_RES))
923 {
924 const ULONG BarIndex = Channel * 2;
925
926 ASSERT(Channel < 2);
927
928 /* Check task file registers */
929 if (!(Controller->AccessRange[BarIndex].Flags & RANGE_IS_VALID))
930 return ChannelDisabled;
931
932 /* Check device control */
933 if (!(Controller->AccessRange[BarIndex + 1].Flags & RANGE_IS_VALID))
934 return ChannelDisabled;
935 }
936 }
937
938 if (Controller->ChannelEnableBits)
939 {
940 if (Controller->Flags & CTRL_FLAG_USE_TEST_FUNCTION)
941 {
942 /* Device-specific test */
943 return Controller->ChannelEnabledTest(Controller, Channel);
944 }
945 else
946 {
947 const ATA_PCI_ENABLE_BITS* EnableBits = &Controller->ChannelEnableBits[Channel];
948 UCHAR RegisterValue;
949
950 /* Test PCI bits */
951 RegisterValue = PciRead8(Controller, EnableBits->Register);
952 if ((RegisterValue & EnableBits->Mask) == EnableBits->ValueEnabled)
953 return ChannelEnabled;
954 else
955 return ChannelDisabled;
956 }
957 }
958
959 /* This channel is always enabled */
960 return ChannelStateUnknown;
961}
962
963static
964VOID
966 _In_ PVOID ChannelContext,
968{
969 PCHANNEL_DATA_PATA ChanData = ChannelContext;
971
972 INFO("CH %lu: %sable interrupts\n", ChanData->Channel, Enable ? "En" : "Dis");
973
975 if (Enable)
977 else
979
980#if defined(_M_IX86)
981 if (ChanData->ChanInfo & CHANNEL_FLAG_CBUS)
982 {
984 ATA_WRITE(ChanData->Regs.Control, Control, ChanData, MRES_CTRL);
985
986 /* Clear interrupts */
987 if (ChanData->CheckInterrupt)
988 ChanData->CheckInterrupt(ChanData);
989 ChanData->ReadStatus(ChanData);
990
992 ChanData->LastAtaBankId = 0xFF;
993 }
994#endif
995 ATA_WRITE(ChanData->Regs.Control, Control, ChanData, MRES_CTRL);
996
997 /* Clear interrupts */
998 if (ChanData->CheckInterrupt)
999 ChanData->CheckInterrupt(ChanData);
1000 ChanData->ReadStatus(ChanData);
1001
1002 if (ChanData->Regs.Dma != NULL)
1003 {
1004 UCHAR Status = ATA_READ(ChanData->Regs.Dma + PCIIDE_DMA_STATUS, ChanData, MRES_DMA);
1005
1006 ATA_WRITE(ChanData->Regs.Dma + PCIIDE_DMA_STATUS, Status, ChanData, MRES_DMA);
1007 }
1008}
1009
1010CODE_SEG("PAGE")
1013 _In_ PVOID ChannelContext)
1014{
1015 PCHANNEL_DATA_PATA ChanData = ChannelContext;
1016 PATA_CONTROLLER Controller = ChanData->Controller;
1017 PCM_PARTIAL_RESOURCE_DESCRIPTOR InterruptDesc;
1018 PKSERVICE_ROUTINE IsrHandler;
1020
1021 PAGED_CODE();
1022
1023 if (Controller->Flags & CTRL_FLAG_NATIVE_PCI)
1024 InterruptDesc = &Controller->InterruptDesc;
1025 else
1026 InterruptDesc = &ChanData->InterruptDesc;
1027 ASSERT(InterruptDesc);
1028
1029 if (ChanData->Regs.Dma != NULL)
1030 IsrHandler = PciIdeChannelIsr;
1031 else
1032 IsrHandler = PataChannelIsr;
1033 Status = IoConnectInterrupt(&ChanData->InterruptObject,
1034 IsrHandler,
1035 ChanData,
1036 NULL,
1037 InterruptDesc->u.Interrupt.Vector,
1038 InterruptDesc->u.Interrupt.Level,
1039 InterruptDesc->u.Interrupt.Level,
1040 (InterruptDesc->Flags & CM_RESOURCE_INTERRUPT_LATCHED)
1042 (InterruptDesc->ShareDisposition == CmResourceShareShared),
1043 InterruptDesc->u.Interrupt.Affinity,
1044 FALSE);
1045 if (!NT_SUCCESS(Status))
1046 {
1047 ERR("Could not connect to interrupt %lu, status 0x%lx\n",
1048 InterruptDesc->u.Interrupt.Vector, Status);
1049 return Status;
1050 }
1051
1052 return STATUS_SUCCESS;
1053}
1054
1055CODE_SEG("PAGE")
1058 _In_ PVOID ChannelContext,
1059 _In_ BOOLEAN Attach)
1060{
1061 PCHANNEL_DATA_PATA ChanData = ChannelContext;
1062
1063 PAGED_CODE();
1064
1065 AtaChanEnableInterruptsSync(ChanData, Attach);
1066
1067 return STATUS_SUCCESS;
1068}
1069
1070CODE_SEG("PAGE")
1073 _In_ PATA_CONTROLLER Controller,
1074 _In_ ULONG HwExtensionSize)
1075{
1076 PCHANNEL_DATA_PATA ChanData;
1077 ULONG i, Size;
1078
1079 PAGED_CODE();
1080 ASSERT(Controller->MaxChannels != 0);
1081
1082 Size = FIELD_OFFSET(CHANNEL_DATA_PATA, HwExt) + HwExtensionSize;
1083 ChanData = ExAllocatePoolZero(NonPagedPool, Size * Controller->MaxChannels, TAG_PCIIDEX);
1084 if (!ChanData)
1086
1087 Controller->ChanDataBlock = ChanData;
1088 Controller->ChannelBitmap = NUM_TO_BITMAP(Controller->MaxChannels);
1089
1090 for (i = 0; i < Controller->MaxChannels; ++i)
1091 {
1092 Controller->Channels[i] = ChanData;
1093
1094 ChanData->Channel = i;
1095 ChanData->Controller = Controller;
1096
1097 /* Set default values */
1098 ChanData->ChanInfo = CHANNEL_FLAG_IO32;
1099 ChanData->AllocateMemory = PciIdeAllocateMemory;
1100 ChanData->FreeMemory = PciIdeFreeMemory;
1101 ChanData->EnableInterrupts = PataEnableInterrupts;
1102 ChanData->PreparePrdTable = PciIdePreparePrdTable;
1103 ChanData->PrepareIo = PataPrepareIo;
1104 ChanData->StartIo = PataStartIo;
1105 ChanData->LoadTaskFile = PataLoadTaskFile;
1106 ChanData->SaveTaskFile = PataSaveTaskFile;
1107 ChanData->ReadStatus = PataReadStatus;
1108 ChanData->SetTransferMode = PciIdeGenericSetTransferMode;
1109 ChanData->TransferModeSupported = PIO_ALL | SWDMA_ALL | MWDMA_ALL | UDMA_ALL;
1110
1112
1113 ChanData = (PVOID)((ULONG_PTR)ChanData + Size);
1114 }
1115
1116 return STATUS_SUCCESS;
1117}
1118
1119CODE_SEG("PAGE")
1122 _Inout_ PATA_CONTROLLER Controller)
1123{
1125 ULONG i;
1126
1127 PAGED_CODE();
1128
1129 Controller->MaxChannels = MAX_IDE_CHANNEL;
1130
1131 /* Match the controller through the PCI ID */
1132 switch (Controller->Pci.VendorID)
1133 {
1134 case PCI_VEN_ATI:
1135 Status = AtiGetControllerProperties(Controller);
1136 break;
1137 case PCI_VEN_AMD:
1138 case PCI_VEN_NVIDIA:
1139 Status = AmdGetControllerProperties(Controller);
1140 break;
1141 case PCI_VEN_CMD:
1142 Status = CmdGetControllerProperties(Controller);
1143 if (Status == STATUS_NO_MATCH)
1145 break;
1146 case PCI_VEN_INTEL:
1148 break;
1149 case PCI_VEN_PC_TECH:
1151 break;
1154 if (Status == STATUS_NO_MATCH)
1156 break;
1157 case PCI_VEN_TOSHIBA:
1159 break;
1160 case PCI_VEN_VIA:
1161 Status = ViaGetControllerProperties(Controller);
1162 break;
1163
1164 default:
1166 break;
1167 }
1168
1169 /* Try to use the generic PCI IDE minidriver */
1170 if (Status == STATUS_NO_MATCH)
1171 {
1172 if ((Controller->Pci.BaseClass != PCI_CLASS_MASS_STORAGE_CTLR) ||
1173 ((Controller->Pci.SubClass != PCI_SUBCLASS_MSC_IDE_CTLR) &&
1174 (Controller->Pci.SubClass != PCI_SUBCLASS_MSC_RAID_CTLR)))
1175 {
1176 ERR("Unsupported controller\n");
1177 return Status;
1178 }
1179
1180 WARN("%04X:%04X.%02X: Using generic PCI IDE minidriver\n",
1181 Controller->Pci.VendorID,
1182 Controller->Pci.DeviceID,
1183 Controller->Pci.RevisionID);
1184
1185 Status = PciIdeCreateChannelData(Controller, 0);
1186 if (!NT_SUCCESS(Status))
1187 return Status;
1188
1189 /* Disable 32-bit I/O for unknown controllers */
1190 for (i = 0; i < Controller->MaxChannels; ++i)
1191 {
1192 PCHANNEL_DATA_PATA ChanData = Controller->Channels[i];
1193
1194 ChanData->ChanInfo &= ~CHANNEL_FLAG_IO32;
1195 }
1196 }
1197
1198 if (!NT_SUCCESS(Status))
1199 return Status;
1200
1201 /*
1202 * Check for a legacy PCI IDE device.
1203 * NOTE: NT architecture does not support switching only one IDE channel to native mode.
1204 */
1205 if ((Controller->Pci.BaseClass == PCI_CLASS_MASS_STORAGE_CTLR) &&
1206 (Controller->Pci.SubClass == PCI_SUBCLASS_MSC_IDE_CTLR))
1207 {
1208 if (!(Controller->Pci.ProgIf & PCIIDE_PROGIF_PRIMARY_CHANNEL_NATIVE_MODE) ||
1209 !(Controller->Pci.ProgIf & PCIIDE_PROGIF_SECONDARY_CHANNEL_NATIVE_MODE))
1210 {
1211 Controller->Flags &= ~CTRL_FLAG_NATIVE_PCI;
1212 }
1213 }
1214
1215 if (Controller->Flags & CTRL_FLAG_NATIVE_PCI)
1216 {
1217 if (Controller->InterruptDesc.Type != CmResourceTypeInterrupt)
1218 {
1219 ERR("No interrupt resource\n");
1221 }
1222 }
1223
1224 if (!PciIdeControllerInitDma(Controller))
1225 {
1226 for (i = 0; i < Controller->MaxChannels; ++i)
1227 {
1228 PCHANNEL_DATA_PATA ChanData = Controller->Channels[i];
1229
1230 ChanData->TransferModeSupported &= PIO_ALL;
1231 }
1232 }
1233
1234 if (Controller->Flags & CTRL_FLAG_IS_SIMPLEX)
1235 {
1236 WARN("Sync access for hardware is required\n");
1237
1238 Controller->HwSyncObject = IoCreateController(0);
1239 if (!Controller->HwSyncObject)
1241 }
1242
1243 return STATUS_SUCCESS;
1244}
#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:98
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:147
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
#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:25
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
_In_ ULONG Mode
Definition: hubbusif.h:303
#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:128
#define PCIIDE_PROGIF_SECONDARY_CHANNEL_NATIVE_MODE
Definition: pata.h:97
#define PCI_VEN_INTEL
Definition: pata.h:19
#define PCI_VEN_ATI
Definition: pata.h:10
#define PCI_VEN_TOSHIBA
Definition: pata.h:17
#define PCIIDE_DMA_STATUS
Definition: pata.h:107
#define SHARED_DATA_TIMINGS
Definition: pata.h:231
#define PCIIDE_DMA_STATUS_RESERVED2
Definition: pata.h:129
#define PCIIDE_DMA_STATUS_DRIVE1_DMA_CAPABLE
Definition: pata.h:131
#define SHARED_CMD_TIMINGS
Definition: pata.h:230
#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:77
#define PCIIDE_PROGIF_DMA_CAPABLE
Definition: pata.h:99
#define PCIIDE_DMA_SECONDARY_CHANNEL_OFFSET
Definition: pata.h:89
#define PCIIDE_DMA_IO_BAR
Definition: pata.h:85
#define PCIIDE_COMMAND_IO_RANGE_LENGTH
Definition: pata.h:82
#define PCI_VEN_VIA
Definition: pata.h:15
#define PCI_VEN_PC_TECH
Definition: pata.h:13
#define PCIIDE_PROGIF_PRIMARY_CHANNEL_NATIVE_MODE
Definition: pata.h:95
#define PC98_ATA_BANK
Definition: pata.h:28
#define PCIIDE_LEGACY_COMMAND_IO_RANGE_LENGTH
Definition: pata.h:72
#define PCIIDE_LEGACY_CONTROL_IO_RANGE_LENGTH
Definition: pata.h:73
#define PCIIDE_CONTROL_IO_RANGE_LENGTH
Definition: pata.h:83
#define PCIIDE_DMA_STATUS_SIMPLEX
Definition: pata.h:132
#define PCIIDE_DMA_IO_RANGE_LENGTH
Definition: pata.h:86
#define PCIIDE_CONTROL_IO_BAR_OFFSET
Definition: pata.h:84
#define PCIIDE_DMA_STATUS_DRIVE0_DMA_CAPABLE
Definition: pata.h:130
#define SHARED_ADDR_TIMINGS
Definition: pata.h:232
#define PCIIDE_LEGACY_PRIMARY_COMMAND_BASE
Definition: pata.h:74
#define PCI_VEN_SERVERWORKS
Definition: pata.h:16
USHORT ATATIM
Definition: pata.h:217
static VOID PciIdeGenericSetTransferMode(_In_ PATA_CONTROLLER Controller, _In_ ULONG Channel, _In_reads_(MAX_IDE_DEVICE) PCHANNEL_DEVICE_CONFIG *DeviceList)
Definition: pata_generic.c:416
static VOID PataClaimLegacyAddressRanges(_In_ PCHANNEL_DATA_PATA ChanData)
Definition: pata_generic.c:452
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:849
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:565
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:902
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:689
NTSTATUS PciIdeConnectInterrupt(_In_ PVOID ChannelContext)
VOID PciIdeFreeResources(_In_ PVOID ChannelContext)
Definition: pata_generic.c:877
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:511
static VOID PataReleaseLegacyAddressRanges(_In_ PCHANNEL_DATA_PATA ChanData)
Definition: pata_generic.c:433
static VOID PciIdeFreeMemory(_In_ PVOID ChannelContext)
Definition: pata_generic.c:485
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:723
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:965
static BOOLEAN PciIdeIsDmaStatusValid(_In_ UCHAR DmaStatus)
Definition: pata_generic.c:544
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:663
#define WRITE_PORT_UCHAR(p, d)
Definition: pc98vid.h:21
CHANNEL_PREPARE_IO PataPrepareIo
Definition: pciidex.h:700
#define CTRL_FLAG_NATIVE_PCI
Definition: pciidex.h:223
FORCEINLINE UCHAR PciRead8(_In_ PATA_CONTROLLER Controller, _In_ ULONG ConfigDataOffset)
Definition: pciidex.h:847
#define CHANNEL_FLAG_MRES_TF
Definition: pciidex.h:280
CHANNEL_LOAD_TASK_FILE PataLoadTaskFile
Definition: pciidex.h:705
#define CHANNEL_FLAG_MRES_DMA
Definition: pciidex.h:281
#define CHANNEL_FLAG_MRES_CTRL
Definition: pciidex.h:282
KDEFERRED_ROUTINE PataPollingTimerDpc
Definition: pciidex.h:708
CHANNEL_START_IO PataStartIo
Definition: pciidex.h:701
#define RANGE_IS_MAPPED
Definition: pciidex.h:192
#define CTRL_FLAG_USE_TEST_FUNCTION
Definition: pciidex.h:226
_In_ ULONG Channel
Definition: pciidex.h:74
#define CHANNEL_FLAG_IO32
Definition: pciidex.h:260
#define CHANNEL_FLAG_DRIVE0_DMA_CAPABLE
Definition: pciidex.h:261
#define CHANNEL_FLAG_PRIMARY_ADDRESS_CLAIMED
Definition: pciidex.h:267
#define IS_PRIMARY_CHANNEL(PdoExtension)
Definition: pciidex.h:43
KSERVICE_ROUTINE PciIdeChannelIsr
Definition: pciidex.h:703
CHANNEL_SAVE_TASK_FILE PataSaveTaskFile
Definition: pciidex.h:706
#define CTRL_FLAG_MANUAL_RES
Definition: pciidex.h:229
CONTROLLER_ATTACH_CHANNEL_EX PciIdeAttachChannel
Definition: pciidex.h:636
KSERVICE_ROUTINE PataChannelIsr
Definition: pciidex.h:702
#define CHANNEL_FLAG_SECONDARY_ADDRESS_CLAIMED
Definition: pciidex.h:268
#define CHANNEL_FLAG_CBUS
Definition: pciidex.h:283
#define CHANNEL_FLAG_DRIVE1_DMA_CAPABLE
Definition: pciidex.h:262
#define CTRL_FLAG_DMA_INTERRUPT
Definition: pciidex.h:230
CHANNEL_SET_MODE_EX SataSetTransferMode
Definition: pciidex.h:633
CHANNEL_CHECK_INTERRUPT PciIdeCheckInterrupt
Definition: pciidex.h:704
CHANNEL_READ_STATUS PataReadStatus
Definition: pciidex.h:707
CHANNEL_PREPARE_PRD_TABLE PciIdePreparePrdTable
Definition: pciidex.h:699
#define CHANNEL_FLAG_HAS_ACPI_GTM
Definition: pciidex.h:275
#define TAG_PCIIDEX
Definition: pciidex.h:32
#define RANGE_IS_VALID
Definition: pciidex.h:190
#define CTRL_FLAG_IS_SIMPLEX
Definition: pciidex.h:224
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:249
CM_PARTIAL_RESOURCE_DESCRIPTOR InterruptDesc
Definition: pciidex.h:171
ATATIM CmdRecovery
Definition: pata.h:224
ATATIM CmdActive
Definition: pata.h:223
ATATIM DataRecovery
Definition: pata.h:227
ATATIM AddressSetup
Definition: pata.h:221
ATATIM DataActive
Definition: pata.h:226
PCHANNEL_CHECK_INTERRUPT CheckInterrupt
Definition: pciidex.h:303
PCHANNEL_READ_STATUS ReadStatus
Definition: pciidex.h:299
ULONG PrdTablePhysicalAddress
Definition: pciidex.h:301
KDPC PollingTimerDpc
Definition: pciidex.h:312
PPCIIDE_PRD_TABLE_ENTRY PrdTable
Definition: pciidex.h:300
PCHANNEL_SAVE_TASK_FILE SaveTaskFile
Definition: pciidex.h:298
PCHANNEL_LOAD_TASK_FILE LoadTaskFile
Definition: pciidex.h:297
IDE_REGISTERS Regs
Definition: pciidex.h:302
struct _CM_PARTIAL_RESOURCE_DESCRIPTOR::@384::@387 Interrupt
union _CM_PARTIAL_RESOURCE_DESCRIPTOR::@384 u
struct _CM_PARTIAL_RESOURCE_DESCRIPTOR::@384::@386 Port
BOOLEAN AtDiskPrimaryAddressClaimed
Definition: iotypes.h:4485
BOOLEAN AtDiskSecondaryAddressClaimed
Definition: iotypes.h:4486
PALLOCATE_COMMON_BUFFER AllocateCommonBuffer
Definition: iotypes.h:2637
PFREE_COMMON_BUFFER FreeCommonBuffer
Definition: iotypes.h:2638
struct _IDE_ACPI_TIMING_MODE_BLOCK::@1699 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
#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
_Must_inspect_result_ _In_ WDFDEVICE Device
Definition: wdfchildlist.h:474
_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
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
@ CmResourceShareShared
Definition: cmtypes.h:243
#define PCI_ENABLE_BUS_MASTER
Definition: iotypes.h:3620
#define PCI_CLASS_MASS_STORAGE_CTLR
Definition: iotypes.h:4106
#define PCI_SUBCLASS_MSC_IDE_CTLR
Definition: iotypes.h:4131
#define PCI_SUBCLASS_MSC_RAID_CTLR
Definition: iotypes.h:4134
KSERVICE_ROUTINE * PKSERVICE_ROUTINE
Definition: ketypes.h:564
@ MaximumMode
Definition: ketypes.h:13
#define IsNEC_98
Definition: ketypes.h:963
#define NT_VERIFY(exp)
Definition: rtlfuncs.h:3304