ReactOS 0.4.16-dev-2633-g8dc9e50
svw_sata.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: ServerWorks/Broadcom SATA controller minidriver
5 * COPYRIGHT: Copyright 2026 Dmitry Borisov <di.sean@protonmail.com>
6 */
7
8/*
9 * Adapted from the FreeBSD ata-serverworks 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_K2_SATA 0x0240
20#define PCI_DEV_BCM5770_SATA 0x0241
21#define PCI_DEV_BCM5770R_SATA 0x0242
22#define PCI_DEV_HT1000_SATA 0x024A
23#define PCI_DEV_HT1000_SATA_2 0x024B
24#define PCI_DEV_HT1100_SATA 0x0410
25#define PCI_DEV_HT1100_SATA_2 0x0411
26
27#define SVW_SATA_PORT_BASE_OFFSET 0x100
28#define SVW_SATA_PORT_CONTROL_OFFSET 0x20
29#define SVW_SATA_PORT_DMA_OFFSET 0x30
30#define SVW_SATA_PORT_SCR_OFFSET 0x40
31#define SVW_SATA_PORT_TF_STRIDE 4
32
33#define HW_FLAGS_8_PORTS 0x01
34#define HW_FLAGS_NO_ATAPI_DMA 0x02
35
37static const struct
38{
42{
50};
51
52/* FUNCTIONS ******************************************************************/
53
54static
57 _In_ PCHANNEL_DATA_PATA ChanData,
61{
63
65 return FALSE;
66
67 *Result = READ_REGISTER_ULONG((PULONG)(ChanData->Regs.Scr + (Register * 4)));
68 return TRUE;
69}
70
71static
74 _In_ PCHANNEL_DATA_PATA ChanData,
78{
80
82 return FALSE;
83
84 WRITE_REGISTER_ULONG((PULONG)(ChanData->Regs.Scr + (Register * 4)), Value);
85 return TRUE;
86}
87
88static
89inline
92 _In_ PATA_CONTROLLER Controller)
93{
94 return (Controller->Pci.DeviceID == PCI_DEV_HT1100_SATA) ? 3 : 5;
95}
96
97static
100 _In_ PCHANNEL_DATA_PATA ChanData)
101{
102 PATA_CONTROLLER Controller = ChanData->Controller;
103 PUCHAR IoBase = Controller->AccessRange[SvwSataGetIoBarIndex(Controller)].IoBase;
104 ULONG InterruptStatus;
105
106 InterruptStatus = READ_REGISTER_ULONG((PULONG)(IoBase + 0x1F80));
107 return !!(InterruptStatus & (1 << ChanData->Channel));
108}
109
110static
111UCHAR
113 _In_ PCHANNEL_DATA_PATA ChanData)
114{
115 /*
116 * The SATA hardware expects 32-bit reads on the status register
117 * to get it latched propertly.
118 */
119 return READ_REGISTER_ULONG((PULONG)ChanData->Regs.Status);
120}
121
122static
123VOID
125 _In_ PCHANNEL_DATA_PATA ChanData,
127{
128 USHORT Features, SectorCount, LbaLow, LbaMid, LbaHigh;
129
130 Features = Request->TaskFile.Feature;
131 SectorCount = Request->TaskFile.SectorCount;
132 LbaLow = Request->TaskFile.LowLba;
133 LbaMid = Request->TaskFile.MidLba;
134 LbaHigh = Request->TaskFile.HighLba;
135
136 if (Request->Flags & REQUEST_FLAG_LBA48)
137 {
138 Features |= (USHORT)Request->TaskFile.FeatureEx << 8;
139 SectorCount |= (USHORT)Request->TaskFile.SectorCountEx << 8;
140 LbaLow |= (USHORT)Request->TaskFile.LowLbaEx << 8;
141 LbaMid |= (USHORT)Request->TaskFile.MidLbaEx << 8;
142 LbaHigh |= (USHORT)Request->TaskFile.HighLbaEx << 8;
143 }
144
145 /* The SATA hardware needs 16-bit accesses for the second byte of FIFO */
146 WRITE_REGISTER_USHORT((PUSHORT)ChanData->Regs.Features, Features);
147 WRITE_REGISTER_USHORT((PUSHORT)ChanData->Regs.SectorCount, SectorCount);
148 WRITE_REGISTER_USHORT((PUSHORT)ChanData->Regs.LbaLow, LbaLow);
149 WRITE_REGISTER_USHORT((PUSHORT)ChanData->Regs.LbaMid, LbaMid);
150 WRITE_REGISTER_USHORT((PUSHORT)ChanData->Regs.LbaHigh, LbaHigh);
151
153 WRITE_REGISTER_UCHAR(ChanData->Regs.Device, Request->TaskFile.DriveSelect);
154}
155
156static
157VOID
159 _In_ PCHANNEL_DATA_PATA ChanData,
161{
162 PATA_TASKFILE TaskFile = &Request->Output;
163 USHORT Error, SectorCount, LbaLow, LbaMid, LbaHigh;
164
165 TaskFile->DriveSelect = READ_REGISTER_UCHAR(ChanData->Regs.Device);
166 TaskFile->Command = READ_REGISTER_UCHAR(ChanData->Regs.Command);
167
168 Error = READ_REGISTER_USHORT((PUSHORT)ChanData->Regs.Error);
169 SectorCount = READ_REGISTER_USHORT((PUSHORT)ChanData->Regs.SectorCount);
170 LbaLow = READ_REGISTER_USHORT((PUSHORT)ChanData->Regs.LbaLow);
171 LbaMid = READ_REGISTER_USHORT((PUSHORT)ChanData->Regs.LbaMid);
172 LbaHigh = READ_REGISTER_USHORT((PUSHORT)ChanData->Regs.LbaHigh);
173
174 TaskFile->Error = Error & 0xFF;
175 TaskFile->SectorCount = SectorCount & 0xFF;
176 TaskFile->LowLba = LbaLow & 0xFF;
177 TaskFile->MidLba = LbaMid & 0xFF;
178 TaskFile->HighLba = LbaHigh & 0xFF;
179
180 if (Request->Flags & REQUEST_FLAG_LBA48)
181 {
182 TaskFile->FeatureEx = Error >> 8;
183 TaskFile->SectorCountEx = SectorCount >> 8;
184 TaskFile->LowLbaEx = LbaLow >> 8;
185 TaskFile->MidLbaEx = LbaMid >> 8;
186 TaskFile->HighLbaEx = LbaHigh >> 8;
187 }
188}
189
190static
191CODE_SEG("PAGE")
192VOID
195 _In_ PUCHAR IoBase,
196 _In_ ULONG PortIndex)
197{
198 PUCHAR ChanBase = IoBase + (PortIndex * SVW_SATA_PORT_BASE_OFFSET);
199
200 PAGED_CODE();
201
203
204 ChanData->Regs.Dma = ChanBase + SVW_SATA_PORT_DMA_OFFSET;
205 ChanData->Regs.Scr = ChanBase + SVW_SATA_PORT_SCR_OFFSET;
206
208 (ULONG_PTR)ChanBase,
211}
212
213CODE_SEG("PAGE")
216 _Inout_ PATA_CONTROLLER Controller)
217{
219 ULONG i, HwFlags;
220 PUCHAR IoBase;
221
222 PAGED_CODE();
223 ASSERT(Controller->Pci.VendorID == PCI_VEN_SERVERWORKS);
224
225 for (i = 0; i < RTL_NUMBER_OF(SvwSataControllerList); ++i)
226 {
227 HwFlags = SvwSataControllerList[i].Flags;
228
229 if (Controller->Pci.DeviceID == SvwSataControllerList[i].DeviceID)
230 break;
231 }
233 return STATUS_NO_MATCH;
234
235 if (HwFlags & HW_FLAGS_8_PORTS)
236 Controller->MaxChannels = 8;
237 else
238 Controller->MaxChannels = 4;
239
240 Controller->Flags |= CTRL_FLAG_MANUAL_RES;
241
242 Status = PciIdeCreateChannelData(Controller, 0);
243 if (!NT_SUCCESS(Status))
244 return Status;
245
246 IoBase = AtaCtrlPciMapBar(Controller, SvwSataGetIoBarIndex(Controller), 0);
247 if (!IoBase)
249
250 /*
251 * Errata: Set SICR registers to turn off waiting for a status message
252 * before sending FIS, fixes some issues with Seagate hard drives.
253 */
254 WRITE_REGISTER_ULONG((PULONG)(IoBase + 0x80),
255 READ_REGISTER_ULONG((PULONG)(IoBase + 0x80)) & ~0x00040000);
256
257 /* Clear interrupts */
258 WRITE_REGISTER_ULONG((PULONG)(IoBase + 0x44), 0xFFFFFFFF);
259 WRITE_REGISTER_ULONG((PULONG)(IoBase + 0x88), 0);
260
261 for (i = 0; i < Controller->MaxChannels; ++i)
262 {
263 PCHANNEL_DATA_PATA ChanData = Controller->Channels[i];
264
265 ChanData->TransferModeSupported = SATA_ALL;
266 ChanData->SetTransferMode = SataSetTransferMode;
267
268 if (HwFlags & HW_FLAGS_NO_ATAPI_DMA)
269 ChanData->ChanInfo |= CHANNEL_FLAG_NO_ATAPI_DMA;
270
271 /*
272 * Errata: Enable the DMA engine before sending the drive command
273 * to avoid data corruption.
274 */
275 ChanData->ChanInfo |= CHANNEL_FLAG_DMA_BEFORE_CMD;
276
277 ChanData->ChanInfo |= CHANNEL_FLAG_NO_SLAVE;
278 ChanData->ReadStatus = SvwSataReadStatus;
282 ChanData->ScrRead = SvwSataScrRead;
283 ChanData->ScrWrite = SvwSataScrWrite;
284
285 SvwSataParseResources(ChanData, IoBase, i);
286 }
287
288 return STATUS_SUCCESS;
289}
#define PAGED_CODE()
#define CODE_SEG(...)
#define RTL_NUMBER_OF(x)
Definition: RtlRegistry.c:12
unsigned char BOOLEAN
Definition: actypes.h:127
enum _SATA_SCR_REGISTER SATA_SCR_REGISTER
@ ATA_SCONTROL
Definition: ahci.h:55
#define WRITE_REGISTER_USHORT(r, v)
Definition: arm.h:14
#define READ_REGISTER_USHORT(r)
Definition: arm.h:13
#define WRITE_REGISTER_ULONG(r, v)
Definition: arm.h:11
#define READ_REGISTER_ULONG(r)
Definition: arm.h:10
LONG NTSTATUS
Definition: precomp.h:26
BOOL Error
Definition: chkdsk.c:66
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
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 REQUEST_FLAG_LBA48
Definition: hwidep.h:167
#define REQUEST_FLAG_SET_DEVICE_REGISTER
Definition: hwidep.h:170
#define ASSERT(a)
Definition: mode.c:44
#define _Inout_
Definition: no_sal2.h:162
#define _In_
Definition: no_sal2.h:158
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:329
#define STATUS_NO_MATCH
Definition: ntstatus.h:873
#define STATUS_DEVICE_CONFIGURATION_ERROR
Definition: ntstatus.h:713
ULONG SectorCount
Definition: part_brfr.c:22
#define SATA_ALL
Definition: pata.h:37
#define PCI_VEN_SERVERWORKS
Definition: pata.h:16
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
#define CHANNEL_FLAG_MRES_TF
Definition: pciidex.h:280
#define CHANNEL_FLAG_MRES_DMA
Definition: pciidex.h:281
#define CHANNEL_FLAG_MRES_CTRL
Definition: pciidex.h:282
#define CHANNEL_FLAG_NO_ATAPI_DMA
Definition: pciidex.h:278
#define CHANNEL_FLAG_NO_SLAVE
Definition: pciidex.h:270
#define PCIIDEX_PAGED_DATA
Definition: pciidex.h:50
#define CTRL_FLAG_MANUAL_RES
Definition: pciidex.h:229
#define CHANNEL_FLAG_DMA_BEFORE_CMD
Definition: pciidex.h:279
CHANNEL_SET_MODE_EX SataSetTransferMode
Definition: pciidex.h:633
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
struct _ATA_CONTROLLER::@1180 AccessRange[PCI_TYPE0_ADDRESSES]
UCHAR SectorCountEx
Definition: ata_shared.h:200
UCHAR SectorCount
Definition: hwidep.h:151
UCHAR MidLba
LBA bits 8-15.
Definition: hwidep.h:153
UCHAR LowLbaEx
LBA bits 24-31.
Definition: ata_shared.h:195
UCHAR HighLba
LBA bits 16-23.
Definition: hwidep.h:154
UCHAR FeatureEx
Definition: ata_shared.h:198
UCHAR HighLbaEx
LBA bits 40-47.
Definition: ata_shared.h:197
UCHAR Command
Definition: hwidep.h:147
UCHAR DriveSelect
Definition: hwidep.h:146
UCHAR LowLba
LBA bits 0-7.
Definition: hwidep.h:152
UCHAR MidLbaEx
LBA bits 32-39.
Definition: ata_shared.h:196
PCHANNEL_CHECK_INTERRUPT CheckInterrupt
Definition: pciidex.h:303
PCHANNEL_READ_STATUS ReadStatus
Definition: pciidex.h:299
PCHANNEL_SAVE_TASK_FILE SaveTaskFile
Definition: pciidex.h:298
PCHANNEL_LOAD_TASK_FILE LoadTaskFile
Definition: pciidex.h:297
PCHANNEL_WRITE_SCR ScrWrite
Definition: pciidex.h:314
PCHANNEL_READ_SCR ScrRead
Definition: pciidex.h:313
#define SVW_SATA_PORT_TF_STRIDE
Definition: svw_sata.c:31
static VOID SvwSataSaveTaskFile(_In_ PCHANNEL_DATA_PATA ChanData, _Inout_ PATA_DEVICE_REQUEST Request)
Definition: svw_sata.c:158
#define PCI_DEV_HT1100_SATA
Definition: svw_sata.c:24
#define SVW_SATA_PORT_BASE_OFFSET
Definition: svw_sata.c:27
static VOID SvwSataLoadTaskFile(_In_ PCHANNEL_DATA_PATA ChanData, _In_ PATA_DEVICE_REQUEST Request)
Definition: svw_sata.c:124
static VOID SvwSataParseResources(_Inout_ PCHANNEL_DATA_PATA ChanData, _In_ PUCHAR IoBase, _In_ ULONG PortIndex)
Definition: svw_sata.c:193
#define SVW_SATA_PORT_DMA_OFFSET
Definition: svw_sata.c:29
static PCIIDEX_PAGED_DATA const struct @1176 SvwSataControllerList[]
static BOOLEAN SvwSataScrWrite(_In_ PCHANNEL_DATA_PATA ChanData, _In_ SATA_SCR_REGISTER Register, _In_ ULONG PortNumber, _In_ ULONG Value)
Definition: svw_sata.c:73
#define PCI_DEV_BCM5770R_SATA
Definition: svw_sata.c:21
#define PCI_DEV_K2_SATA
Definition: svw_sata.c:19
static BOOLEAN SvwSataScrRead(_In_ PCHANNEL_DATA_PATA ChanData, _In_ SATA_SCR_REGISTER Register, _In_ ULONG PortNumber, _In_ PULONG Result)
Definition: svw_sata.c:56
USHORT Flags
Definition: svw_sata.c:40
#define SVW_SATA_PORT_CONTROL_OFFSET
Definition: svw_sata.c:28
#define PCI_DEV_HT1000_SATA
Definition: svw_sata.c:22
#define HW_FLAGS_NO_ATAPI_DMA
Definition: svw_sata.c:34
static UCHAR SvwSataReadStatus(_In_ PCHANNEL_DATA_PATA ChanData)
Definition: svw_sata.c:112
#define SVW_SATA_PORT_SCR_OFFSET
Definition: svw_sata.c:30
USHORT DeviceID
Definition: svw_sata.c:39
#define HW_FLAGS_8_PORTS
Definition: svw_sata.c:33
static ULONG SvwSataGetIoBarIndex(_In_ PATA_CONTROLLER Controller)
Definition: svw_sata.c:91
#define PCI_DEV_HT1100_SATA_2
Definition: svw_sata.c:25
static BOOLEAN SvwSataCheckInterrupt(_In_ PCHANNEL_DATA_PATA ChanData)
Definition: svw_sata.c:99
#define PCI_DEV_BCM5770_SATA
Definition: svw_sata.c:20
NTSTATUS SvwSataGetControllerProperties(_Inout_ PATA_CONTROLLER Controller)
Definition: svw_sata.c:215
#define PCI_DEV_HT1000_SATA_2
Definition: svw_sata.c:23
uint32_t * PULONG
Definition: typedefs.h:59
unsigned char UCHAR
Definition: typedefs.h:53
uint16_t * PUSHORT
Definition: typedefs.h:56
uint32_t ULONG_PTR
Definition: typedefs.h:65
unsigned char * PUCHAR
Definition: typedefs.h:53
uint32_t ULONG
Definition: typedefs.h:59
_In_ WDFREQUEST Request
Definition: wdfdevice.h:547
_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
NTKERNELAPI VOID NTAPI WRITE_REGISTER_UCHAR(IN PUCHAR Register, IN UCHAR Value)
NTKERNELAPI UCHAR NTAPI READ_REGISTER_UCHAR(IN PUCHAR Register)