ReactOS 0.4.16-dev-2633-g8dc9e50
sil680.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: Silicon Image 0680 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
14#define PCI_DEV_SIL0680 0x0680
15
16#define SIL_REG_XFER_MODE(Channel) (0x80 + ((Channel) << 2))
17#define SIL_REG_SYS_CFG 0x8A
18#define SIL_REG_CFG(Channel) (0xA0 + ((Channel) << 4))
19#define SIL_REG_STATUS(Channel) (0xA1 + ((Channel) << 4))
20#define SIL_REG_TF_TIM(Channel) (0xA2 + ((Channel) << 4))
21#define SIL_REG_PIO_TIMING(Channel, Drive) (0xA4 + ((Channel) << 4) + ((Drive) << 1))
22#define SIL_REG_DMA_TIMING(Channel, Drive) (0xA8 + ((Channel) << 4) + ((Drive) << 1))
23#define SIL_REG_UDMA_TIMING(Channel, Drive) (0xAC + ((Channel) << 4) + ((Drive) << 1))
24
25#define SIL_CFG_CABLE_80 0x00000001
26#define SIL_CFG_MONITOR_IORDY 0x00000200
27#define SIL_STATUS_INTR 0x08
28
29#define SIL_CLK_MASK 0x30
30#define SIL_CLK_100MHZ 0x00
31#define SIL_CLK_133MHZ 0x10
32#define SIL_CLK_X2 0x20
33#define SIL_CLK_DISABLED 0x30
34
36{
37 0x328A, // 0
38 0x2283, // 1
39 0x1281, // 2
40 0x10C3, // 3
41 0x10C1 // 4
42};
43
44static const USHORT Sil680PioTimings[] =
45{
46 0x328A, // 0
47 0x2283, // 1
48 0x1104, // 2
49 0x10C3, // 3
50 0x10C1 // 4
51};
52
53static const USHORT Sil680MwDmaTimings[] =
54{
55 0x2208, // 0
56 0x10C2, // 1
57 0x10C1, // 2
58};
59
60static const UCHAR Sil680UdmaTimings[2][7] =
61{
62 // 0 1 2 3 4 5 6
63 { 0x0B, 0x07, 0x05, 0x04, 0x02, 0x01 }, // 100MHz
64 { 0x0F, 0x0B, 0x07, 0x05, 0x03, 0x02, 0x01 }, // 133MHz
65};
66
67/* FUNCTIONS ******************************************************************/
68
69static
70VOID
72 _In_ PATA_CONTROLLER Controller,
75{
76 ULONG i, SlowestPioMode, Config;
77 UCHAR ModeReg;
78 BOOLEAN MonitorIoReady = FALSE;
79
80 INFO("CH %lu: Config (before)\n"
81 "MODE %08lX\n"
82 "CFG %08lX\n"
83 "PIO %08lX\n"
84 "DMA %08lX\n"
85 "UDMA %08lX\n",
86 Channel,
88 PciRead32(Controller, SIL_REG_CFG(Channel)),
89 PciRead32(Controller, SIL_REG_PIO_TIMING(Channel, 0)),
90 PciRead32(Controller, SIL_REG_DMA_TIMING(Channel, 0)),
91 PciRead32(Controller, SIL_REG_UDMA_TIMING(Channel, 0)));
92
93 SlowestPioMode = UDMA_MODE(0);
94 ModeReg = PciRead8(Controller, SIL_REG_XFER_MODE(Channel));
95
96 for (i = 0; i < MAX_IDE_DEVICE; ++i)
97 {
99 UCHAR XferMode, SysConfig;
100
101 if (!Device)
102 continue;
103
104 /* PIO timings */
105 SlowestPioMode = min(SlowestPioMode, Device->PioMode);
107
108 if (Device->PioMode >= PIO_MODE(3))
109 MonitorIoReady = TRUE;
110
111 if (Device->DmaMode >= UDMA_MODE(0))
112 {
113 SysConfig = PciRead8(Controller, SIL_REG_SYS_CFG);
114
115 /* Try to enable the 133MHz IDE clock */
116 if ((SysConfig & SIL_CLK_MASK) == SIL_CLK_100MHZ)
117 {
118 PciWrite8(Controller, SIL_REG_SYS_CFG, SysConfig | SIL_CLK_133MHZ);
119
120 SysConfig = PciRead8(Controller, SIL_REG_SYS_CFG);
121 }
122
123 /* If we are unable to do so, skip UDMA6 selection */
124 if ((Device->DmaMode == UDMA_MODE(6)) &&
125 (SysConfig & SIL_CLK_MASK) == SIL_CLK_100MHZ)
126 {
127 ULONG SupportedModes = Device->SupportedModes & ~(PIO_ALL | UDMA_MODE6);
128
129 if (!_BitScanReverse(&Device->DmaMode, SupportedModes))
130 Device->DmaMode = PIO_MODE(0);
131 }
132 }
133
134 /* UDMA timings */
135 if (Device->DmaMode >= UDMA_MODE(0))
136 {
137 ULONG ClockIndex = ((SysConfig & SIL_CLK_MASK) == SIL_CLK_100MHZ) ? 0 : 1;
138 USHORT UdmaTim;
139
140 XferMode = 3;
141
142 UdmaTim = PciRead16(Controller, SIL_REG_UDMA_TIMING(Channel, i));
143 UdmaTim &= ~0x003F;
144 UdmaTim |= Sil680UdmaTimings[ClockIndex][Device->DmaMode - UDMA_MODE(0)];
145 PciWrite16(Controller, SIL_REG_UDMA_TIMING(Channel, i), UdmaTim);
146 }
147 /* DMA timings */
148 else if (Device->DmaMode != PIO_MODE(0))
149 {
150 ULONG ModeIndex = Device->DmaMode - MWDMA_MODE(0);
151
152 XferMode = 2;
153
154 PciWrite16(Controller, SIL_REG_DMA_TIMING(Channel, i), Sil680MwDmaTimings[ModeIndex]);
155 }
156 else
157 {
158 if (Device->IoReadySupported)
159 XferMode = 1;
160 else
161 XferMode = 0;
162 }
163
164 ModeReg &= ~(0x03 << (i * 4));
165 ModeReg |= XferMode << (i * 4);
166 }
167
168 /* Transfer mode */
169 PciWrite8(Controller, SIL_REG_XFER_MODE(Channel), ModeReg);
170
171 Config = PciRead32(Controller, SIL_REG_CFG(Channel));
172 if (MonitorIoReady)
174 else
175 Config &= ~SIL_CFG_MONITOR_IORDY;
176
177 /* Task file timings */
178 if (SlowestPioMode != UDMA_MODE(0))
179 {
180 Config &= ~0xFFFF0000;
181 Config |= Sil680TaskFileTimings[SlowestPioMode] << 16;
182 }
183
184 PciWrite32(Controller, SIL_REG_CFG(Channel), Config);
185
186 INFO("CH %lu: Config (after)\n"
187 "MODE %08lX\n"
188 "CFG %08lX\n"
189 "PIO %08lX\n"
190 "DMA %08lX\n"
191 "UDMA %08lX\n",
192 Channel,
193 PciRead32(Controller, SIL_REG_XFER_MODE(Channel)),
194 Config,
195 PciRead32(Controller, SIL_REG_PIO_TIMING(Channel, 0)),
196 PciRead32(Controller, SIL_REG_DMA_TIMING(Channel, 0)),
197 PciRead32(Controller, SIL_REG_UDMA_TIMING(Channel, 0)));
198}
199
200static
203 _In_ PCHANNEL_DATA_PATA ChanData)
204{
205 PATA_CONTROLLER Controller = ChanData->Controller;
207
208 Status = PciRead8(Controller, SIL_REG_STATUS(ChanData->Channel));
209 return !!(Status & SIL_STATUS_INTR);
210}
211
212CODE_SEG("PAGE")
215 _Inout_ PATA_CONTROLLER Controller)
216{
218 ULONG i;
219
220 PAGED_CODE();
221 ASSERT(Controller->Pci.VendorID == PCI_VEN_CMD);
222
223 if (Controller->Pci.VendorID != PCI_DEV_SIL0680)
224 return STATUS_NO_MATCH;
225
226 Status = PciIdeCreateChannelData(Controller, 0);
227 if (!NT_SUCCESS(Status))
228 return Status;
229
230 for (i = 0; i < Controller->MaxChannels; ++i)
231 {
232 PCHANNEL_DATA_PATA ChanData = Controller->Channels[i];
234
236 ChanData->SetTransferMode = Sil680SetTransferMode;
237 ChanData->TransferModeSupported = PIO_ALL | MWDMA_ALL | UDMA_MODES(0, 6);
238
239 /* Check for 80-conductor cable */
240 Config = PciRead8(Controller, SIL_REG_CFG(i));
241 if (!(Config & SIL_CFG_CABLE_80))
242 {
243 INFO("CH %lu: BIOS detected 40-conductor cable\n", ChanData->Channel);
244 ChanData->TransferModeSupported &= ~UDMA_80C_ALL;
245 }
246 }
247
249}
#define PAGED_CODE()
#define CODE_SEG(...)
unsigned char BOOLEAN
Definition: actypes.h:127
#define MWDMA_ALL
Definition: ata_user.h:27
#define PIO_MODE(n)
Definition: ata_user.h:36
#define MWDMA_MODE(n)
Definition: ata_user.h:38
#define PIO_ALL
Definition: ata_user.h:19
#define UDMA_MODE(n)
Definition: ata_user.h:39
LONG NTSTATUS
Definition: precomp.h:26
#define STATUS_NOT_IMPLEMENTED
Definition: d3dkmdt.h:42
#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
#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
#define UDMA_MODE6
Definition: ide.h:297
#define MAX_IDE_DEVICE
Definition: ide.h:32
#define ASSERT(a)
Definition: mode.c:44
#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 _In_
Definition: no_sal2.h:158
#define STATUS_NO_MATCH
Definition: ntstatus.h:873
#define PCI_VEN_CMD
Definition: pata.h:14
#define UDMA_MODES(MinMode, MaxMode)
Definition: pata.h:49
NTSTATUS PciIdeCreateChannelData(_In_ PATA_CONTROLLER Controller, _In_ ULONG HwExtensionSize)
FORCEINLINE UCHAR PciRead8(_In_ PATA_CONTROLLER Controller, _In_ ULONG ConfigDataOffset)
Definition: pciidex.h:847
_In_ ULONG Channel
Definition: pciidex.h:74
FORCEINLINE VOID PciWrite16(_In_ PATA_CONTROLLER Controller, _In_ ULONG ConfigDataOffset, _In_ USHORT Value)
Definition: pciidex.h:893
FORCEINLINE VOID PciWrite8(_In_ PATA_CONTROLLER Controller, _In_ ULONG ConfigDataOffset, _In_ UCHAR Value)
Definition: pciidex.h:883
FORCEINLINE VOID PciWrite32(_In_ PATA_CONTROLLER Controller, _In_ ULONG ConfigDataOffset, _In_ ULONG Value)
Definition: pciidex.h:903
FORCEINLINE USHORT PciRead16(_In_ PATA_CONTROLLER Controller, _In_ ULONG ConfigDataOffset)
Definition: pciidex.h:859
FORCEINLINE ULONG PciRead32(_In_ PATA_CONTROLLER Controller, _In_ ULONG ConfigDataOffset)
Definition: pciidex.h:871
unsigned short USHORT
Definition: pedump.c:61
unsigned char _BitScanReverse(unsigned long *_Index, unsigned long _Mask)
Definition: intrin_arm.h:180
#define SIL_CLK_MASK
Definition: sil680.c:29
#define SIL_CFG_CABLE_80
Definition: sil680.c:25
#define SIL_REG_XFER_MODE(Channel)
Definition: sil680.c:16
#define SIL_REG_DMA_TIMING(Channel, Drive)
Definition: sil680.c:22
static const UCHAR Sil680UdmaTimings[2][7]
Definition: sil680.c:60
static const USHORT Sil680TaskFileTimings[]
Definition: sil680.c:35
#define SIL_REG_CFG(Channel)
Definition: sil680.c:18
#define SIL_CLK_133MHZ
Definition: sil680.c:31
#define SIL_REG_SYS_CFG
Definition: sil680.c:17
#define SIL_CLK_100MHZ
Definition: sil680.c:30
NTSTATUS Sil680GetControllerProperties(_Inout_ PATA_CONTROLLER Controller)
Definition: sil680.c:214
static const USHORT Sil680PioTimings[]
Definition: sil680.c:44
#define SIL_REG_UDMA_TIMING(Channel, Drive)
Definition: sil680.c:23
static BOOLEAN Sil680CheckInterrupt(_In_ PCHANNEL_DATA_PATA ChanData)
Definition: sil680.c:202
static VOID Sil680SetTransferMode(_In_ PATA_CONTROLLER Controller, _In_ ULONG Channel, _In_reads_(MAX_IDE_DEVICE) PCHANNEL_DEVICE_CONFIG *DeviceList)
Definition: sil680.c:71
#define SIL_REG_PIO_TIMING(Channel, Drive)
Definition: sil680.c:21
#define PCI_DEV_SIL0680
Definition: sil680.c:14
#define SIL_STATUS_INTR
Definition: sil680.c:27
static const USHORT Sil680MwDmaTimings[]
Definition: sil680.c:53
#define SIL_REG_STATUS(Channel)
Definition: sil680.c:19
#define SIL_CFG_MONITOR_IORDY
Definition: sil680.c:26
PCHANNEL_CHECK_INTERRUPT CheckInterrupt
Definition: pciidex.h:303
unsigned char UCHAR
Definition: typedefs.h:53
uint32_t ULONG
Definition: typedefs.h:59
_Must_inspect_result_ _In_ WDFDEVICE Device
Definition: wdfchildlist.h:474
_Must_inspect_result_ _In_ WDFDEVICE _In_ PWDF_CHILD_LIST_CONFIG Config
Definition: wdfchildlist.h:476