ReactOS 0.4.16-dev-2633-g8dc9e50
smart.c
Go to the documentation of this file.
1/*
2 * PROJECT: ReactOS ATA Port Driver
3 * LICENSE: MIT (https://spdx.org/licenses/MIT)
4 * PURPOSE: SMART Feature Set support
5 * COPYRIGHT: Copyright 2026 Dmitry Borisov <di.sean@protonmail.com>
6 */
7
8/* INCLUDES *******************************************************************/
9
10#include "atapi.h"
11
12/* FUNCTIONS ******************************************************************/
13
14static
15VOID
17 _In_ ATAPORT_DEVICE_EXTENSION* __restrict DevExt,
18 _In_ IDEREGS* __restrict IdeRegs,
20{
21 PATA_TASKFILE TaskFile = &Request->TaskFile;
22
23 TaskFile->Feature = IdeRegs->bFeaturesReg;
24 TaskFile->SectorCount = IdeRegs->bSectorCountReg;
25 TaskFile->LowLba = IdeRegs->bSectorNumberReg;
26 TaskFile->MidLba = IdeRegs->bCylLowReg;
27 TaskFile->HighLba = IdeRegs->bCylHighReg;
28 TaskFile->Command = IDE_COMMAND_SMART; // SMART_CMD
29
30 /* Set the master/slave bit to the correct value */
31 TaskFile->DriveSelect = IdeRegs->bDriveHeadReg & ~IDE_DRIVE_SELECT_SLAVE;
32 TaskFile->DriveSelect |= DevExt->Device.DeviceSelect & IDE_DRIVE_SELECT_SLAVE;
33}
34
35static
36VOID
39 _Out_ IDEREGS* __restrict IdeRegs)
40{
41 PATA_TASKFILE TaskFile = &Request->Output;
42
43 IdeRegs->bFeaturesReg = TaskFile->Feature;
44 IdeRegs->bSectorCountReg = TaskFile->SectorCount;
45 IdeRegs->bSectorNumberReg = TaskFile->LowLba;
46 IdeRegs->bCylLowReg = TaskFile->MidLba;
47 IdeRegs->bCylHighReg = TaskFile->HighLba;
48 IdeRegs->bCommandReg = TaskFile->Command;
49 IdeRegs->bDriveHeadReg = TaskFile->DriveSelect;
50}
51
52static
56{
57 PSENDCMDOUTPARAMS CmdOut;
58
59 CmdOut = (PSENDCMDOUTPARAMS)(((PUCHAR)Request->Srb->DataBuffer) + sizeof(SRB_IO_CONTROL));
60
61 if (Request->SrbStatus == SRB_STATUS_SUCCESS)
62 {
64 CmdOut->DriverStatus.bIDEError = 0;
65 }
66 else
67 {
69 CmdOut->DriverStatus.bIDEError = Request->Output.Error;
70 }
71
72 /* Return the SMART status */
74 {
76 {
77 PIDEREGS IdeRegs = (PIDEREGS)&CmdOut->bBuffer;
78
80 }
81 else
82 {
84 CmdOut->DriverStatus.bIDEError = Request->Output.Error;
85 }
86 }
87
88 return COMPLETE_IRP;
89}
90
96{
97 union _PARAMS
98 {
99 PSENDCMDINPARAMS CmdIn;
100 PSENDCMDOUTPARAMS CmdOut;
101 } Buffer;
102
103 if (Srb->DataTransferLength < (sizeof(SRB_IO_CONTROL) + sizeof(*Buffer.CmdIn) - 1))
105
107
108 if (Buffer.CmdIn->irDriveRegs.bCommandReg != SMART_CMD)
110
111 switch (Buffer.CmdIn->irDriveRegs.bFeaturesReg)
112 {
113 case READ_ATTRIBUTES:
114 {
115 Request->DataTransferLength = READ_ATTRIBUTE_BUFFER_SIZE;
117 break;
118 }
119
120 case READ_THRESHOLDS:
121 {
122 Request->DataTransferLength = READ_THRESHOLD_BUFFER_SIZE;
124 break;
125 }
126
127 case SMART_READ_LOG:
128 {
129 Request->DataTransferLength =
130 Buffer.CmdIn->irDriveRegs.bSectorCountReg * SMART_LOG_SECTOR_SIZE;
132 break;
133 }
134
135 case SMART_WRITE_LOG:
136 {
137 Request->DataTransferLength =
138 Buffer.CmdIn->irDriveRegs.bSectorCountReg * SMART_LOG_SECTOR_SIZE;
140 break;
141 }
142
144 {
145 Request->DataTransferLength = sizeof(IDEREGS);
147 break;
148 }
149
151 {
152 UCHAR Subcommand = Buffer.CmdIn->irDriveRegs.bSectorNumberReg;
153
154 if (Subcommand == SMART_SHORT_SELFTEST_CAPTIVE ||
156 {
158 }
159
161 }
164 case ENABLE_SMART:
165 case DISABLE_SMART:
167 {
168 Request->DataTransferLength = 0;
169 Request->Flags = 0;
170 break;
171 }
172
173 default:
175 }
176
178 {
180 (sizeof(SRB_IO_CONTROL) + sizeof(*Buffer.CmdOut) - 1 + Request->DataTransferLength))
181 {
183 }
184
185 Request->DataBuffer = Buffer.CmdOut->bBuffer;
186 }
187 else if (Request->Flags & REQUEST_FLAG_DATA_OUT)
188 {
190 (sizeof(SRB_IO_CONTROL) + sizeof(*Buffer.CmdIn) - 1 + Request->DataTransferLength))
191 {
193 }
194
195 Request->DataBuffer = Buffer.CmdIn->bBuffer;
196 }
197
199
200 AtaIdeRegsToTaskFile(DevExt, &Buffer.CmdIn->irDriveRegs, Request);
201
202 return SRB_STATUS_PENDING;
203}
204
205CODE_SEG("PAGE")
210{
211 union _PARAMS
212 {
213 PSENDCMDINPARAMS CmdIn;
214 PSENDCMDOUTPARAMS CmdOut;
215 } Buffer;
216
217 PAGED_CODE();
218
220 (sizeof(SRB_IO_CONTROL) + sizeof(*Buffer.CmdOut) - 1 + IDENTIFY_BUFFER_SIZE))
221 {
224 }
225
227
228 if (IS_ATAPI(&DevExt->Device) || (Buffer.CmdIn->irDriveRegs.bCommandReg != ID_CMD))
229 {
232 }
233
234 Buffer.CmdOut->cBufferSize = IDENTIFY_BUFFER_SIZE;
235 Buffer.CmdOut->DriverStatus.bDriverError = 0;
236 Buffer.CmdOut->DriverStatus.bIDEError = 0;
237
238 RtlCopyMemory(Buffer.CmdOut->bBuffer, &DevExt->IdentifyDeviceData, IDENTIFY_BUFFER_SIZE);
239
241 return STATUS_SUCCESS;
242}
243
244CODE_SEG("PAGE")
249{
250 PATAPORT_CHANNEL_EXTENSION ChanExt = DevExt->Common.FdoExt;
251 PATAPORT_PORT_DATA PortData = &ChanExt->PortData;
252 PGETVERSIONINPARAMS VersionParameters;
253 ULONG i;
254
255 PAGED_CODE();
256
257 if (Srb->DataTransferLength < (sizeof(*VersionParameters) + sizeof(SRB_IO_CONTROL)))
258 {
261 }
262
263 VersionParameters = (PGETVERSIONINPARAMS)(((PUCHAR)Srb->DataBuffer) + sizeof(SRB_IO_CONTROL));
264
265 /* SMART 1.03 */
266 VersionParameters->bVersion = 1;
267 VersionParameters->bRevision = 1;
268 VersionParameters->bReserved = 0;
269
271
272 VersionParameters->bIDEDeviceMap = 0;
273
274 /* Emulate the PATA behavior */
275 for (i = 0; i < MAX_IDE_DEVICE; ++i)
276 {
278 ULONG DeviceFlag;
279
280 DevExt = AtaFdoFindDeviceByPath(ChanExt,
281 AtaMarshallScsiAddress(PortData->PortNumber, i, 0),
282 Srb);
283 if (!DevExt)
284 continue;
285
286 DeviceFlag = 1 << i;
287 if (PortData->PortNumber != 0)
288 DeviceFlag <<= 2;
289 if (IS_ATAPI(&DevExt->Device))
290 DeviceFlag <<= 4;
291 VersionParameters->bIDEDeviceMap |= DeviceFlag;
292
294 }
295
297 return STATUS_SUCCESS;
298}
#define PAGED_CODE()
#define CODE_SEG(...)
#define IDE_COMMAND_SMART
Definition: ata.h:681
ATA_COMPLETION_ACTION
Definition: ata_shared.h:148
@ COMPLETE_IRP
Definition: ata_shared.h:149
#define REQUEST_FLAG_DATA_IN
Definition: ata_shared.h:287
#define REQUEST_FLAG_DATA_OUT
Definition: ata_shared.h:290
#define REQUEST_FLAG_SAVE_TASK_FILE
Definition: ata_shared.h:309
#define REQUEST_FLAG_HAS_TASK_FILE
Definition: ata_shared.h:312
FORCEINLINE ATA_SCSI_ADDRESS AtaMarshallScsiAddress(_In_ ULONG PathId, _In_ ULONG TargetId, _In_ ULONG Lun)
Definition: atapi.h:585
DECLSPEC_NOINLINE_FROM_PAGED PATAPORT_DEVICE_EXTENSION AtaFdoFindDeviceByPath(_In_ PATAPORT_CHANNEL_EXTENSION ChanExt, _In_ ATA_SCSI_ADDRESS AtaScsiAddress, _In_ PVOID ReferenceTag)
Definition: fdo.c:614
#define IDE_DRIVE_SELECT_SLAVE
Definition: atapi.h:212
#define IS_ATAPI(Device)
Definition: atapi.h:176
struct _IDEREGS * PIDEREGS
#define ID_CMD
Definition: helper.h:20
#define SMART_CMD
Definition: helper.h:21
struct _IDEREGS IDEREGS
struct _SENDCMDOUTPARAMS * PSENDCMDOUTPARAMS
struct _SENDCMDINPARAMS * PSENDCMDINPARAMS
LONG NTSTATUS
Definition: precomp.h:26
_In_ PSCSI_REQUEST_BLOCK Srb
Definition: cdrom.h:989
Definition: bufpool.h:45
#define SRB_STATUS_PENDING
Definition: srb.h:340
#define SRB_STATUS_SUCCESS
Definition: srb.h:341
#define SRB_STATUS_INVALID_REQUEST
Definition: srb.h:346
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 MAX_IDE_DEVICE
Definition: ide.h:32
#define _Out_
Definition: no_sal2.h:160
#define _In_
Definition: no_sal2.h:158
#define SMART_WRITE_LOG
Definition: ntdddisk.h:745
#define EXECUTE_OFFLINE_DIAGS
Definition: ntdddisk.h:743
#define CAP_ATAPI_ID_CMD
Definition: ntdddisk.h:657
#define READ_ATTRIBUTE_BUFFER_SIZE
Definition: ntdddisk.h:726
#define ENABLE_SMART
Definition: ntdddisk.h:746
#define SMART_SHORT_SELFTEST_CAPTIVE
Definition: ntdddisk.h:716
#define SAVE_ATTRIBUTE_VALUES
Definition: ntdddisk.h:742
#define RETURN_SMART_STATUS
Definition: ntdddisk.h:748
#define READ_THRESHOLDS
Definition: ntdddisk.h:740
#define IDENTIFY_BUFFER_SIZE
Definition: ntdddisk.h:727
#define SMART_READ_LOG
Definition: ntdddisk.h:744
#define SMART_LOG_SECTOR_SIZE
Definition: ntdddisk.h:729
#define SMART_IDE_ERROR
Definition: ntdddisk.h:701
#define DISABLE_SMART
Definition: ntdddisk.h:747
#define SMART_EXTENDED_SELFTEST_CAPTIVE
Definition: ntdddisk.h:717
#define ENABLE_DISABLE_AUTO_OFFLINE
Definition: ntdddisk.h:749
#define READ_ATTRIBUTES
Definition: ntdddisk.h:739
struct _GETVERSIONINPARAMS * PGETVERSIONINPARAMS
#define CAP_ATA_ID_CMD
Definition: ntdddisk.h:656
#define READ_THRESHOLD_BUFFER_SIZE
Definition: ntdddisk.h:728
#define ENABLE_DISABLE_AUTOSAVE
Definition: ntdddisk.h:741
#define SMART_NO_ERROR
Definition: ntdddisk.h:700
#define CAP_SMART_CMD
Definition: ntdddisk.h:658
#define __fallthrough
Definition: sal_old.h:314
struct _SRB_IO_CONTROL SRB_IO_CONTROL
#define STATUS_SUCCESS
Definition: shellext.h:65
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:69
static VOID AtaTaskFileToIdeRegs(_In_ ATA_DEVICE_REQUEST *__restrict Request, _Out_ IDEREGS *__restrict IdeRegs)
Definition: smart.c:37
static VOID AtaIdeRegsToTaskFile(_In_ ATAPORT_DEVICE_EXTENSION *__restrict DevExt, _In_ IDEREGS *__restrict IdeRegs, _Out_ ATA_DEVICE_REQUEST *__restrict Request)
Definition: smart.c:16
static ATA_COMPLETION_ACTION AtaReqCompleteSmartIoControl(_In_ PATA_DEVICE_REQUEST Request)
Definition: smart.c:54
NTSTATUS AtaPdoHandleMiniportSmartVersion(_In_ PATAPORT_DEVICE_EXTENSION DevExt, _In_ PSCSI_REQUEST_BLOCK Srb)
Definition: smart.c:246
UCHAR AtaReqSmartIoControl(_In_ PATAPORT_DEVICE_EXTENSION DevExt, _In_ PATA_DEVICE_REQUEST Request, _In_ PSCSI_REQUEST_BLOCK Srb)
Definition: smart.c:92
NTSTATUS AtaPdoHandleMiniportIdentify(_In_ PATAPORT_DEVICE_EXTENSION DevExt, _In_ PSCSI_REQUEST_BLOCK Srb)
Definition: smart.c:207
ATAPORT_PORT_DATA PortData
Definition: atapi.h:442
ATAPORT_COMMON_EXTENSION Common
Definition: atapi.h:440
IO_REMOVE_LOCK RemoveLock
Definition: atapi.h:434
ATAPORT_IO_CONTEXT Device
Definition: atapi.h:457
ATAPORT_COMMON_EXTENSION Common
Definition: atapi.h:455
ULONG PortNumber
Definition: atapi.h:396
UCHAR SectorCount
Definition: hwidep.h:151
UCHAR Feature
Definition: hwidep.h:150
UCHAR MidLba
LBA bits 8-15.
Definition: hwidep.h:153
UCHAR HighLba
LBA bits 16-23.
Definition: hwidep.h:154
UCHAR Command
Definition: hwidep.h:147
UCHAR DriveSelect
Definition: hwidep.h:146
UCHAR LowLba
LBA bits 0-7.
Definition: hwidep.h:152
UCHAR bIDEError
Definition: helper.h:3
UCHAR bDriverError
Definition: helper.h:2
Definition: helper.h:8
PVOID DataBuffer
Definition: srb.h:263
ULONG DataTransferLength
Definition: srb.h:261
UCHAR SrbStatus
Definition: srb.h:251
UCHAR bBuffer[1]
Definition: helper.h:27
DRIVERSTATUS DriverStatus
Definition: helper.h:26
unsigned char UCHAR
Definition: typedefs.h:53
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
unsigned char * PUCHAR
Definition: typedefs.h:53
uint32_t ULONG
Definition: typedefs.h:59
#define STATUS_INVALID_DEVICE_REQUEST
Definition: udferr_usr.h:138
_In_ WDFREQUEST Request
Definition: wdfdevice.h:547
#define IoReleaseRemoveLock(_RemoveLock, _Tag)
Definition: iofuncs.h:2764