ReactOS 0.4.16-dev-2633-g8dc9e50
via.c
Go to the documentation of this file.
1/*
2 * PROJECT: ReactOS ATA Bus Driver
3 * LICENSE: BSD-2-Clause (https://spdx.org/licenses/BSD-2-Clause)
4 * PURPOSE: VIA ATA controller minidriver
5 * COPYRIGHT: Copyright 2026 Dmitry Borisov <di.sean@protonmail.com>
6 */
7
8/*
9 * Some code taken from the NetBSD viaide driver
10 * Copyright (c) 1999, 2000, 2001 Manuel Bouyer
11 */
12
13/* INCLUDES *******************************************************************/
14
15#include "pciidex.h"
16
17/* GLOBALS ********************************************************************/
18
19#define PCI_DEV_VT82C576M_IDE 0x1571
20#define PCI_DEV_VT82C586A_IDE 0x0571
21#define PCI_DEV_VT6410_IDE_RAID 0x3164
22#define PCI_DEV_VT6415_IDE 0x0415
23#define PCI_DEV_VT6420_IDE 0x4149
24#define PCI_DEV_VT6421A_RAID 0x3249
25#define PCI_DEV_CX700M2_IDE_SATA 0x5324
26#define PCI_DEV_CX700M2_IDE_SATA_RAID 0x0581
27#define PCI_DEV_VX855_IDE 0xC409
28
29#define PCI_DEV_VT8237_SATA 0x3149
30#define PCI_DEV_VT8237A_SATA 0x0591
31#define PCI_DEV_VT8237A_SATA_2 0x5337
32#define PCI_DEV_VT8237S_SATA 0x5372
33#define PCI_DEV_VT8237S_SATA_RAID 0x7372
34#define PCI_DEV_VT8251_SATA_AHCI 0x3349
35#define PCI_DEV_VT8251_SATA_2 0x5287
36#define PCI_DEV_VT8261_SATA 0x9000
37#define PCI_DEV_VT8261_SATA_RAID 0x9040
38#define PCI_DEV_VX900_SATA 0x9001
39#define PCI_DEV_VX900_SATA_RAID 0x9041
40
41#define PCI_DEV_BRIDGE_VT82C586 0x0586
42#define PCI_DEV_BRIDGE_VT82C596A 0x0596
43#define PCI_DEV_BRIDGE_VT82C686A 0x0686
44#define PCI_DEV_BRIDGE_VT8231 0x8231
45#define PCI_DEV_BRIDGE_VT8233 0x3074
46#define PCI_DEV_BRIDGE_VT8233A 0x3147
47#define PCI_DEV_BRIDGE_VT8233C 0x3109
48#define PCI_DEV_BRIDGE_VT8235 0x3177
49#define PCI_DEV_BRIDGE_VT8237 0x3227
50#define PCI_DEV_BRIDGE_VT8237A 0x3337
51#define PCI_DEV_BRIDGE_VT8237S 0x3372
52#define PCI_DEV_BRIDGE_VT8251 0x3287
53#define PCI_DEV_BRIDGE_VT8261 0x3402
54
55#define HW_FLAGS_TYPE_MASK 0x000F
56#define HW_FLAGS_CHECK_BRIDGE 0x0010
57#define HW_FLAGS_HAS_UDMA_CLOCK 0x0020
58#define HW_FLAGS_SINGLE_CHAN 0x0040
59#define HW_FLAGS_SINGLE_PORT 0x0080
60#define HW_FLAGS_PCI_SCR 0x0100
61
62#define TYPE_33 0
63#define TYPE_66 1
64#define TYPE_100 2
65#define TYPE_133 3
66#define TYPE_MWDMA 4
67#define TYPE_SATA 5
68
69#define GET_TYPE(Flags) ((Flags) & HW_FLAGS_TYPE_MASK)
70
71#define VIA_PCI_CLOCK 30000
72
73#define VIA_REG_ENABLE_CTRL 0x40
74#define VIA_REG_DRIVE_TIMING 0x48
75#define VIA_REG_PORT_TIMING(Channel) (0x4F - (Channel))
76#define VIA_REG_ADDRESS_SETUP 0x4C
77#define VIA_REG_UDMA_CTRL 0x50
78#define VIA_REG_SSTATUS 0xA0
79#define VIA_REG_SCONTROL 0xA4
80#define VIA_REG_SERROR 0xA8
81#define VIA_REG_SERROR_VT8237 0xB0
82
83#define VIA_UDMA_CLOCK_UDMA66 0x08
84#define VIA_UDMA_CABLE_BITS 0x10
85#define VIA_UDMA_CLEAR_MASK 0xEF // Save the cable bits
86
87#define VIA_UDMA_CLOCK_ENABLED(Reg32, Channel) \
88 (((Reg32) & (0x00080000 >> ((Channel) * 16))) != 0)
89
90#define VIA_UDMA_CABLE_PRESENT(Reg32, Channel) \
91 (((Reg32) & (0x10100000 >> ((Channel) * 16))) != 0)
92
93#define VIA_SINGLE_CHAN_UDMA_CABLE_PRESENT(Controller) \
94 ((PciRead16(Controller, 0x50) & 0x1010) != 0)
95
96/* Note that the cable bits are inverted */
97#define VT6421A_UDMA_CABLE_PRESENT(Controller) \
98 ((PciRead16(Controller, 0xB2) & 0x1010) == 0)
99
100#define VIA_REG_SATA_PORT_MAP 0x49
101
102#define VT6421A_REG_SATA_CTRL 0x52 // Also for VT8237
103#define VT6421A_REG_TIMING_CTRL(Drive) (0xAB - (Drive))
104#define VT6421A_REG_UDMA_CTRL(Drive) (0xB3 - (Drive))
105
106#define VT6421A_UDMA_SLOW 0x0F
107#define VT6421A_FIFO_WATERMARK_64DW 0x04
108
110static const struct
111{
115{
134
135static const struct
136{
139} ViaUdmaTimings[] =
140{
141 // UDMA 0 1 2 3 4 5 6
142 { 0x03, { 0xE2, 0xE1, 0xE0 } }, // TYPE_33
143 { 0x03, { 0xE6, 0xE4, 0xE2, 0xE1, 0xE0 } }, // TYPE_66
144 { 0x07, { 0xEA, 0xE6, 0xE4, 0xE2, 0xE1, 0xE0 } }, // TYPE_100
145 { 0x07, { 0xEE, 0xE8, 0xE6, 0xE4, 0xE2, 0xE1, 0xE0 } }, // TYPE_133
147
150{
151 { 0x40, 0x02, 0x02 },
152 { 0x40, 0x01, 0x01 },
153};
154
157{
158 { 0x40, 0x02, 0x02 },
159 { 0xC0, 0x01, 0x01 },
160};
161
162/* FUNCTIONS ******************************************************************/
163
164VOID
166 _Inout_ PATA_TIMING Timing)
167{
168 Timing->AddressSetup = CLAMP_TIMING(Timing->AddressSetup, 1, 4) - 1;
169 Timing->CmdRecovery = CLAMP_TIMING(Timing->CmdRecovery, 1, 16) - 1;
170 Timing->CmdActive = CLAMP_TIMING(Timing->CmdActive, 1, 16) - 1;
171 Timing->DataRecovery = CLAMP_TIMING(Timing->DataRecovery, 1, 16) - 1;
172 Timing->DataActive = CLAMP_TIMING(Timing->DataActive, 1, 16) - 1;
173}
174
175static
176VOID
178 _In_ PATA_CONTROLLER Controller,
181{
182 PCHANNEL_DATA_PATA ChanData = Controller->Channels[Channel];
183 ATA_TIMING DeviceTimings[MAX_IDE_DEVICE];
184 ULONG i;
185 ULONG DriveTimReg, UdmaTimReg;
186 UCHAR PortTimReg;
187
189
190 INFO("CH %lu: Config (before)\n"
191 "DRV %08lX\n"
192 "PORT %08lX\n"
193 "UDMA %08lX\n"
194 "CFG %08lX\n",
195 Channel,
196 PciRead32(Controller, 0x48),
197 PciRead32(Controller, 0x4C),
198 PciRead32(Controller, 0x50),
199 PciRead32(Controller, 0x40));
200
201 DriveTimReg = PciRead32(Controller, VIA_REG_DRIVE_TIMING);
202 PortTimReg = PciRead8(Controller, VIA_REG_PORT_TIMING(Channel));
203
204 if (GET_TYPE(ChanData->HwFlags) != TYPE_MWDMA)
205 UdmaTimReg = PciRead32(Controller, VIA_REG_UDMA_CTRL);
206
207 for (i = 0; i < MAX_IDE_DEVICE; ++i)
208 {
210 PATA_TIMING Timing = &DeviceTimings[i];
211 const ULONG DeviceIndex = (Channel << 1) + i; // 0 1 2 3
212 const ULONG Shift = (3 - DeviceIndex) << 3; // 24 16 8 0
213 ULONG Value;
214
215 /* UDMA timings */
216 if (GET_TYPE(ChanData->HwFlags) != TYPE_MWDMA)
217 {
218 if (Device && (Device->DmaMode >= UDMA_MODE(0)))
219 {
220 ULONG ModeIndex = Device->DmaMode - UDMA_MODE(0);
221 Value = ViaUdmaTimings[GET_TYPE(ChanData->HwFlags)].Data[ModeIndex];
222 }
223 else
224 {
225 Value = ViaUdmaTimings[GET_TYPE(ChanData->HwFlags)].DefaultValue;
226 }
227
228 /* Turn on the 66MHz UDMA clock */
229 if ((i != 0) && (GET_TYPE(ChanData->HwFlags) == TYPE_66))
231
232 UdmaTimReg &= ~(VIA_UDMA_CLEAR_MASK << Shift);
233 UdmaTimReg |= Value << Shift;
234 }
235
236 if (!Device)
237 continue;
238
239 /* PIO and DMA timings */
240 ViaClampTimings(Timing);
241
242 Value = (Timing->DataActive << 4) | Timing->DataRecovery;
243 DriveTimReg &= ~(0xFF << Shift);
244 DriveTimReg |= Value << Shift;
245
246 PortTimReg = (Timing->CmdActive << 4) | Timing->CmdRecovery;
247 }
248
249 PciWrite8(Controller, VIA_REG_PORT_TIMING(Channel), PortTimReg);
250 PciWrite32(Controller, VIA_REG_DRIVE_TIMING, DriveTimReg);
251
252 if (GET_TYPE(ChanData->HwFlags) != TYPE_MWDMA)
253 PciWrite32(Controller, VIA_REG_UDMA_CTRL, UdmaTimReg);
254
255 INFO("CH %lu: Config (after)\n"
256 "DRV %08lX\n"
257 "PORT %08lX\n"
258 "UDMA %08lX\n"
259 "CFG %08lX\n",
260 Channel,
261 PciRead32(Controller, 0x48),
262 PciRead32(Controller, 0x4C),
263 PciRead32(Controller, 0x50),
264 PciRead32(Controller, 0x40));
265}
266
267static
268VOID
270 _In_ PATA_CONTROLLER Controller,
273{
274 UCHAR SataControl = PciRead8(Controller, VT6421A_REG_SATA_CTRL);
275 ULONG i;
276
277 if (!(SataControl & VT6421A_FIFO_WATERMARK_64DW))
278 {
279 for (i = 0; i < MAX_IDE_DEVICE; ++i)
280 {
282
283 if (!Device)
284 continue;
285
286 /* Fix freezes with Western Digital drives. See CORE-5897 for more details */
287 if (_strnicmp(Device->FriendlyName, "WD", 2) == 0)
288 {
289 /* This will slow down I/O performance */
290 WARN("Enabling workaround for the '%s' drive\n", Device->FriendlyName);
291 SataControl |= VT6421A_FIFO_WATERMARK_64DW;
292 PciWrite8(Controller, VT6421A_REG_SATA_CTRL, SataControl);
293 break;
294 }
295 }
296 }
297
299}
300
301static
302VOID
304 _In_ PATA_CONTROLLER Controller,
307{
308 ATA_TIMING DeviceTimings[MAX_IDE_DEVICE];
309 ULONG i;
310
312
314
315 for (i = 0; i < MAX_IDE_DEVICE; ++i)
316 {
318 PATA_TIMING Timing = &DeviceTimings[i];
319 UCHAR UdmaTimReg;
320
321 /* UDMA timings */
322 UdmaTimReg = PciRead8(Controller, VT6421A_REG_UDMA_CTRL(i));
323 UdmaTimReg &= VIA_UDMA_CABLE_BITS;
324 if (Device && (Device->DmaMode >= UDMA_MODE(0)))
325 UdmaTimReg |= ViaUdmaTimings[TYPE_133].Data[Device->DmaMode - UDMA_MODE(0)];
326 else
327 UdmaTimReg |= VT6421A_UDMA_SLOW;
328 PciWrite8(Controller, VT6421A_REG_UDMA_CTRL(i), UdmaTimReg);
329
330 if (!Device)
331 continue;
332
333 ViaClampTimings(Timing);
334
335 /* PIO timings */
336 PciWrite8(Controller,
338 (Timing->DataActive << 4) | Timing->DataRecovery);
339 }
340}
341
342static
343ULONG
345 _In_ PATA_CONTROLLER Controller)
346{
347 if ((Controller->Pci.DeviceID == PCI_DEV_VT8237S_SATA_RAID))
349
350 return VIA_REG_SERROR;
351}
352
353static
356 _In_ PCHANNEL_DATA_PATA ChanData,
360{
361 PATA_CONTROLLER Controller = ChanData->Controller;
362 ULONG Value, Offset = 2 * ChanData->Channel + PortNumber;
363 UCHAR Reg;
364
365 switch (Register)
366 {
367 case ATA_SSTATUS:
368 {
369 Reg = PciRead8(Controller, VIA_REG_SSTATUS + Offset);
370
371 Value = Reg & 0x03;
372
373 if (Reg & 0x04)
375 else if (Reg & 0x08)
377 else
379
380 if (Reg & 0x10)
382 else
384 break;
385 }
386 case ATA_SERROR:
387 {
388 Value = PciRead32(Controller, ViaGetSerrOffset(Controller) + Offset * 4);
389 break;
390 }
391 case ATA_SCONTROL:
392 {
393 Value = 0;
394 Reg = PciRead8(Controller, VIA_REG_SCONTROL + Offset);
395 if (Reg & 0x01)
397 if (Reg & 0x02)
399 if (Reg & 0x04)
401 if (Reg & 0x08)
403 break;
404 }
405
406 default:
407 return FALSE;
408 }
409
410 *Result = Value;
411 return TRUE;
412}
413
414static
417 _In_ PCHANNEL_DATA_PATA ChanData,
421{
422 PATA_CONTROLLER Controller = ChanData->Controller;
423 ULONG Offset = 2 * ChanData->Channel + PortNumber;
424
425 switch (Register)
426 {
427 case ATA_SERROR:
428 {
429 PciWrite32(Controller, ViaGetSerrOffset(Controller) + Offset * 4, Value);
430 break;
431 }
432 case ATA_SCONTROL:
433 {
434 UCHAR Val = 0;
436 Val |= 0x01;
438 Val |= 0x02;
440 Val |= 0x04;
442 Val |= 0x08;
443
444 PciWrite8(Controller, VIA_REG_SCONTROL + Offset, Val);
445 break;
446 }
447
448 default:
449 return FALSE;
450 }
451
452 return TRUE;
453}
454
455static
458 _In_ PCHANNEL_DATA_PATA ChanData,
462{
464
466 return FALSE;
467
468 *Result = READ_PORT_ULONG((PULONG)(ChanData->Regs.Scr + (Register * 4)));
469 return TRUE;
470}
471
472static
475 _In_ PCHANNEL_DATA_PATA ChanData,
479{
481
483 return FALSE;
484
485 WRITE_PORT_ULONG((PULONG)(ChanData->Regs.Scr + (Register * 4)), Value);
486 return TRUE;
487}
488
489static
490CODE_SEG("PAGE")
494 _In_ ULONG PortIndex)
495{
496 PUCHAR CommandPortBase, ControlPortBase, DmaBase, ScrBase;
497
498 PAGED_CODE();
499
500 /*
501 * [BAR 0]: I/O ports at E150 [size=16] Channel 0
502 * [BAR 1]: I/O ports at E140 [size=16] Channel 1
503 * [BAR 2]: I/O ports at E130 [size=16] Channel 2
504 * [BAR 3]: I/O ports at E120 [size=16]
505 * [BAR 4]: I/O ports at E100 [size=32] BM DMA
506 * [BAR 5]: I/O ports at E000 [size=256] SATA PHY (minimum size = 128)
507 */
508
509 CommandPortBase = AtaCtrlPciMapBar(ChanData->Controller, PortIndex, 16);
510 if (!CommandPortBase)
512
513 DmaBase = AtaCtrlPciMapBar(ChanData->Controller, 4, 32);
514 if (!DmaBase)
516
517 ScrBase = AtaCtrlPciMapBar(ChanData->Controller, 5, 128);
518 if (!ScrBase)
520
521 ChanData->Regs.Dma = DmaBase + (PortIndex * 8);
522 ChanData->Regs.Scr = ScrBase + (PortIndex * 64);
523
524 ControlPortBase = CommandPortBase + PCIIDE_COMMAND_IO_RANGE_LENGTH;
525
527 (ULONG_PTR)CommandPortBase,
528 (ULONG_PTR)ControlPortBase + PCIIDE_CONTROL_IO_BAR_OFFSET,
529 1);
530 return STATUS_SUCCESS;
531}
532
533static
534CODE_SEG("PAGE")
537 _Inout_ PATA_CONTROLLER Controller)
538{
540 ULONG i;
541
542 PAGED_CODE();
543
544 /*
545 * Channel 0: SATA port #0 (M only)
546 * Channel 1: SATA port #1 (M only)
547 * Channel 2: PATA channel
548 */
549 Controller->MaxChannels = 3;
550 Controller->Flags |= CTRL_FLAG_MANUAL_RES;
551
552 Status = PciIdeCreateChannelData(Controller, 0);
553 if (!NT_SUCCESS(Status))
554 return Status;
555
556 for (i = 0; i < Controller->MaxChannels; ++i)
557 {
558 PCHANNEL_DATA_PATA ChanData = Controller->Channels[i];
559
560 if (i == 2)
561 {
562 /* No MWDMA support */
563 ChanData->TransferModeSupported = PIO_ALL | UDMA_ALL;
564 ChanData->SetTransferMode = Via6421SetTransferMode;
565
566 if (!VT6421A_UDMA_CABLE_PRESENT(Controller))
567 {
568 INFO("CH %lu: BIOS detected 40-conductor cable\n", ChanData->Channel);
569 ChanData->TransferModeSupported &= ~UDMA_80C_ALL;
570 }
571 }
572 else
573 {
574 ChanData->ChanInfo |= CHANNEL_FLAG_NO_SLAVE;
575 ChanData->SetTransferMode = ViaSataSetTransferMode;
576 ChanData->TransferModeSupported = SATA_ALL;
577 ChanData->ScrRead = ViaScrReadIoPort;
578 ChanData->ScrWrite = ViaScrWriteIoPort;
579 }
580
581 Status = Via6421ParseResources(ChanData, i);
582 if (!NT_SUCCESS(Status))
583 return Status;
584 }
585
586 return STATUS_SUCCESS;
587}
588
589static
590CODE_SEG("PAGE")
593 _Inout_ PATA_CONTROLLER Controller)
594{
596 ULONG i;
597
598 PAGED_CODE();
599
600 Status = PciIdeCreateChannelData(Controller, 0);
601 if (!NT_SUCCESS(Status))
602 return Status;
603
604 Controller->ChannelEnableBits = ViaCx700EnableBits;
605
606 /*
607 * Channel 0: 2 SATA ports (M/S emulation)
608 * Channel 1: PATA channel
609 */
610 for (i = 0; i < Controller->MaxChannels; ++i)
611 {
612 PCHANNEL_DATA_PATA ChanData = Controller->Channels[i];
613
614 if (i == 0)
615 {
616 ChanData->SetTransferMode = SataSetTransferMode;
617 ChanData->TransferModeSupported = SATA_ALL;
618 ChanData->ScrRead = ViaScrReadPci;
619 ChanData->ScrWrite = ViaScrWritePci;
620 }
621 else
622 {
623 ChanData->HwFlags |= TYPE_133;
624 ChanData->SetTransferMode = ViaSetTransferMode;
625 ChanData->TransferModeSupported = PIO_ALL | MWDMA_ALL | UDMA_ALL;
626
627 if (!VIA_SINGLE_CHAN_UDMA_CABLE_PRESENT(Controller))
628 {
629 INFO("CH %lu: BIOS detected 40-conductor cable\n", ChanData->Channel);
630 ChanData->TransferModeSupported &= ~UDMA_80C_ALL;
631 }
632 }
633 }
634
635 return STATUS_SUCCESS;
636}
637
638static
639VOID
641 _In_ PATA_CONTROLLER Controller)
642{
643 UCHAR Value;
644
645 /*
646 * Enable the primary and secondary IDE channels.
647 *
648 * The VT6410 can be either a controller soldered onto the motherboard
649 * or added on an external PCI card. These PCI cards usually come
650 * without an option ROM on their own and have these bits set to 0s by default.
651 */
652 Value = PciRead8(Controller, VIA_REG_ENABLE_CTRL);
653 Value |= 0x03;
654 PciWrite8(Controller, VIA_REG_ENABLE_CTRL, Value);
655}
656
657static
658CODE_SEG("PAGE")
665{
666 PULONG HwFlags = Context;
667 ULONG i;
669 static const struct
670 {
672 UCHAR MinimumRevisionID;
673 UCHAR Flags;
674 } ViaBridgeList[] =
675 {
692 };
693
696
697 PAGED_CODE();
698
699 if (PciConfig->VendorID != PCI_VEN_VIA)
700 return FALSE;
701
702 for (i = 0; i < RTL_NUMBER_OF(ViaBridgeList); ++i)
703 {
704 if ((PciConfig->DeviceID == ViaBridgeList[i].DeviceID) &&
705 (PciConfig->RevisionID >= ViaBridgeList[i].MinimumRevisionID))
706 {
707 INFO("Found %04X:%04X.%02X VIA bridge\n",
708 PciConfig->VendorID, PciConfig->DeviceID, PciConfig->RevisionID);
709
710 *HwFlags = ViaBridgeList[i].Flags;
711 return TRUE;
712 }
713 }
714
715 return FALSE;
716}
717
718static
719CODE_SEG("PAGE")
722 _Inout_ PATA_CONTROLLER Controller,
723 _In_ ULONG HwFlags)
724{
725 ULONG i, UdmaTimReg;
726
727 PAGED_CODE();
728
729 /*
730 * Look for a PCI-ISA bridge to see what features are available.
731 * Early VIA PATA controllers share the same PCI device ID
732 * but have very different capabilities.
733 */
734 if (HwFlags & HW_FLAGS_CHECK_BRIDGE)
735 {
737 {
738 ERR("Unable to find the VIA bridge\n");
739 ASSERT(FALSE);
740 return STATUS_NO_MATCH;
741 }
742 }
743
744 if (Controller->Pci.DeviceID == PCI_DEV_VT6410_IDE_RAID)
745 Controller->Start = Via6410ControllerStart;
746
747 /* The VT6415 has no channel enable bits */
748 if (Controller->Pci.DeviceID != PCI_DEV_VT6415_IDE)
749 Controller->ChannelEnableBits = ViaPataEnableBits;
750
751 if (GET_TYPE(HwFlags) != TYPE_MWDMA)
752 UdmaTimReg = PciRead32(Controller, VIA_REG_UDMA_CTRL);
753
754 for (i = 0; i < Controller->MaxChannels; ++i)
755 {
756 PCHANNEL_DATA_PATA ChanData = Controller->Channels[i];
757
758 ChanData->HwFlags = HwFlags;
759 ChanData->SetTransferMode = ViaSetTransferMode;
760
761 switch (GET_TYPE(ChanData->HwFlags))
762 {
763 case TYPE_MWDMA:
764 {
765 ChanData->TransferModeSupported = PIO_ALL | MWDMA_ALL;
766 break;
767 }
768 case TYPE_33:
769 {
770 ChanData->TransferModeSupported = PIO_ALL | MWDMA_ALL | UDMA_MODES(0, 2);
771 break;
772 }
773 case TYPE_66:
774 {
775 ChanData->TransferModeSupported = PIO_ALL | MWDMA_ALL | UDMA_MODES(0, 4);
776
777 /* Check to see if the BIOS has enabled the 66MHz UDMA clock for us */
778 if (!VIA_UDMA_CLOCK_ENABLED(UdmaTimReg, i))
779 {
780 /* It seems that the clock can also be disabled due to hardware errata */
781 INFO("CH %lu: BIOS detected 40-conductor cable "
782 "or this chip is ATA/33 capable\n", ChanData->Channel);
783 ChanData->TransferModeSupported &= ~UDMA_80C_ALL;
784
785 /* Use timing table based on a 33MHz UDMA clock */
786 ChanData->HwFlags &= ~HW_FLAGS_TYPE_MASK;
787 ChanData->HwFlags |= TYPE_33;
788 }
789 break;
790 }
791 case TYPE_100:
792 {
793 ChanData->TransferModeSupported = PIO_ALL | MWDMA_ALL | UDMA_MODES(0, 5);
794
795 if (!VIA_UDMA_CABLE_PRESENT(UdmaTimReg, i))
796 {
797 INFO("CH %lu: BIOS detected 40-conductor cable\n", ChanData->Channel);
798 ChanData->TransferModeSupported &= ~UDMA_80C_ALL;
799 }
800 break;
801 }
802 case TYPE_133:
803 {
804 ChanData->TransferModeSupported = PIO_ALL | MWDMA_ALL | UDMA_MODES(0, 6);
805
806 if (!VIA_UDMA_CABLE_PRESENT(UdmaTimReg, i))
807 {
808 INFO("CH %lu: BIOS detected 40-conductor cable\n", ChanData->Channel);
809 ChanData->TransferModeSupported &= ~UDMA_80C_ALL;
810 }
811 break;
812 }
813
814 default:
815 ASSERT(FALSE);
817 }
818 }
819
820 return STATUS_SUCCESS;
821}
822
823static
824CODE_SEG("PAGE")
827 _Inout_ PATA_CONTROLLER Controller,
828 _In_ ULONG HwFlags)
829{
830 ULONG i;
831
832 PAGED_CODE();
833
834 INFO("Port map: %02X\n", PciRead8(Controller, VIA_REG_SATA_PORT_MAP));
835
836 for (i = 0; i < Controller->MaxChannels; ++i)
837 {
838 PCHANNEL_DATA_PATA ChanData = Controller->Channels[i];
839
840 ChanData->HwFlags = HwFlags;
841 ChanData->TransferModeSupported = SATA_ALL;
842 ChanData->SetTransferMode = SataSetTransferMode;
843
844 if (HwFlags & HW_FLAGS_SINGLE_PORT)
845 ChanData->ChanInfo |= CHANNEL_FLAG_NO_SLAVE;
846
847 if (HwFlags & HW_FLAGS_PCI_SCR)
848 {
849 ChanData->ScrRead = ViaScrReadPci;
850 ChanData->ScrWrite = ViaScrWritePci;
851 }
852 }
853
854 return STATUS_SUCCESS;
855}
856
857CODE_SEG("PAGE")
860 _Inout_ PATA_CONTROLLER Controller)
861{
863 ULONG i, HwFlags;
864
865 PAGED_CODE();
866 ASSERT(Controller->Pci.VendorID == PCI_VEN_VIA);
867
868 if (Controller->Pci.DeviceID == PCI_DEV_VT6421A_RAID)
869 {
870 return Via6421GetControllerProperties(Controller);
871 }
872 else if ((Controller->Pci.DeviceID == PCI_DEV_CX700M2_IDE_SATA) ||
873 (Controller->Pci.DeviceID == PCI_DEV_CX700M2_IDE_SATA_RAID))
874 {
875 return ViaCx700GetControllerProperties(Controller);
876 }
877
878 for (i = 0; i < RTL_NUMBER_OF(ViaControllerList); ++i)
879 {
880 HwFlags = ViaControllerList[i].Flags;
881
882 if (Controller->Pci.DeviceID == ViaControllerList[i].DeviceID)
883 break;
884 }
886 return STATUS_NO_MATCH;
887
888 if (HwFlags & HW_FLAGS_SINGLE_CHAN)
889 Controller->MaxChannels = 1;
890
891 Status = PciIdeCreateChannelData(Controller, 0);
892 if (!NT_SUCCESS(Status))
893 return Status;
894
895 if (GET_TYPE(HwFlags) == TYPE_SATA)
896 return ViaSataGetControllerProperties(Controller, HwFlags);
897
898 return ViaPataGetControllerProperties(Controller, HwFlags);
899}
#define PAGED_CODE()
#define CODE_SEG(...)
#define RTL_NUMBER_OF(x)
Definition: RtlRegistry.c:12
unsigned char BOOLEAN
Definition: actypes.h:127
#define AHCI_PXCTL_DET_RESET
Definition: ahci.h:237
#define AHCI_PXSSTS_IPM_PARTIAL
Definition: ahci.h:225
#define AHCI_PXCTL_IPM_DISABLE_PARTIAL
Definition: ahci.h:248
#define AHCI_PXSSTS_IPM_SLUMBER
Definition: ahci.h:226
#define AHCI_PXSSTS_SPD_SATA1
Definition: ahci.h:219
enum _SATA_SCR_REGISTER SATA_SCR_REGISTER
#define AHCI_PXSSTS_SPD_SATA2
Definition: ahci.h:220
#define AHCI_PXCTL_IPM_DISABLE_SLUMBER
Definition: ahci.h:249
#define AHCI_PXCTL_DET_DISABLE_SATA
Definition: ahci.h:238
@ ATA_SCONTROL
Definition: ahci.h:55
@ ATA_SSTATUS
Definition: ahci.h:53
@ ATA_SERROR
Definition: ahci.h:54
#define AHCI_PXSSTS_IPM_ACTIVE
Definition: ahci.h:224
#define UDMA_ALL
Definition: ata_user.h:31
#define MWDMA_ALL
Definition: ata_user.h:27
#define PIO_ALL
Definition: ata_user.h:19
#define UDMA_MODE(n)
Definition: ata_user.h:39
LONG NTSTATUS
Definition: precomp.h:26
#define WARN(fmt,...)
Definition: precomp.h:61
#define ERR(fmt,...)
Definition: precomp.h:57
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
#define _strnicmp(_String1, _String2, _MaxCount)
Definition: compat.h:23
PDEVICE_LIST DeviceList
Definition: utils.c:27
#define INFO
Definition: debug.h:89
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
ULONG NTAPI READ_PORT_ULONG(IN PULONG Port)
Definition: portio.c:70
VOID NTAPI WRITE_PORT_ULONG(IN PULONG Port, IN ULONG Value)
Definition: portio.c:123
#define MAX_IDE_DEVICE
Definition: ide.h:32
#define MAX_IDE_CHANNEL
Definition: ide.h:30
#define ASSERT(a)
Definition: mode.c:44
#define _In_reads_(s)
Definition: no_sal2.h:168
#define _Inout_
Definition: no_sal2.h:162
#define _In_
Definition: no_sal2.h:158
#define UNREACHABLE
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:329
_In_ ULONG _In_ ULONG Offset
Definition: ntddpcm.h:101
#define STATUS_NO_MATCH
Definition: ntstatus.h:873
#define STATUS_DEVICE_CONFIGURATION_ERROR
Definition: ntstatus.h:713
#define SATA_ALL
Definition: pata.h:37
#define SHARED_CMD_TIMINGS
Definition: pata.h:230
#define UDMA_MODES(MinMode, MaxMode)
Definition: pata.h:49
#define PCIIDE_COMMAND_IO_RANGE_LENGTH
Definition: pata.h:82
#define PCI_VEN_VIA
Definition: pata.h:15
FORCEINLINE ATATIM CLAMP_TIMING(_In_ ATATIM Value, _In_ ATATIM Minimum, _In_ ATATIM Maximum)
Definition: pata.h:236
#define PCIIDE_CONTROL_IO_BAR_OFFSET
Definition: pata.h:84
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 PciIdeCreateChannelData(_In_ PATA_CONTROLLER Controller, _In_ ULONG HwExtensionSize)
VOID PciIdeInitTaskFileIoResources(_In_ PCHANNEL_DATA_PATA ChanData, _In_ ULONG_PTR CommandPortBase, _In_ ULONG_PTR ControlPortBase, _In_ ULONG CommandBlockSpare)
Definition: pata_generic.c:663
BOOLEAN PciFindDevice(_In_ __callback PATA_PCI_MATCH_FN MatchFunction, _In_ PVOID Context)
Definition: pciidex.c:13
FORCEINLINE UCHAR PciRead8(_In_ PATA_CONTROLLER Controller, _In_ ULONG ConfigDataOffset)
Definition: pciidex.h:847
_In_ ULONG _In_ PCI_SLOT_NUMBER PciSlot
Definition: pciidex.h:66
#define CHANNEL_FLAG_NO_SLAVE
Definition: pciidex.h:270
_In_ ULONG Channel
Definition: pciidex.h:74
#define PCIIDEX_PAGED_DATA
Definition: pciidex.h:50
FORCEINLINE VOID PciWrite8(_In_ PATA_CONTROLLER Controller, _In_ ULONG ConfigDataOffset, _In_ UCHAR Value)
Definition: pciidex.h:883
#define CTRL_FLAG_MANUAL_RES
Definition: pciidex.h:229
_In_ ULONG BusNumber
Definition: pciidex.h:65
FORCEINLINE VOID PciWrite32(_In_ PATA_CONTROLLER Controller, _In_ ULONG ConfigDataOffset, _In_ ULONG Value)
Definition: pciidex.h:903
CHANNEL_SET_MODE_EX SataSetTransferMode
Definition: pciidex.h:633
_In_ ULONG _In_ PCI_SLOT_NUMBER _In_ PPCI_COMMON_HEADER PciConfig
Definition: pciidex.h:67
FORCEINLINE ULONG PciRead32(_In_ PATA_CONTROLLER Controller, _In_ ULONG ConfigDataOffset)
Definition: pciidex.h:871
unsigned short USHORT
Definition: pedump.c:61
#define STATUS_SUCCESS
Definition: shellext.h:65
PVOID AtaCtrlPciMapBar(_In_ PATA_CONTROLLER Controller, _In_range_(0, PCI_TYPE0_ADDRESSES) ULONG Index, _In_ ULONG MinimumIoLength)
Definition: fdo.c:249
ULONG PortNumber
Definition: storport.c:18
_In_ PVOID Context
Definition: storport.h:2269
ATATIM CmdRecovery
Definition: pata.h:224
ATATIM CmdActive
Definition: pata.h:223
ATATIM DataRecovery
Definition: pata.h:227
ATATIM DataActive
Definition: pata.h:226
PCHANNEL_WRITE_SCR ScrWrite
Definition: pciidex.h:314
PCHANNEL_READ_SCR ScrRead
Definition: pciidex.h:313
uint32_t * PULONG
Definition: typedefs.h:59
unsigned char UCHAR
Definition: typedefs.h:53
uint32_t ULONG_PTR
Definition: typedefs.h:65
unsigned char * PUCHAR
Definition: typedefs.h:53
uint32_t ULONG
Definition: typedefs.h:59
#define PCI_DEV_BRIDGE_VT8233A
Definition: via.c:46
static NTSTATUS Via6421GetControllerProperties(_Inout_ PATA_CONTROLLER Controller)
Definition: via.c:536
#define PCI_DEV_VT82C576M_IDE
Definition: via.c:19
#define PCI_DEV_BRIDGE_VT82C596A
Definition: via.c:42
static BOOLEAN ViaQuerySouthBridgeInformation(_In_ PVOID Context, _In_ ULONG BusNumber, _In_ PCI_SLOT_NUMBER PciSlot, _In_ PPCI_COMMON_HEADER PciConfig)
Definition: via.c:660
#define VIA_REG_ENABLE_CTRL
Definition: via.c:73
#define VT6421A_REG_UDMA_CTRL(Drive)
Definition: via.c:104
#define VIA_UDMA_CLOCK_ENABLED(Reg32, Channel)
Definition: via.c:87
#define VIA_REG_DRIVE_TIMING
Definition: via.c:74
static VOID Via6421SetTransferMode(_In_ PATA_CONTROLLER Controller, _In_ ULONG Channel, _In_reads_(MAX_IDE_DEVICE) PCHANNEL_DEVICE_CONFIG *DeviceList)
Definition: via.c:303
#define PCI_DEV_VX900_SATA_RAID
Definition: via.c:39
static BOOLEAN ViaScrReadIoPort(_In_ PCHANNEL_DATA_PATA ChanData, _In_ SATA_SCR_REGISTER Register, _In_ ULONG PortNumber, _In_ PULONG Result)
Definition: via.c:457
#define PCI_DEV_VT8251_SATA_2
Definition: via.c:35
static VOID ViaSataSetTransferMode(_In_ PATA_CONTROLLER Controller, _In_ ULONG Channel, _In_reads_(MAX_IDE_DEVICE) PCHANNEL_DEVICE_CONFIG *DeviceList)
Definition: via.c:269
#define PCI_DEV_BRIDGE_VT8251
Definition: via.c:52
static PCIIDEX_PAGED_DATA const ATA_PCI_ENABLE_BITS ViaCx700EnableBits[MAX_IDE_CHANNEL]
Definition: via.c:156
static NTSTATUS ViaCx700GetControllerProperties(_Inout_ PATA_CONTROLLER Controller)
Definition: via.c:592
#define HW_FLAGS_HAS_UDMA_CLOCK
Definition: via.c:57
static BOOLEAN ViaScrWritePci(_In_ PCHANNEL_DATA_PATA ChanData, _In_ SATA_SCR_REGISTER Register, _In_ ULONG PortNumber, _In_ ULONG Value)
Definition: via.c:416
#define PCI_DEV_CX700M2_IDE_SATA_RAID
Definition: via.c:26
#define PCI_DEV_VT8237A_SATA_2
Definition: via.c:31
#define PCI_DEV_BRIDGE_VT8235
Definition: via.c:48
#define PCI_DEV_BRIDGE_VT8231
Definition: via.c:44
UCHAR DefaultValue
Definition: via.c:137
#define VIA_REG_PORT_TIMING(Channel)
Definition: via.c:75
#define PCI_DEV_VT8237S_SATA
Definition: via.c:32
static NTSTATUS Via6421ParseResources(_Inout_ PCHANNEL_DATA_PATA ChanData, _In_ ULONG PortIndex)
Definition: via.c:492
#define VT6421A_REG_TIMING_CTRL(Drive)
Definition: via.c:103
#define VIA_UDMA_CABLE_PRESENT(Reg32, Channel)
Definition: via.c:90
#define VIA_UDMA_CLOCK_UDMA66
Definition: via.c:83
#define VT6421A_FIFO_WATERMARK_64DW
Definition: via.c:107
VOID ViaClampTimings(_Inout_ PATA_TIMING Timing)
Definition: via.c:165
static const struct @1178 ViaUdmaTimings[]
#define PCI_DEV_BRIDGE_VT8237
Definition: via.c:49
#define VIA_SINGLE_CHAN_UDMA_CABLE_PRESENT(Controller)
Definition: via.c:93
#define VIA_UDMA_CABLE_BITS
Definition: via.c:84
#define PCI_DEV_BRIDGE_VT8261
Definition: via.c:53
#define PCI_DEV_VT6415_IDE
Definition: via.c:22
#define HW_FLAGS_CHECK_BRIDGE
Definition: via.c:56
#define PCI_DEV_BRIDGE_VT8233C
Definition: via.c:47
#define PCI_DEV_VT8237A_SATA
Definition: via.c:30
#define PCI_DEV_VT8251_SATA_AHCI
Definition: via.c:34
static ULONG ViaGetSerrOffset(_In_ PATA_CONTROLLER Controller)
Definition: via.c:344
#define VT6421A_UDMA_SLOW
Definition: via.c:106
static PCIIDEX_PAGED_DATA const ATA_PCI_ENABLE_BITS ViaPataEnableBits[MAX_IDE_CHANNEL]
Definition: via.c:149
#define PCI_DEV_VT6410_IDE_RAID
Definition: via.c:21
#define PCI_DEV_VX900_SATA
Definition: via.c:38
#define PCI_DEV_CX700M2_IDE_SATA
Definition: via.c:25
USHORT Flags
Definition: via.c:113
#define PCI_DEV_VT8261_SATA_RAID
Definition: via.c:37
static NTSTATUS ViaPataGetControllerProperties(_Inout_ PATA_CONTROLLER Controller, _In_ ULONG HwFlags)
Definition: via.c:721
#define PCI_DEV_VT8237S_SATA_RAID
Definition: via.c:33
NTSTATUS ViaGetControllerProperties(_Inout_ PATA_CONTROLLER Controller)
Definition: via.c:859
#define VIA_REG_SERROR_VT8237
Definition: via.c:81
static VOID Via6410ControllerStart(_In_ PATA_CONTROLLER Controller)
Definition: via.c:640
#define PCI_DEV_BRIDGE_VT82C686A
Definition: via.c:43
#define VT6421A_UDMA_CABLE_PRESENT(Controller)
Definition: via.c:97
#define VIA_REG_SCONTROL
Definition: via.c:79
#define GET_TYPE(Flags)
Definition: via.c:69
#define VIA_PCI_CLOCK
Definition: via.c:71
static BOOLEAN ViaScrWriteIoPort(_In_ PCHANNEL_DATA_PATA ChanData, _In_ SATA_SCR_REGISTER Register, _In_ ULONG PortNumber, _In_ ULONG Value)
Definition: via.c:474
#define PCI_DEV_VT6421A_RAID
Definition: via.c:24
static BOOLEAN ViaScrReadPci(_In_ PCHANNEL_DATA_PATA ChanData, _In_ SATA_SCR_REGISTER Register, _In_ ULONG PortNumber, _In_ PULONG Result)
Definition: via.c:355
#define PCI_DEV_BRIDGE_VT8237S
Definition: via.c:51
#define VT6421A_REG_SATA_CTRL
Definition: via.c:102
#define HW_FLAGS_SINGLE_CHAN
Definition: via.c:58
#define VIA_REG_UDMA_CTRL
Definition: via.c:77
#define PCI_DEV_VT8237_SATA
Definition: via.c:29
#define VIA_REG_SERROR
Definition: via.c:80
USHORT DeviceID
Definition: via.c:112
#define TYPE_33
Definition: via.c:62
#define PCI_DEV_VX855_IDE
Definition: via.c:27
static NTSTATUS ViaSataGetControllerProperties(_Inout_ PATA_CONTROLLER Controller, _In_ ULONG HwFlags)
Definition: via.c:826
#define TYPE_MWDMA
Definition: via.c:66
#define HW_FLAGS_SINGLE_PORT
Definition: via.c:59
#define HW_FLAGS_PCI_SCR
Definition: via.c:60
static PCIIDEX_PAGED_DATA const struct @1177 ViaControllerList[]
#define PCI_DEV_VT6420_IDE
Definition: via.c:23
#define PCI_DEV_BRIDGE_VT8233
Definition: via.c:45
#define VIA_REG_SATA_PORT_MAP
Definition: via.c:100
#define PCI_DEV_VT82C586A_IDE
Definition: via.c:20
#define TYPE_SATA
Definition: via.c:67
#define PCI_DEV_BRIDGE_VT82C586
Definition: via.c:41
static VOID ViaSetTransferMode(_In_ PATA_CONTROLLER Controller, _In_ ULONG Channel, _In_reads_(MAX_IDE_DEVICE) PCHANNEL_DEVICE_CONFIG *DeviceList)
Definition: via.c:177
#define PCI_DEV_VT8261_SATA
Definition: via.c:36
#define VIA_UDMA_CLEAR_MASK
Definition: via.c:85
#define VIA_REG_SSTATUS
Definition: via.c:78
#define TYPE_100
Definition: via.c:64
#define PCI_DEV_BRIDGE_VT8237A
Definition: via.c:50
#define TYPE_133
Definition: via.c:65
#define TYPE_66
Definition: via.c:63
_Must_inspect_result_ _In_ WDFDEVICE Device
Definition: wdfchildlist.h:474
_Must_inspect_result_ _In_ WDFKEY _In_ PCUNICODE_STRING _Out_opt_ PUSHORT _Inout_opt_ PUNICODE_STRING Value
Definition: wdfregistry.h:413
_At_(*)(_In_ PWSK_CLIENT Client, _In_opt_ PUNICODE_STRING NodeName, _In_opt_ PUNICODE_STRING ServiceName, _In_opt_ ULONG NameSpace, _In_opt_ GUID *Provider, _In_opt_ PADDRINFOEXW Hints, _Outptr_ PADDRINFOEXW *Result, _In_opt_ PEPROCESS OwningProcess, _In_opt_ PETHREAD OwningThread, _Inout_ PIRP Irp Result)(Mem)) NTSTATUS(WSKAPI *PFN_WSK_GET_ADDRESS_INFO
Definition: wsk.h:409
_In_ ULONG Shift
Definition: rtlfuncs.h:2698