ReactOS 0.4.17-dev-1133-gc25e4fd
hpt.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: HighPoint ATA controller minidriver
5 * COPYRIGHT: Copyright 2026 Dmitry Borisov <di.sean@protonmail.com>
6 */
7
8/*
9 * Adapted from the FreeBSD ata-highpoint driver
10 * Copyright (c) 1998-2008 Søren Schmidt <sos@FreeBSD.org>
11 */
12
13/* INCLUDES *******************************************************************/
14
15#include "pciidex.h"
16
17/* GLOBALS ********************************************************************/
18
19#define PCI_DEV_HPT366 0x0004
20#define PCI_DEV_HPT372 0x0005
21#define PCI_DEV_HPT302 0x0006
22#define PCI_DEV_HPT371 0x0007
23#define PCI_DEV_HPT374 0x0008
24#define PCI_DEV_HPT372N 0x0009
25
26#define TYPE_366 0
27#define TYPE_370 1
28#define TYPE_372 2
29#define TYPE_374 3
30
31#define GET_TYPE(Flags) ((Flags) & HW_FLAGS_TYPE_MASK)
32
33#define HW_FLAGS_TYPE_MASK 0x03
34#define HW_FLAGS_SINGLE_CHAN 0x04
35#define HW_FLAGS_UDMA4 0x08
36#define HW_FLAGS_UDMA5 0x10
37
38#define HPT_REG_TIMING(Index) (0x40 + (Index << 2))
39
40#define HPT366_TIM_DATA_HIGH_CYT_MASK 0x0000000F
41#define HPT366_TIM_DATA_LOW_CYT_MASK 0x000000F0
42#define HPT366_TIM_CMD_HIGH_CYT_MASK 0x00000F00
43#define HPT366_TIM_CMD_LOW_CYT_MASK 0x0000F000
44#define HPT366_TIM_UDMA_CYT_MASK 0x00070000
45#define HPT366_TIM_PRE_HIGH_CYT_MASK 0x00380000
46#define HPT366_TIM_CMD_PRE_HIGH_CYT_MASK 0x01C00000
47#define HPT366_TIM_UDMA_ENABLE 0x10000000
48#define HPT366_TIM_DMA_ENABLE 0x20000000
49#define HPT366_TIM_PIO_MST_ENABLE 0x40000000
50#define HPT366_TIM_PIO_BUFFER_ENABLE 0x80000000
51
52#define HPT37X_TIM_DATA_HIGH_CYT_MASK 0x0000000F
53#define HPT37X_TIM_DATA_LOW_CYT_MASK 0x000001F0
54#define HPT37X_TIM_CMD_HIGH_CYT_MASK 0x00001E00
55#define HPT37X_TIM_CMD_LOW_CYT_MASK 0x0003E000
56#define HPT37X_TIM_UDMA_CYT_MASK 0x001C0000
57#define HPT37X_TIM_UDMA_DUAL_CLOCK_ENABLE 0x00200000
58#define HPT37X_TIM_PRE_HIGH_CYT_MASK 0x01C00000
59#define HPT37X_TIM_CMD_PRE_HIGH_CYT_MASK 0x0E000000
60#define HPT37X_TIM_UDMA_ENABLE 0x10000000
61#define HPT37X_TIM_DMA_ENABLE 0x20000000
62#define HPT37X_TIM_PIO_MST_ENABLE 0x40000000
63#define HPT37X_TIM_PIO_BUFFER_ENABLE 0x80000000
64
66static const struct
67{
72{
76
78
81
85};
86
87static const ULONG HptTimings[][4] =
88{
89 // HPT366 HPT370 HPT372 HPT374 mode
90 { 0x00d0a7aa, 0x06914e57, 0x0d029d5e, 0x0ac1f48a }, // PIO 0
91 { 0x00d0a7a3, 0x06914e43, 0x0d029d26, 0x0ac1f465 }, // PIO 1
92 { 0x00d0a753, 0x06514e33, 0x0c829ca6, 0x0a81f454 }, // PIO 2
93 { 0x00c8a742, 0x06514e22, 0x0c829c84, 0x0a81f443 }, // PIO 3
94 { 0x00c8a731, 0x06514e21, 0x0c829c62, 0x0a81f442 }, // PIO 4
95
96 { 0x20c8a797, 0x26514e97, 0x2c82922e, 0x228082ea }, // MWDMA 0
97 { 0x20c8a732, 0x26514e33, 0x2c829266, 0x22808254 }, // MWDMA 1
98 { 0x20c8a731, 0x26514e21, 0x2c829262, 0x22808242 }, // MWDMA 2
99
100 { 0x10c8a731, 0x16514e31, 0x1c829c62, 0x121882ea }, // UDMA 0
101 { 0x10cba731, 0x164d4e31, 0x1c9a9c62, 0x12148254 }, // UDMA 1
102 { 0x10caa731, 0x16494e31, 0x1c929c62, 0x120c8242 }, // UDMA 2
103 { 0x10cfa731, 0x166d4e31, 0x1c8e9c62, 0x128c8242 }, // UDMA 3
104 { 0x10c9a731, 0x16454e31, 0x1c8a9c62, 0x12ac8242 }, // UDMA 4
105 { 0, 0x16454e31, 0x1c8a9c62, 0x12848242 }, // UDMA 5
106 { 0, 0, 0x1c869c62, 0x12808242 } // UDMA 6
107};
108
109static const ULONG HptMwDmaToPioMode[] =
110{
111 PIO_MODE(1), // MWDMA_MODE(0)
112 PIO_MODE(3), // MWDMA_MODE(1)
113 PIO_MODE(4), // MWDMA_MODE(2)
114};
115
118{
119 { 0x50, 0x04, 0x04 },
120 { 0x54, 0x04, 0x04 },
121};
122
125{
126 { 0x50, 0x30, 0x30 },
127};
128
129/* FUNCTIONS ******************************************************************/
130
131static
132ULONG
135 _In_ ULONG HptType)
136{
137 ULONG Mask, Mode, PioTimings, DmaTimings;
138
139 Mode = Device->PioMode;
140 PioTimings = HptTimings[Mode][HptType];
141
142 Mode = Device->DmaMode;
143 if (Mode >= MWDMA_MODE(0))
144 Mode -= MWDMA_MODE(0) - SWDMA_MODE(0);
145 DmaTimings = HptTimings[Mode][HptType];
146
147 if (Device->DmaMode >= UDMA_MODE(0))
148 {
149 if (HptType == TYPE_366)
150 {
154 }
155 else
156 {
161 }
162 }
163 else if (Device->DmaMode != PIO_MODE(0))
164 {
165 Mask = 0xFFFFFFFF;
166
167 for (Mode = Device->DmaMode; Mode > PIO_MODE(0); Mode--)
168 {
169 ULONG MinPio;
170
171 if (!(Device->SupportedModes & ~PIO_ALL & (1 << Mode)))
172 continue;
173
174 MinPio = HptMwDmaToPioMode[Mode - MWDMA_MODE(0)];
175
176 if (Device->SupportedModes & (1 << MinPio))
177 {
178 Device->PioMode = MinPio;
179 break;
180 }
181 }
182 if (Mode != Device->DmaMode)
183 {
184 if (Mode == PIO_MODE(0))
185 WARN("Too slow device '%s', disabling DMA\n", Device->FriendlyName);
186 else
187 INFO("Downgrade DMA speed from %lu to %lu\n", Device->DmaMode, Mode);
188 }
189 Device->DmaMode = Mode;
190 }
191
192 if (Device->DmaMode == PIO_MODE(0))
193 Mask = 0;
194
195 return (PioTimings & ~Mask) | (DmaTimings & Mask);
196}
197
198static
199VOID
204{
205 PCHANNEL_DATA_PATA ChanData = Controller->Channels[Channel];
206 ULONG i;
207
208 for (i = 0; i < MAX_IDE_DEVICE; ++i)
209 {
211 const ULONG DeviceIndex = (Channel << 1) + i;
212 ULONG Value;
213
214 if (!Device)
215 continue;
216
218
219 INFO("CH %lu: Dev %lu update timings from %08lx to %08lx\n",
220 Channel,
221 i,
222 PciRead32(Controller, HPT_REG_TIMING(DeviceIndex)),
223 Value);
224
226 }
227}
228
229static
230VOID
233{
234 PCHANNEL_DATA_PATA ChanData = Controller->Channels[0];
235 ULONG HwFlags = ChanData->HwFlags;
236 UCHAR Value;
237
238 if (GET_TYPE(HwFlags) == TYPE_366)
239 {
240 /* Disable interrupt prediction */
241 Value = PciRead8(Controller, 0x51);
242 Value &= ~0x80;
243 PciWrite8(Controller, 0x51, Value);
244 }
245 else
246 {
247 /* Disable interrupt prediction */
248 Value = PciRead8(Controller, 0x51);
249 Value &= ~0x03;
250 PciWrite8(Controller, 0x51, Value);
251
252 Value = PciRead8(Controller, 0x55);
253 Value &= ~0x03;
254 PciWrite8(Controller, 0x55, Value);
255
256 /* Enable interrupts */
257 Value = PciRead8(Controller, 0x5A);
258 Value &= ~0x10;
259 PciWrite8(Controller, 0x5A, Value);
260
261 /* Set clocks */
262 if (GET_TYPE(HwFlags) < TYPE_372)
263 {
264 PciWrite8(Controller, 0x5B, 0x22);
265 }
266 else
267 {
268 Value = PciRead8(Controller, 0x5B);
269 Value &= 0x01;
270 Value |= 0x20;
271 PciWrite8(Controller, 0x5B, Value);
272 }
273 }
274}
275
276static
277CODE_SEG("PAGE")
281 _In_ ULONG HwFlags,
283{
284 UCHAR Register, Value, CableSelect;
285
286 PAGED_CODE();
287
288 /* Unlock the cable state pins */
289 if (GET_TYPE(HwFlags) != TYPE_366)
290 {
291 if ((GET_TYPE(HwFlags) == TYPE_374) && (Controller->BusLocation & 1))
292 {
293 Register = (Channel == 0) ? 0x53 : 0x57;
296 }
297 else
298 {
299 Register = 0x5B;
302 }
303 }
304
305 CableSelect = PciRead8(Controller, 0x5A);
306
307 /* Restore settings */
308 if (GET_TYPE(HwFlags) != TYPE_366)
310
311 return !(CableSelect & (0x02 >> Channel));
312}
313
314CODE_SEG("PAGE")
318{
320 ULONG i, HwFlags;
321
322 PAGED_CODE();
323 ASSERT(Controller->Pci.VendorID == PCI_VEN_HIGHPOINT);
324
325 for (i = 0; i < RTL_NUMBER_OF(HptControllerList); ++i)
326 {
327 HwFlags = HptControllerList[i].Flags;
328
329 if ((Controller->Pci.DeviceID == HptControllerList[i].DeviceID) &&
330 (Controller->Pci.RevisionID >= HptControllerList[i].MinimumRevisionID))
331 {
332 break;
333 }
334 }
336 return STATUS_NO_MATCH;
337
340
341 if (HwFlags & HW_FLAGS_SINGLE_CHAN)
342 Controller->MaxChannels = 1;
343
344 if (GET_TYPE(HwFlags) == TYPE_366)
345 Controller->ChannelEnableBits = Hpt366EnableBits;
346 else
347 Controller->ChannelEnableBits = Hpt37xEnableBits;
348
350 if (!NT_SUCCESS(Status))
351 return Status;
352
353 for (i = 0; i < Controller->MaxChannels; ++i)
354 {
355 PCHANNEL_DATA_PATA ChanData = Controller->Channels[i];
356
357 ChanData->HwFlags = HwFlags;
358 ChanData->SetTransferMode = HptSetTransferMode;
359
360 ChanData->TransferModeSupported = PIO_ALL | MWDMA_ALL | UDMA_ALL;
361 if (HwFlags & HW_FLAGS_UDMA5)
362 ChanData->TransferModeSupported &= ~UDMA_MODE6;
363 else if (HwFlags & HW_FLAGS_UDMA4)
364 ChanData->TransferModeSupported &= ~(UDMA_MODE6 | UDMA_MODE5);
365
366 /* Check for 80-conductor cable */
367 if (!HptHasUdmaCable(Controller, HwFlags, i))
368 {
369 INFO("CH %lu: BIOS detected 40-conductor cable\n", ChanData->Channel);
370 ChanData->TransferModeSupported &= ~UDMA_80C_ALL;
371 }
372 }
373
374 return STATUS_SUCCESS;
375}
#define PAGED_CODE()
#define CODE_SEG(...)
#define RTL_NUMBER_OF(x)
Definition: RtlRegistry.c:12
unsigned char BOOLEAN
Definition: actypes.h:127
#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 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
LONG NTSTATUS
Definition: precomp.h:26
#define WARN(fmt,...)
Definition: precomp.h:61
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
PDEVICE_LIST DeviceList
Definition: utils.c:27
#define INFO
Definition: debug.h:89
unsigned int Mask
Definition: fpcontrol.c:82
Status
Definition: gdiplustypes.h:24
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define HPT366_TIM_UDMA_CYT_MASK
Definition: hpt.c:44
#define HPT_REG_TIMING(Index)
Definition: hpt.c:38
#define HW_FLAGS_UDMA5
Definition: hpt.c:36
#define HPT37X_TIM_UDMA_DUAL_CLOCK_ENABLE
Definition: hpt.c:57
#define HPT366_TIM_PIO_MST_ENABLE
Definition: hpt.c:49
#define PCI_DEV_HPT372N
Definition: hpt.c:24
#define HW_FLAGS_UDMA4
Definition: hpt.c:35
#define PCI_DEV_HPT366
Definition: hpt.c:19
#define TYPE_366
Definition: hpt.c:26
#define TYPE_370
Definition: hpt.c:27
static VOID HptControllerStart(_In_ PATA_CONTROLLER Controller)
Definition: hpt.c:231
#define PCI_DEV_HPT372
Definition: hpt.c:20
static ULONG HptChooseTimings(_Inout_ PCHANNEL_DEVICE_CONFIG Device, _In_ ULONG HptType)
Definition: hpt.c:133
NTSTATUS HptGetControllerProperties(_Inout_ PATA_CONTROLLER Controller)
Definition: hpt.c:316
#define TYPE_372
Definition: hpt.c:28
static VOID HptSetTransferMode(_In_ PATA_CONTROLLER Controller, _In_ ULONG Channel, _In_reads_(MAX_IDE_DEVICE) PCHANNEL_DEVICE_CONFIG *DeviceList)
Definition: hpt.c:200
#define PCI_DEV_HPT302
Definition: hpt.c:21
#define TYPE_374
Definition: hpt.c:29
#define HPT37X_TIM_PIO_MST_ENABLE
Definition: hpt.c:62
static PCIIDEX_PAGED_DATA const ATA_PCI_ENABLE_BITS Hpt366EnableBits[1]
Definition: hpt.c:124
static const ULONG HptMwDmaToPioMode[]
Definition: hpt.c:109
#define PCI_DEV_HPT374
Definition: hpt.c:23
#define GET_TYPE(Flags)
Definition: hpt.c:31
#define PCI_DEV_HPT371
Definition: hpt.c:22
UCHAR MinimumRevisionID
Definition: hpt.c:69
static PCIIDEX_PAGED_DATA const ATA_PCI_ENABLE_BITS Hpt37xEnableBits[MAX_IDE_CHANNEL]
Definition: hpt.c:117
#define HPT366_TIM_UDMA_ENABLE
Definition: hpt.c:47
#define HW_FLAGS_SINGLE_CHAN
Definition: hpt.c:34
#define HPT37X_TIM_UDMA_CYT_MASK
Definition: hpt.c:56
USHORT DeviceID
Definition: hpt.c:68
static BOOLEAN HptHasUdmaCable(_In_ PATA_CONTROLLER Controller, _In_ ULONG HwFlags, _In_ ULONG Channel)
Definition: hpt.c:279
UCHAR Flags
Definition: hpt.c:70
static PCIIDEX_PAGED_DATA const struct @1283 HptControllerList[]
static const ULONG HptTimings[][4]
Definition: hpt.c:87
#define HPT37X_TIM_UDMA_ENABLE
Definition: hpt.c:60
_In_ ULONG Mode
Definition: hubbusif.h:303
_Must_inspect_result_ _In_ PUCXHUB_DEVICE_CREATE_INFO _Out_ UCXUSBDEVICE * Device
Definition: hubucx.h:258
#define UDMA_MODE6
Definition: ide.h:297
#define MAX_IDE_DEVICE
Definition: ide.h:32
#define UDMA_MODE5
Definition: ide.h:296
#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 STATUS_NO_MATCH
Definition: ntstatus.h:873
#define PCI_VEN_HIGHPOINT
Definition: pata.h:15
NTSTATUS PciIdeCreateChannelData(_In_ PATA_CONTROLLER Controller, _In_ ULONG HwExtensionSize)
FORCEINLINE UCHAR PciRead8(_In_ PATA_CONTROLLER Controller, _In_ ULONG ConfigDataOffset)
Definition: pciidex.h:859
_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:895
FORCEINLINE VOID PciWrite32(_In_ PATA_CONTROLLER Controller, _In_ ULONG ConfigDataOffset, _In_ ULONG Value)
Definition: pciidex.h:915
#define CTRL_FLAG_DMA_INTERRUPT
Definition: pciidex.h:231
FORCEINLINE ULONG PciRead32(_In_ PATA_CONTROLLER Controller, _In_ ULONG ConfigDataOffset)
Definition: pciidex.h:883
unsigned short USHORT
Definition: pedump.c:61
#define STATUS_SUCCESS
Definition: shellext.h:65
unsigned char UCHAR
Definition: typedefs.h:53
uint32_t ULONG
Definition: typedefs.h:59
_Must_inspect_result_ _In_ WDFDEVICE _In_ PUCX_CONTROLLER_CONFIG _In_opt_ PWDF_OBJECT_ATTRIBUTES _Out_ UCXCONTROLLER * Controller
_Must_inspect_result_ _In_ WDFKEY _In_ PCUNICODE_STRING _Out_opt_ PUSHORT _Inout_opt_ PUNICODE_STRING Value
Definition: wdfregistry.h:413