ReactOS 0.4.16-dev-2633-g8dc9e50
pata_io.c File Reference
#include "pciidex.h"
Include dependency graph for pata_io.c:

Go to the source code of this file.

Functions

VOID AtaWriteBlock16 (_In_ PUSHORT Port, _In_ PUSHORT Buffer, _In_ ULONG Count, _In_ ULONG MmioFlags)
 
VOID AtaReadBlock16 (_In_ PUSHORT Port, _In_ PUSHORT Buffer, _In_ ULONG Count, _In_ ULONG MmioFlags)
 
VOID AtaWriteBlock32 (_In_ PULONG Port, _In_ PULONG Buffer, _In_ ULONG Count, _In_ ULONG MmioFlags)
 
VOID AtaReadBlock32 (_In_ PULONG Port, _In_ PULONG Buffer, _In_ ULONG Count, _In_ ULONG MmioFlags)
 
UCHAR AtaReadPortUchar (_In_ PUCHAR Port, _In_ ULONG MmioFlags)
 
VOID AtaWritePortUchar (_In_ PUCHAR Port, _In_ UCHAR Value, _In_ ULONG MmioFlags)
 
VOID AtaWritePortUlong (_In_ PULONG Port, _In_ ULONG Value, _In_ ULONG MmioFlags)
 
VOID PataSaveTaskFile (_In_ PCHANNEL_DATA_PATA ChanData, _Inout_ PATA_DEVICE_REQUEST Request)
 
UCHAR PataReadStatus (_In_ PCHANNEL_DATA_PATA ChanData)
 
static VOID PataCompleteCommand (_In_ PCHANNEL_DATA_PATA ChanData, _In_ UCHAR IdeStatus, _In_ UCHAR SrbStatus)
 
static UCHAR PciIdeDmaReadStatus (_In_ PCHANNEL_DATA_PATA ChanData)
 
static VOID PciIdeDmaPrepare (_In_ PCHANNEL_DATA_PATA ChanData)
 
static VOID PciIdeDmaStart (_In_ PCHANNEL_DATA_PATA ChanData, _In_ PATA_DEVICE_REQUEST Request)
 
VOID PciIdeDmaStop (_In_ PCHANNEL_DATA_PATA ChanData)
 
static VOID PciIdeDmaClearInterrupt (_In_ PCHANNEL_DATA_PATA ChanData, _In_ UCHAR DmaStatus)
 
static VOID PataChangeInterruptMode (_In_ PCHANNEL_DATA_PATA ChanData, _In_ PATA_IO_CONTEXT_COMMON Device, _In_ PATA_DEVICE_REQUEST Request)
 
static VOID PataSendCdb (_In_ PCHANNEL_DATA_PATA ChanData, _In_ PATA_DEVICE_REQUEST Request)
 
static VOID PataPioDataIn (_In_ PCHANNEL_DATA_PATA ChanData, _In_ ULONG ByteCount)
 
static VOID PataPioDataOut (_In_ PCHANNEL_DATA_PATA ChanData, _In_ ULONG ByteCount)
 
static UCHAR PataProcessAtapiRequest (_In_ PCHANNEL_DATA_PATA ChanData, _In_ PATA_DEVICE_REQUEST Request, _In_ UCHAR IdeStatus)
 
static UCHAR PataProcessAtaRequest (_In_ PCHANNEL_DATA_PATA ChanData, _In_ PATA_DEVICE_REQUEST Request, _In_ UCHAR IdeStatus)
 
static BOOLEAN PataProcessRequest (_In_ PCHANNEL_DATA_PATA ChanData, _In_ UCHAR IdeStatus, _In_ UCHAR DmaStatus)
 
VOID PataLoadTaskFile (_In_ PCHANNEL_DATA_PATA ChanData, _In_ PATA_DEVICE_REQUEST Request)
 
static BOOLEAN PataExecutePacketCommand (_In_ PCHANNEL_DATA_PATA ChanData, _In_ PATA_IO_CONTEXT_COMMON Device, _In_ PATA_DEVICE_REQUEST Request)
 
static BOOLEAN PataExecuteAtaCommand (_In_ PCHANNEL_DATA_PATA ChanData, _In_ PATA_IO_CONTEXT_COMMON Device, _In_ PATA_DEVICE_REQUEST Request)
 
BOOLEAN PataStartIo (_In_ PVOID ChannelContext, _In_ PATA_DEVICE_REQUEST Request)
 
VOID PataPrepareIo (_In_ PVOID ChannelContext, _In_ PATA_DEVICE_REQUEST Request)
 
VOID PciIdePreparePrdTable (_In_ PVOID ChannelContext, _In_ PATA_DEVICE_REQUEST Request, _In_ SCATTER_GATHER_LIST *__restrict SgList)
 
BOOLEAN PataAllocateSlot (_In_ PVOID ChannelContext, _In_ PATA_DEVICE_REQUEST Request, _In_ BOOLEAN Allocate)
 
BOOLEAN NTAPI PciIdeChannelIsr (_In_ PKINTERRUPT Interrupt, _In_ PVOID Context)
 
BOOLEAN NTAPI PataChannelIsr (_In_ PKINTERRUPT Interrupt, _In_ PVOID Context)
 
BOOLEAN PciIdeCheckInterrupt (_In_ PCHANNEL_DATA_PATA ChanData)
 
static BOOLEAN PataPoll (_In_ PCHANNEL_DATA_PATA ChanData)
 
VOID NTAPI PataPollingTimerDpc (_In_ PKDPC Dpc, _In_opt_ PVOID DeferredContext, _In_opt_ PVOID SystemArgument1, _In_opt_ PVOID SystemArgument2)
 

Function Documentation

◆ AtaReadBlock16()

VOID AtaReadBlock16 ( _In_ PUSHORT  Port,
_In_ PUSHORT  Buffer,
_In_ ULONG  Count,
_In_ ULONG  MmioFlags 
)

Definition at line 31 of file pata_io.c.

36{
37 ASSERT(Buffer != NULL);
38 ASSERT(Count != 0);
39
40 if (MmioFlags)
42 else
44}
#define READ_PORT_BUFFER_USHORT(port, buffer, count)
Definition: hardware.h:31
Definition: bufpool.h:45
#define NULL
Definition: types.h:112
CPPORT Port[4]
Definition: headless.c:38
#define ASSERT(a)
Definition: mode.c:44
int Count
Definition: noreturn.cpp:7
NTKERNELAPI VOID NTAPI READ_REGISTER_BUFFER_USHORT(IN PUSHORT Register, IN PUSHORT Buffer, IN ULONG Count)

◆ AtaReadBlock32()

VOID AtaReadBlock32 ( _In_ PULONG  Port,
_In_ PULONG  Buffer,
_In_ ULONG  Count,
_In_ ULONG  MmioFlags 
)

Definition at line 63 of file pata_io.c.

68{
69 ASSERT(Buffer != NULL);
70 ASSERT(Count != 0);
71
72 if (MmioFlags)
74 else
76}
#define READ_PORT_BUFFER_ULONG(port, buffer, count)
Definition: hardware.h:32
NTKERNELAPI VOID NTAPI READ_REGISTER_BUFFER_ULONG(IN PULONG Register, IN PULONG Buffer, IN ULONG Count)

◆ AtaReadPortUchar()

UCHAR AtaReadPortUchar ( _In_ PUCHAR  Port,
_In_ ULONG  MmioFlags 
)

Definition at line 79 of file pata_io.c.

82{
83 if (MmioFlags)
85 else
86 return READ_PORT_UCHAR(Port);
87}
#define READ_PORT_UCHAR(p)
Definition: pc98vid.h:22
NTKERNELAPI UCHAR NTAPI READ_REGISTER_UCHAR(IN PUCHAR Register)

◆ AtaWriteBlock16()

VOID AtaWriteBlock16 ( _In_ PUSHORT  Port,
_In_ PUSHORT  Buffer,
_In_ ULONG  Count,
_In_ ULONG  MmioFlags 
)

Definition at line 15 of file pata_io.c.

20{
21 ASSERT(Buffer != NULL);
22 ASSERT(Count != 0);
23
24 if (MmioFlags)
26 else
28}
#define WRITE_PORT_BUFFER_USHORT(port, buffer, count)
Definition: hardware.h:34
NTKERNELAPI VOID NTAPI WRITE_REGISTER_BUFFER_USHORT(IN PUSHORT Register, IN PUSHORT Buffer, IN ULONG Count)

◆ AtaWriteBlock32()

VOID AtaWriteBlock32 ( _In_ PULONG  Port,
_In_ PULONG  Buffer,
_In_ ULONG  Count,
_In_ ULONG  MmioFlags 
)

Definition at line 47 of file pata_io.c.

52{
53 ASSERT(Buffer != NULL);
54 ASSERT(Count != 0);
55
56 if (MmioFlags)
58 else
60}
#define WRITE_PORT_BUFFER_ULONG(port, buffer, count)
Definition: hardware.h:35
NTKERNELAPI VOID NTAPI WRITE_REGISTER_BUFFER_ULONG(IN PULONG Register, IN PULONG Buffer, IN ULONG Count)

◆ AtaWritePortUchar()

VOID AtaWritePortUchar ( _In_ PUCHAR  Port,
_In_ UCHAR  Value,
_In_ ULONG  MmioFlags 
)

Definition at line 90 of file pata_io.c.

94{
95 if (MmioFlags)
97 else
99}
#define WRITE_PORT_UCHAR(p, d)
Definition: pc98vid.h:21
_Must_inspect_result_ _In_ WDFKEY _In_ PCUNICODE_STRING _Out_opt_ PUSHORT _Inout_opt_ PUNICODE_STRING Value
Definition: wdfregistry.h:413
NTKERNELAPI VOID NTAPI WRITE_REGISTER_UCHAR(IN PUCHAR Register, IN UCHAR Value)

◆ AtaWritePortUlong()

VOID AtaWritePortUlong ( _In_ PULONG  Port,
_In_ ULONG  Value,
_In_ ULONG  MmioFlags 
)

Definition at line 102 of file pata_io.c.

106{
107 if (MmioFlags)
109 else
111}
#define WRITE_REGISTER_ULONG(r, v)
Definition: arm.h:11
VOID NTAPI WRITE_PORT_ULONG(IN PULONG Port, IN ULONG Value)
Definition: portio.c:123

◆ PataAllocateSlot()

BOOLEAN PataAllocateSlot ( _In_ PVOID  ChannelContext,
_In_ PATA_DEVICE_REQUEST  Request,
_In_ BOOLEAN  Allocate 
)

Definition at line 1044 of file pata_io.c.

1048{
1049 UNREFERENCED_PARAMETER(ChannelContext);
1052
1053 return TRUE;
1054}
_In_ PATA_DEVICE_REQUEST _In_ BOOLEAN Allocate
Definition: ata_shared.h:437
#define TRUE
Definition: types.h:120
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:329
_In_ WDFREQUEST Request
Definition: wdfdevice.h:547

◆ PataChangeInterruptMode()

static VOID PataChangeInterruptMode ( _In_ PCHANNEL_DATA_PATA  ChanData,
_In_ PATA_IO_CONTEXT_COMMON  Device,
_In_ PATA_DEVICE_REQUEST  Request 
)
static

Definition at line 271 of file pata_io.c.

275{
277
278 if (Request->Flags & REQUEST_FLAG_POLL)
279 {
280 ChanData->IsPollingActive = TRUE;
282 }
283 else
284 {
285 ChanData->IsPollingActive = FALSE;
286 Control = 0;
287 }
288 TRACE("Interrupt mode %s\n", Control ? "disable" : "enable");
289
290 ATA_WRITE(ChanData->Regs.Control, Control | IDE_DC_ALWAYS, ChanData, MRES_CTRL);
291
292 /* Seems to be needed */
293 ATA_IO_WAIT();
294
295 /* Workaround for VIA chipsets that reset the DEV bit after interrupt mode change */
296 if (ChanData->Controller->Pci.VendorID == PCI_VEN_VIA)
297 {
298 ATA_SELECT_DEVICE(ChanData, DEV_NUMBER(Device), Device->DeviceSelect);
300 }
301}
#define REQUEST_FLAG_POLL
Definition: ata_shared.h:353
#define IDE_STATUS_BUSY
Definition: atapi.h:132
#define IDE_DC_DISABLE_INTERRUPTS
Definition: atapi.h:145
#define FALSE
Definition: types.h:117
#define ATA_IO_WAIT()
Definition: hwidep.h:39
#define ATA_WRITE(Port, Value)
Definition: hwidep.h:80
#define IDE_DC_ALWAYS
Definition: hwidep.h:54
#define ATA_TIME_BUSY_SELECT
20 ms
Definition: hwidep.h:69
#define PCI_VEN_VIA
Definition: pata.h:15
FORCEINLINE VOID ATA_SELECT_DEVICE(_In_ PCHANNEL_DATA_PATA ChanData, _In_ UCHAR DeviceNumber, _In_ UCHAR DeviceSelect)
Definition: pata.h:271
FORCEINLINE UCHAR ATA_WAIT(_In_ PCHANNEL_DATA_PATA ChanData, _In_range_(>, 0) ULONG Timeout, _In_ UCHAR Mask, _In_ UCHAR Value)
Definition: pata.h:301
#define DEV_NUMBER(Device)
Definition: pciidex.h:56
#define TRACE(s)
Definition: solgame.cpp:4
unsigned char UCHAR
Definition: typedefs.h:53
_Must_inspect_result_ _In_ WDFDEVICE Device
Definition: wdfchildlist.h:474
_In_ WDF_WMI_PROVIDER_CONTROL Control
Definition: wdfwmi.h:166

Referenced by PataStartIo().

◆ PataChannelIsr()

BOOLEAN NTAPI PataChannelIsr ( _In_ PKINTERRUPT  Interrupt,
_In_ PVOID  Context 
)

Definition at line 1114 of file pata_io.c.

1117{
1118 PCHANNEL_DATA_PATA ChanData = Context;
1119 UCHAR IdeStatus;
1120
1122
1123 if (ChanData->CheckInterrupt && !(ChanData->CheckInterrupt(ChanData)))
1124 return FALSE;
1125
1126 /* Acknowledge the IDE interrupt */
1127 IdeStatus = ChanData->ReadStatus(ChanData);
1128
1129 /* This interrupt is spurious or not ours */
1130 if (!(ChanData->ActiveSlotsBitmap & (1 << PATA_CHANNEL_SLOT)) ||
1131 !(ChanData->CommandFlags & CMD_FLAG_AWAIT_INTERRUPT) ||
1132 (IdeStatus & IDE_STATUS_BUSY))
1133 {
1134 WARN("Spurious IDE interrupt %02x, flags %08lx\n", IdeStatus, ChanData->CommandFlags);
1135 return FALSE;
1136 }
1137
1138 PataProcessRequest(ChanData, IdeStatus, 0);
1139 return TRUE;
1140}
#define WARN(fmt,...)
Definition: precomp.h:61
#define PATA_CHANNEL_SLOT
Definition: pata.h:193
#define CMD_FLAG_AWAIT_INTERRUPT
Definition: pata.h:186
static BOOLEAN PataProcessRequest(_In_ PCHANNEL_DATA_PATA ChanData, _In_ UCHAR IdeStatus, _In_ UCHAR DmaStatus)
Definition: pata_io.c:719
_In_ PVOID Context
Definition: storport.h:2269
PCHANNEL_CHECK_INTERRUPT CheckInterrupt
Definition: pciidex.h:303
PCHANNEL_READ_STATUS ReadStatus
Definition: pciidex.h:299
ULONG CommandFlags
Definition: pciidex.h:306
_Must_inspect_result_ _In_ WDFDEVICE _In_ PWDF_INTERRUPT_CONFIG _In_opt_ PWDF_OBJECT_ATTRIBUTES _Out_ WDFINTERRUPT * Interrupt
Definition: wdfinterrupt.h:379

◆ PataCompleteCommand()

static VOID PataCompleteCommand ( _In_ PCHANNEL_DATA_PATA  ChanData,
_In_ UCHAR  IdeStatus,
_In_ UCHAR  SrbStatus 
)
static

Definition at line 154 of file pata_io.c.

158{
160
161 Request->SrbStatus = SrbStatus;
162
163 /* Handle failed commands */
164 if (SrbStatus != SRB_STATUS_SUCCESS && SrbStatus != SRB_STATUS_DATA_OVERRUN)
165 {
166 if (!(Request->Device->TransportFlags & DEVICE_IS_ATAPI) ||
168 {
169 /* Save the current task file for the "ATA LBA field" (SAT-6 11.7) */
170 ChanData->SaveTaskFile(ChanData, Request);
172 }
173 else
174 {
175 Request->Output.Status = IdeStatus;
176 Request->Output.Error = ATA_READ(ChanData->Regs.Error, ChanData, MRES_TF);
177 }
178
179 /* Request arbitration from the port worker */
180 ChanData->PortNotification(AtaRequestFailed, ChanData->PortContext, Request);
181 return;
182 }
183
184 ChanData->ActiveSlotsBitmap &= ~(1 << PATA_CHANNEL_SLOT);
185
186 /* Save the latest copy of the task file registers */
188 {
189 ChanData->SaveTaskFile(ChanData, Request);
191 }
192
193 ChanData->PortNotification(AtaRequestComplete, ChanData->PortContext, 1 << PATA_CHANNEL_SLOT);
194}
#define REQUEST_FLAG_SAVE_TASK_FILE
Definition: ata_shared.h:309
#define DEVICE_IS_ATAPI
Definition: ata_shared.h:165
#define REQUEST_FLAG_HAS_TASK_FILE
Definition: ata_shared.h:312
@ AtaRequestFailed
Definition: ata_shared.h:77
@ AtaRequestComplete
Definition: ata_shared.h:74
#define SRB_STATUS_DATA_OVERRUN
Definition: srb.h:357
#define SRB_STATUS_SUCCESS
Definition: srb.h:341
#define ATA_READ(Port)
Definition: hwidep.h:89

Referenced by PataProcessRequest(), and PataStartIo().

◆ PataExecuteAtaCommand()

static BOOLEAN PataExecuteAtaCommand ( _In_ PCHANNEL_DATA_PATA  ChanData,
_In_ PATA_IO_CONTEXT_COMMON  Device,
_In_ PATA_DEVICE_REQUEST  Request 
)
static

Definition at line 847 of file pata_io.c.

851{
852 ULONG CommandFlags, BlockCount;
853
854 if ((ChanData->ChanInfo & CHANNEL_FLAG_DMA_BEFORE_CMD) && (Request->Flags & REQUEST_FLAG_DMA))
855 PciIdeDmaStart(ChanData, Request);
856
857 ChanData->LoadTaskFile(ChanData, Request);
858
859 ATA_WRITE(ChanData->Regs.Command, Request->TaskFile.Command, ChanData, MRES_TF);
860
861 CommandFlags = (Request->Flags & (REQUEST_FLAG_DATA_IN | REQUEST_FLAG_DATA_OUT));
862 CommandFlags |= ~Request->Flags & REQUEST_FLAG_POLL;
863
864 /* DMA transfer */
865 if (Request->Flags & REQUEST_FLAG_DMA)
866 {
867 ChanData->CommandFlags = CommandFlags | CMD_FLAG_DMA_TRANSFER;
868
869 /* Start the DMA engine */
870 PciIdeDmaStart(ChanData, Request);
871 return FALSE;
872 }
873
874 /* PIO transfer */
875 ChanData->CommandFlags = CommandFlags | CMD_FLAG_ATA_PIO_TRANSFER;
876
877 /* Set the byte count per DRQ data block */
879 BlockCount = Device->MultiSectorCount;
880 else
881 BlockCount = 1;
882 ChanData->DrqByteCount = BlockCount * Device->SectorSize;
883
884 /*
885 * For PIO writes we need to send the first data block
886 * to make the device start generating interrupts.
887 */
888 if (Request->Flags & REQUEST_FLAG_DATA_OUT)
889 return TRUE;
890
891 return FALSE;
892}
#define REQUEST_FLAG_DATA_IN
Definition: ata_shared.h:287
#define REQUEST_FLAG_DATA_OUT
Definition: ata_shared.h:290
#define REQUEST_FLAG_DMA
Definition: ata_shared.h:278
#define REQUEST_FLAG_READ_WRITE_MULTIPLE
Definition: hwidep.h:168
#define CMD_FLAG_ATA_PIO_TRANSFER
Definition: pata.h:189
#define CMD_FLAG_DMA_TRANSFER
Definition: pata.h:190
static VOID PciIdeDmaStart(_In_ PCHANNEL_DATA_PATA ChanData, _In_ PATA_DEVICE_REQUEST Request)
Definition: pata_io.c:227
#define CHANNEL_FLAG_DMA_BEFORE_CMD
Definition: pciidex.h:279
uint32_t ULONG
Definition: typedefs.h:59

Referenced by PataStartIo().

◆ PataExecutePacketCommand()

static BOOLEAN PataExecutePacketCommand ( _In_ PCHANNEL_DATA_PATA  ChanData,
_In_ PATA_IO_CONTEXT_COMMON  Device,
_In_ PATA_DEVICE_REQUEST  Request 
)
static

Definition at line 806 of file pata_io.c.

810{
811 ULONG CommandFlags;
813 UCHAR Features;
814
815 CommandFlags = (Request->Flags & (REQUEST_FLAG_DATA_IN | REQUEST_FLAG_DATA_OUT));
816 CommandFlags |= ~Request->Flags & REQUEST_FLAG_POLL;
818 ChanData->CommandFlags = CommandFlags;
819
820 /* Prepare to transfer a device command */
821 if (Request->Flags & REQUEST_FLAG_DMA)
822 {
823 /* DMA transfer */
824 ByteCount = 0;
825 Features = IDE_FEATURE_DMA;
826 }
827 else
828 {
829 /* PIO transfer */
830 ByteCount = min(ChanData->BytesToTransfer, ATAPI_MAX_DRQ_DATA_BLOCK);
831 Features = IDE_FEATURE_PIO;
832 }
833 ATA_WRITE(ChanData->Regs.ByteCountLow, (UCHAR)(ByteCount >> 0), ChanData, MRES_TF);
834 ATA_WRITE(ChanData->Regs.ByteCountHigh, (UCHAR)(ByteCount >> 8), ChanData, MRES_TF);
835 ATA_WRITE(ChanData->Regs.Features, Features, ChanData, MRES_TF);
836 ATA_WRITE(ChanData->Regs.Command, IDE_COMMAND_ATAPI_PACKET, ChanData, MRES_TF);
837
838 /* Wait for an interrupt that signals that device is ready to accept the command packet */
839 if (Device->TransportFlags & DEVICE_HAS_CDB_INTERRUPT)
840 return FALSE;
841
842 return TRUE;
843}
#define DEVICE_HAS_CDB_INTERRUPT
Definition: ata_shared.h:166
#define IDE_FEATURE_DMA
Definition: atapi.h:219
#define IDE_COMMAND_ATAPI_PACKET
Definition: atapi.h:109
#define IDE_FEATURE_PIO
Definition: hwidep.h:52
#define min(a, b)
Definition: monoChain.cc:55
#define ATAPI_MAX_DRQ_DATA_BLOCK
Definition: pata.h:65
#define CMD_FLAG_ATAPI_PIO_TRANSFER
Definition: pata.h:188
#define CMD_FLAG_AWAIT_CDB
Definition: pata.h:183
unsigned short USHORT
Definition: pedump.c:61
_Must_inspect_result_ typedef _In_ PHYSICAL_ADDRESS _In_ LARGE_INTEGER ByteCount
Definition: iotypes.h:1099

Referenced by PataStartIo().

◆ PataLoadTaskFile()

VOID PataLoadTaskFile ( _In_ PCHANNEL_DATA_PATA  ChanData,
_In_ PATA_DEVICE_REQUEST  Request 
)

Definition at line 778 of file pata_io.c.

781{
782 if (Request->Flags & REQUEST_FLAG_LBA48)
783 {
784 ATA_WRITE(ChanData->Regs.Features, Request->TaskFile.FeatureEx, ChanData, MRES_TF);
785 ATA_WRITE(ChanData->Regs.SectorCount, Request->TaskFile.SectorCountEx, ChanData, MRES_TF);
786 ATA_WRITE(ChanData->Regs.LbaLow, Request->TaskFile.LowLbaEx, ChanData, MRES_TF);
787 ATA_WRITE(ChanData->Regs.LbaMid, Request->TaskFile.MidLbaEx, ChanData, MRES_TF);
788 ATA_WRITE(ChanData->Regs.LbaHigh, Request->TaskFile.HighLbaEx, ChanData, MRES_TF);
789
790 /* Store the extra information in the second byte of FIFO: */
791 }
792 ATA_WRITE(ChanData->Regs.Features, Request->TaskFile.Feature, ChanData, MRES_TF);
793 ATA_WRITE(ChanData->Regs.SectorCount, Request->TaskFile.SectorCount, ChanData, MRES_TF);
794 ATA_WRITE(ChanData->Regs.LbaLow, Request->TaskFile.LowLba, ChanData, MRES_TF);
795 ATA_WRITE(ChanData->Regs.LbaMid, Request->TaskFile.MidLba, ChanData, MRES_TF);
796 ATA_WRITE(ChanData->Regs.LbaHigh, Request->TaskFile.HighLba, ChanData, MRES_TF);
797
799 {
800 ATA_WRITE(ChanData->Regs.Device, Request->TaskFile.DriveSelect, ChanData, MRES_TF);
801 }
802}
#define REQUEST_FLAG_LBA48
Definition: hwidep.h:167
#define REQUEST_FLAG_SET_DEVICE_REGISTER
Definition: hwidep.h:170

◆ PataPioDataIn()

static VOID PataPioDataIn ( _In_ PCHANNEL_DATA_PATA  ChanData,
_In_ ULONG  ByteCount 
)
static

Definition at line 330 of file pata_io.c.

333{
334 ByteCount = min(ByteCount, ChanData->BytesToTransfer);
335
336 TRACE("Read block %lu %lu %p\n",
337 ByteCount, ChanData->BytesToTransfer, ChanData->DataBuffer);
338
339 /* Transfer the data block */
340 if (!(ByteCount & (sizeof(ULONG) - 1)) &&
341 (ChanData->ChanInfo & CHANNEL_FLAG_IO32))
342 {
343 ATA_READ_BLOCK_32((PULONG)ChanData->Regs.Data,
344 (PULONG)ChanData->DataBuffer,
345 ByteCount / sizeof(ULONG),
346 ChanData,
347 MRES_TF);
348 }
349 else
350 {
351 ATA_READ_BLOCK_16((PUSHORT)ChanData->Regs.Data,
352 (PUSHORT)ChanData->DataBuffer,
353 ByteCount / sizeof(USHORT),
354 ChanData,
355 MRES_TF);
356
357 /* Read one last byte */
358 if (ByteCount & (sizeof(USHORT) - 1))
359 {
360 DECLSPEC_ALIGN(2) UCHAR LocalBuffer[2];
362
363 /* Some hardware (Intel SCH) always expect 16- or 32-bit accesses for the data port */
364 ATA_READ_BLOCK_16((PUSHORT)ChanData->Regs.Data,
365 (PUSHORT)LocalBuffer,
366 1,
367 ChanData,
368 MRES_TF);
369
370 BufferEnd = ChanData->DataBuffer + ByteCount - 1;
371 *BufferEnd = LocalBuffer[0];
372 }
373 }
374
375 ChanData->DataBuffer += ByteCount;
376 ChanData->BytesToTransfer -= ByteCount;
377}
#define DECLSPEC_ALIGN(x)
Definition: corecrt.h:141
#define ATA_READ_BLOCK_16(Port, Buffer, Count)
Definition: hwidep.h:92
#define ATA_READ_BLOCK_32(Port, Buffer, Count)
Definition: hwidep.h:95
#define CHANNEL_FLAG_IO32
Definition: pciidex.h:260
uint32_t * PULONG
Definition: typedefs.h:59
uint16_t * PUSHORT
Definition: typedefs.h:56
unsigned char * PUCHAR
Definition: typedefs.h:53
_In_ PUCHAR BufferEnd
Definition: usbdlib.h:189

Referenced by PataProcessAtapiRequest(), and PataProcessAtaRequest().

◆ PataPioDataOut()

static VOID PataPioDataOut ( _In_ PCHANNEL_DATA_PATA  ChanData,
_In_ ULONG  ByteCount 
)
static

Definition at line 381 of file pata_io.c.

384{
385 ByteCount = min(ByteCount, ChanData->BytesToTransfer);
386
387 TRACE("Write block %lu %lu %p\n",
388 ByteCount, ChanData->BytesToTransfer, ChanData->DataBuffer);
389
390 /* Transfer the data block */
391 if (!(ByteCount & (sizeof(ULONG) - 1)) &&
392 (ChanData->ChanInfo & CHANNEL_FLAG_IO32))
393 {
394 ATA_WRITE_BLOCK_32((PULONG)ChanData->Regs.Data,
395 (PULONG)ChanData->DataBuffer,
396 ByteCount / sizeof(ULONG),
397 ChanData,
398 MRES_TF);
399 }
400 else
401 {
402 ATA_WRITE_BLOCK_16((PUSHORT)ChanData->Regs.Data,
403 (PUSHORT)ChanData->DataBuffer,
404 ByteCount / sizeof(USHORT),
405 ChanData,
406 MRES_TF);
407
408 /* Write one last byte */
409 if (ByteCount & (sizeof(USHORT) - 1))
410 {
411 DECLSPEC_ALIGN(2) UCHAR LocalBuffer[2];
413
414 BufferEnd = ChanData->DataBuffer + ByteCount - 1;
415 LocalBuffer[0] = *BufferEnd;
416 LocalBuffer[1] = 0;
417
418 ATA_WRITE_BLOCK_16((PUSHORT)ChanData->Regs.Data,
419 (PUSHORT)LocalBuffer,
420 1,
421 ChanData,
422 MRES_TF);
423 }
424 }
425
426 ChanData->DataBuffer += ByteCount;
427 ChanData->BytesToTransfer -= ByteCount;
428}
#define ATA_WRITE_BLOCK_16(Port, Buffer, Count)
Definition: hwidep.h:83
#define ATA_WRITE_BLOCK_32(Port, Buffer, Count)
Definition: hwidep.h:86

Referenced by PataProcessAtapiRequest(), and PataProcessAtaRequest().

◆ PataPoll()

static BOOLEAN PataPoll ( _In_ PCHANNEL_DATA_PATA  ChanData)
static

Definition at line 1159 of file pata_io.c.

1161{
1162 BOOLEAN IsRequestCompleted = FALSE;
1163 UCHAR IdeStatus;
1164
1165 while (TRUE)
1166 {
1167 /* Need to wait for a valid status */
1168 ATA_IO_WAIT();
1169
1170 /* Do a quick check here for a busy */
1171 IdeStatus = ATA_WAIT(ChanData, ATA_TIME_BUSY_POLL, IDE_STATUS_BUSY, 0);
1172 if (IdeStatus & IDE_STATUS_BUSY)
1173 {
1174 /* Device is still busy, schedule a timer to retry the poll */
1175 break;
1176 }
1177
1178 IsRequestCompleted = PataProcessRequest(ChanData, IdeStatus, 0);
1179 if (IsRequestCompleted)
1180 break;
1181 }
1182
1183 return IsRequestCompleted;
1184}
unsigned char BOOLEAN
Definition: actypes.h:127
#define ATA_TIME_BUSY_POLL
5 s
Definition: hwidep.h:70

Referenced by PataPollingTimerDpc().

◆ PataPollingTimerDpc()

VOID NTAPI PataPollingTimerDpc ( _In_ PKDPC  Dpc,
_In_opt_ PVOID  DeferredContext,
_In_opt_ PVOID  SystemArgument1,
_In_opt_ PVOID  SystemArgument2 
)

Definition at line 1188 of file pata_io.c.

1193{
1195 KIRQL OldIrql;
1196 BOOLEAN IsRequestCompleted;
1197
1201
1202 OldIrql = KeAcquireInterruptSpinLock(ChanData->InterruptObject);
1203
1204 if (!(ChanData->ActiveSlotsBitmap & (1 << PATA_CHANNEL_SLOT)) ||
1206 {
1207 IsRequestCompleted = FALSE;
1208 }
1209 else
1210 {
1211 IsRequestCompleted = PataPoll(ChanData);
1212 }
1213
1214 KeReleaseInterruptSpinLock(ChanData->InterruptObject, OldIrql);
1215
1216 if (!IsRequestCompleted)
1218}
BOOLEAN NTAPI KeInsertQueueDpc(IN PKDPC Dpc, IN PVOID SystemArgument1, IN PVOID SystemArgument2)
Definition: dpc.c:725
UCHAR KIRQL
Definition: env_spec_w32.h:591
KIRQL NTAPI KeAcquireInterruptSpinLock(IN PKINTERRUPT Interrupt)
Definition: spinlock.c:154
VOID NTAPI KeReleaseInterruptSpinLock(IN PKINTERRUPT Interrupt, IN KIRQL OldIrql)
Definition: spinlock.c:171
static BOOLEAN PataPoll(_In_ PCHANNEL_DATA_PATA ChanData)
Definition: pata_io.c:1159
KDPC PollingTimerDpc
Definition: pciidex.h:312
_Must_inspect_result_ _In_ PWDF_DPC_CONFIG _In_ PWDF_OBJECT_ATTRIBUTES _Out_ WDFDPC * Dpc
Definition: wdfdpc.h:112
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:778
_In_opt_ PVOID _In_opt_ PVOID SystemArgument1
Definition: ketypes.h:740
_In_opt_ PVOID DeferredContext
Definition: ketypes.h:739
_In_opt_ PVOID _In_opt_ PVOID _In_opt_ PVOID SystemArgument2
Definition: ketypes.h:741

◆ PataPrepareIo()

VOID PataPrepareIo ( _In_ PVOID  ChannelContext,
_In_ PATA_DEVICE_REQUEST  Request 
)

Definition at line 958 of file pata_io.c.

961{
962 PCHANNEL_DATA_PATA ChanData = ChannelContext;
963
964 /*
965 * HACK: In an emulated PC-98 system IDE interrupts are often lost.
966 * The reason for this problem is unknown (not the driver's fault).
967 * Always poll for the command completion as a workaround.
968 */
969 if (IsNEC_98)
970 Request->Flags |= REQUEST_FLAG_POLL;
971
972 ChanData->BytesToTransfer = Request->DataTransferLength;
973 ChanData->DataBuffer = Request->DataBuffer;
974}
PUCHAR DataBuffer
Definition: pciidex.h:304
ULONG BytesToTransfer
Definition: pciidex.h:305
#define IsNEC_98
Definition: ketypes.h:963

◆ PataProcessAtapiRequest()

static UCHAR PataProcessAtapiRequest ( _In_ PCHANNEL_DATA_PATA  ChanData,
_In_ PATA_DEVICE_REQUEST  Request,
_In_ UCHAR  IdeStatus 
)
static

Definition at line 432 of file pata_io.c.

436{
437 UCHAR SrbStatus, InterruptReason;
439
440 InterruptReason = ATA_READ(ChanData->Regs.InterruptReason, ChanData, MRES_TF);
441 InterruptReason &= ATAPI_INT_REASON_MASK;
442 InterruptReason |= IdeStatus & IDE_STATUS_DRQ;
443
444 /*
445 * The NEC CDR-C251 drive is not fully ATAPI-compliant
446 * and clears BSY before raising the DRQ bit and updating the interrupt reason register.
447 * As a workaround, we will wait a bit more in the case the valid IR is not quite there yet.
448 */
449 if ((InterruptReason == ATAPI_INT_REASON_COD) || (InterruptReason == ATAPI_INT_REASON_IO))
450 {
451#if DBG
452 static SIZE_T WarningsGiven = 0;
453 if (WarningsGiven++ < 2)
454 WARN("Not fully compliant ATAPI device %02x %02x\n", IdeStatus, InterruptReason);
455#endif
457
458 InterruptReason = ATA_READ(ChanData->Regs.InterruptReason, ChanData, MRES_TF);
459 InterruptReason &= ATAPI_INT_REASON_MASK;
460 InterruptReason |= IdeStatus & IDE_STATUS_DRQ;
461 }
462
463 switch (InterruptReason)
464 {
466 {
467 if (!(ChanData->CommandFlags & CMD_FLAG_AWAIT_CDB))
468 {
469 WARN("Invalid interrupt reason %02x %02x, flags %08lx\n",
470 InterruptReason,
471 IdeStatus,
472 ChanData->CommandFlags);
473
474 SrbStatus = SRB_STATUS_BUS_RESET;
475 break;
476 }
477 ChanData->CommandFlags &= ~CMD_FLAG_AWAIT_CDB;
478
479 PataSendCdb(ChanData, Request);
480
481 /* Start the DMA engine */
482 if (Request->Flags & REQUEST_FLAG_DMA)
483 {
484 ChanData->CommandFlags |= CMD_FLAG_DMA_TRANSFER;
485 PciIdeDmaStart(ChanData, Request);
486 }
487
488 SrbStatus = SRB_STATUS_PENDING;
489 break;
490 }
491
493 {
494 if (ChanData->CommandFlags & (CMD_FLAG_DATA_OUT | CMD_FLAG_AWAIT_CDB))
495 {
496 WARN("Invalid interrupt reason %02x %02x, flags %08lx\n",
497 InterruptReason,
498 IdeStatus,
499 ChanData->CommandFlags);
500
501 SrbStatus = SRB_STATUS_BUS_RESET;
502 break;
503 }
504
505 ByteCount = ATA_READ(ChanData->Regs.ByteCountLow, ChanData, MRES_TF);
506 ByteCount |= ATA_READ(ChanData->Regs.ByteCountHigh, ChanData, MRES_TF) << 8;
507
508 PataPioDataIn(ChanData, ByteCount);
509 SrbStatus = SRB_STATUS_PENDING;
510 break;
511 }
512
514 {
515 if (ChanData->CommandFlags & (CMD_FLAG_DATA_IN | CMD_FLAG_AWAIT_CDB))
516 {
517 WARN("Invalid interrupt reason %02x %02x, flags %08lx\n",
518 InterruptReason,
519 IdeStatus,
520 ChanData->CommandFlags);
521
522 SrbStatus = SRB_STATUS_BUS_RESET;
523 break;
524 }
525
526 ByteCount = ATA_READ(ChanData->Regs.ByteCountLow, ChanData, MRES_TF);
527 ByteCount |= ATA_READ(ChanData->Regs.ByteCountHigh, ChanData, MRES_TF) << 8;
528
529 PataPioDataOut(ChanData, ByteCount);
530 SrbStatus = SRB_STATUS_PENDING;
531 break;
532 }
533
535 {
536 /* The NEC CDR-260 drive always clears CoD and IO on command completion */
537 if (!(Request->Device->TransportFlags & DEVICE_IS_NEC_CDR260))
538 {
539 WARN("Invalid interrupt reason %02x %02x, flags %08lx\n",
540 InterruptReason,
541 IdeStatus,
542 ChanData->CommandFlags);
543
544 SrbStatus = SRB_STATUS_BUS_RESET;
545 break;
546 }
548 }
550 {
551 if (IdeStatus & (IDE_STATUS_ERROR | IDE_STATUS_DEVICE_FAULT))
552 {
553 SrbStatus = SRB_STATUS_ERROR;
554 }
555 else if (ChanData->BytesToTransfer != 0)
556 {
557 /* This indicates a residual underrun */
558 ASSERT(Request->DataTransferLength >= ChanData->BytesToTransfer);
559 Request->DataTransferLength -= ChanData->BytesToTransfer;
560
561 SrbStatus = SRB_STATUS_DATA_OVERRUN;
562 }
563 else
564 {
565 SrbStatus = SRB_STATUS_SUCCESS;
566 }
567 break;
568 }
569
570 default:
571 {
572 WARN("Invalid interrupt reason %02x %02x, flags %08lx\n",
573 InterruptReason,
574 IdeStatus,
575 ChanData->CommandFlags);
576
577 SrbStatus = SRB_STATUS_BUS_RESET;
578 break;
579 }
580 }
581
582 return SrbStatus;
583}
#define IDE_STATUS_DEVICE_FAULT
Definition: ata.h:624
#define DEVICE_IS_NEC_CDR260
Definition: ata_shared.h:168
#define IDE_STATUS_ERROR
Definition: atapi.h:125
#define IDE_STATUS_DRQ
Definition: atapi.h:128
static BOOLEAN WarningsGiven[5]
Definition: bussupp.c:425
#define SRB_STATUS_BUS_RESET
Definition: srb.h:353
#define SRB_STATUS_PENDING
Definition: srb.h:340
#define SRB_STATUS_ERROR
Definition: srb.h:344
#define ATAPI_INT_REASON_STATUS_NEC
Definition: hwidep.h:62
#define ATA_TIME_DRQ_ASSERT
150 us
Definition: hwidep.h:78
#define ATAPI_INT_REASON_IO
Definition: hwidep.h:59
#define ATAPI_INT_REASON_COD
Definition: hwidep.h:58
#define ATAPI_INT_REASON_STATUS
Definition: hwidep.h:63
#define ATAPI_INT_REASON_MASK
Definition: hwidep.h:60
#define ATAPI_INT_REASON_AWAIT_CDB
Definition: hwidep.h:64
#define ATAPI_INT_REASON_DATA_IN
Definition: hwidep.h:65
#define ATAPI_INT_REASON_DATA_OUT
Definition: pata.h:160
#define CMD_FLAG_DATA_OUT
Definition: pata.h:185
#define CMD_FLAG_DATA_IN
Definition: pata.h:184
static VOID PataPioDataOut(_In_ PCHANNEL_DATA_PATA ChanData, _In_ ULONG ByteCount)
Definition: pata_io.c:381
static VOID PataPioDataIn(_In_ PCHANNEL_DATA_PATA ChanData, _In_ ULONG ByteCount)
Definition: pata_io.c:330
static VOID PataSendCdb(_In_ PCHANNEL_DATA_PATA ChanData, _In_ PATA_DEVICE_REQUEST Request)
Definition: pata_io.c:305
#define __fallthrough
Definition: sal_old.h:314
ULONG_PTR SIZE_T
Definition: typedefs.h:80

Referenced by PataProcessRequest().

◆ PataProcessAtaRequest()

static UCHAR PataProcessAtaRequest ( _In_ PCHANNEL_DATA_PATA  ChanData,
_In_ PATA_DEVICE_REQUEST  Request,
_In_ UCHAR  IdeStatus 
)
static

Definition at line 587 of file pata_io.c.

591{
592 /* Check for errors */
593 if (IdeStatus & (IDE_STATUS_ERROR | IDE_STATUS_DEVICE_FAULT))
594 {
595 if (IdeStatus & IDE_STATUS_DRQ)
596 {
597 ERR("DRQ not cleared, status 0x%02x\n", IdeStatus);
599 }
600 else
601 {
602 return SRB_STATUS_ERROR;
603 }
604 }
605
606 /* Non-data ATA command */
607 if (!(ChanData->CommandFlags & (CMD_FLAG_DATA_IN | CMD_FLAG_DATA_OUT)))
608 {
609 // HACK: NP21/W IDE emulation bug, needs to be fixed on the emulator side
610 if (IsNEC_98)
611 IdeStatus &= ~IDE_STATUS_DRQ;
612
613 if (IdeStatus & IDE_STATUS_DRQ)
614 {
615 ERR("DRQ not cleared, status 0x%02x\n", IdeStatus);
617 }
618 else
619 {
620 return SRB_STATUS_SUCCESS;
621 }
622 }
623
624 /* Read command */
625 if (ChanData->CommandFlags & CMD_FLAG_DATA_IN)
626 {
627 if (!(IdeStatus & IDE_STATUS_DRQ))
628 {
629 if ((IdeStatus == 0) &&
630 ((Request->TaskFile.Command == IDE_COMMAND_ATAPI_IDENTIFY) ||
631 (Request->TaskFile.Command == IDE_COMMAND_IDENTIFY)))
632 {
633 /*
634 * Some controllers indicate status 0x00
635 * when the selected device does not exist,
636 * no point in going further.
637 */
638 return SRB_STATUS_ERROR;
639 }
640 else
641 {
642#if DBG
643 static SIZE_T WarningsGiven = 0;
644 if (WarningsGiven++ < 2)
645 WARN("Not fully compliant ATA device %02x\n", IdeStatus);
646#endif
647
648 /*
649 * The NEC CDR-C251 drive clears BSY before raising the DRQ bit
650 * while processing the ATAPI identify command.
651 * Give the device a chance to assert that bit.
652 */
653 IdeStatus = ATA_WAIT(ChanData,
657 if (!(IdeStatus & IDE_STATUS_DRQ))
658 {
659
660 ERR("DRQ not set, status 0x%02x\n", IdeStatus);
662 }
663 }
664 }
665
666 /* Read the next data block */
667 PataPioDataIn(ChanData, ChanData->DrqByteCount);
668
669 if (ChanData->BytesToTransfer != 0)
670 return SRB_STATUS_PENDING;
671
672 /* All data has been transferred, wait for DRQ to clear */
673 IdeStatus = ATA_WAIT(ChanData,
676 0);
677 if (IdeStatus & (IDE_STATUS_BUSY | IDE_STATUS_DRQ))
678 {
679 ERR("DRQ not cleared, status 0x%02x\n", IdeStatus);
681 }
682
683 if (IdeStatus & (IDE_STATUS_ERROR | IDE_STATUS_DEVICE_FAULT))
684 return SRB_STATUS_ERROR;
685
686 return SRB_STATUS_SUCCESS;
687 }
688
689 /* Write command */
690 if (ChanData->BytesToTransfer == 0)
691 {
692 if (IdeStatus & IDE_STATUS_DRQ)
693 {
694 ERR("DRQ not cleared, status 0x%02x\n", IdeStatus);
696 }
697 else
698 {
699 return SRB_STATUS_SUCCESS;
700 }
701 }
702
703 if (!(IdeStatus & IDE_STATUS_DRQ))
704 {
705 ERR("DRQ not set, status 0x%02x %lu/%lu\n",
706 IdeStatus,
707 ChanData->BytesToTransfer,
708 Request->DataTransferLength);
710 }
711
712 /* Write the next data block */
713 PataPioDataOut(ChanData, ChanData->DrqByteCount);
714 return SRB_STATUS_PENDING;
715}
#define IDE_COMMAND_ATAPI_IDENTIFY
Definition: atapi.h:110
#define IDE_COMMAND_IDENTIFY
Definition: atapi.h:118
#define ERR(fmt,...)
Definition: precomp.h:57
#define ATA_TIME_DRQ_CLEAR
10 ms
Definition: hwidep.h:74

Referenced by PataProcessRequest().

◆ PataProcessRequest()

static BOOLEAN PataProcessRequest ( _In_ PCHANNEL_DATA_PATA  ChanData,
_In_ UCHAR  IdeStatus,
_In_ UCHAR  DmaStatus 
)
static

Definition at line 719 of file pata_io.c.

723{
725 UCHAR SrbStatus;
726
727 ASSERT(!(IdeStatus & IDE_STATUS_BUSY));
728
729 TRACE("%u Status 0x%02x, DMA 0x%02x, REQ 0x%lx\n",
730 DEV_NUMBER(Request->Device),
731 IdeStatus,
732 DmaStatus,
733 ChanData->CommandFlags);
734
735 switch (ChanData->CommandFlags & CMD_FLAG_TRANSFER_MASK)
736 {
738 {
739 if ((DmaStatus & PCIIDE_DMA_STATUS_ERROR) ||
741 {
742 SrbStatus = SRB_STATUS_ERROR;
743 }
744 else
745 {
746 SrbStatus = SRB_STATUS_SUCCESS;
747 }
748 break;
749 }
750
752 {
753 SrbStatus = PataProcessAtaRequest(ChanData, Request, IdeStatus);
754 break;
755 }
756
758 {
759 SrbStatus = PataProcessAtapiRequest(ChanData, Request, IdeStatus);
760 break;
761 }
762
763 default:
764 {
765 ASSERT(FALSE);
767 }
768 }
769
770 if (SrbStatus == SRB_STATUS_PENDING)
771 return FALSE;
772
773 PataCompleteCommand(ChanData, IdeStatus, SrbStatus);
774 return TRUE;
775}
#define UNREACHABLE
#define CMD_FLAG_TRANSFER_MASK
Definition: pata.h:182
#define PCIIDE_DMA_STATUS_ERROR
Definition: pata.h:126
static UCHAR PataProcessAtaRequest(_In_ PCHANNEL_DATA_PATA ChanData, _In_ PATA_DEVICE_REQUEST Request, _In_ UCHAR IdeStatus)
Definition: pata_io.c:587
static VOID PataCompleteCommand(_In_ PCHANNEL_DATA_PATA ChanData, _In_ UCHAR IdeStatus, _In_ UCHAR SrbStatus)
Definition: pata_io.c:154
static UCHAR PataProcessAtapiRequest(_In_ PCHANNEL_DATA_PATA ChanData, _In_ PATA_DEVICE_REQUEST Request, _In_ UCHAR IdeStatus)
Definition: pata_io.c:432

Referenced by PataChannelIsr(), PataPoll(), PataStartIo(), and PciIdeChannelIsr().

◆ PataReadStatus()

UCHAR PataReadStatus ( _In_ PCHANNEL_DATA_PATA  ChanData)

Definition at line 146 of file pata_io.c.

148{
149 return ATA_READ(ChanData->Regs.Status, ChanData, MRES_TF);
150}

◆ PataSaveTaskFile()

VOID PataSaveTaskFile ( _In_ PCHANNEL_DATA_PATA  ChanData,
_Inout_ PATA_DEVICE_REQUEST  Request 
)

Definition at line 114 of file pata_io.c.

117{
118 PATA_TASKFILE TaskFile = &Request->Output;
119
120 TaskFile->Error = ATA_READ(ChanData->Regs.Error, ChanData, MRES_TF);
121 TaskFile->SectorCount = ATA_READ(ChanData->Regs.SectorCount, ChanData, MRES_TF);
122 TaskFile->LowLba = ATA_READ(ChanData->Regs.LbaLow, ChanData, MRES_TF);
123 TaskFile->MidLba = ATA_READ(ChanData->Regs.LbaMid, ChanData, MRES_TF);
124 TaskFile->HighLba = ATA_READ(ChanData->Regs.LbaHigh, ChanData, MRES_TF);
125 TaskFile->DriveSelect = ATA_READ(ChanData->Regs.Device, ChanData, MRES_TF);
126 TaskFile->Command = ATA_READ(ChanData->Regs.Command, ChanData, MRES_TF);
127
128 if (Request->Flags & REQUEST_FLAG_LBA48)
129 {
130 UCHAR Control = ATA_READ(ChanData->Regs.Control, ChanData, MRES_CTRL) | IDE_DC_ALWAYS;
131
132 /* Read the extra information from the second byte of FIFO */
133 ATA_WRITE(ChanData->Regs.Control, Control | IDE_HIGH_ORDER_BYTE, ChanData, MRES_CTRL);
134
135 TaskFile->FeatureEx = ATA_READ(ChanData->Regs.Features, ChanData, MRES_TF);
136 TaskFile->SectorCountEx = ATA_READ(ChanData->Regs.SectorCount, ChanData, MRES_TF);
137 TaskFile->LowLbaEx = ATA_READ(ChanData->Regs.LbaLow, ChanData, MRES_TF);
138 TaskFile->MidLbaEx = ATA_READ(ChanData->Regs.LbaMid, ChanData, MRES_TF);
139 TaskFile->HighLbaEx = ATA_READ(ChanData->Regs.LbaHigh, ChanData, MRES_TF);
140
141 ATA_WRITE(ChanData->Regs.Control, Control, ChanData, MRES_CTRL);
142 }
143}
#define IDE_HIGH_ORDER_BYTE
Definition: atapi.h:213
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

◆ PataSendCdb()

static VOID PataSendCdb ( _In_ PCHANNEL_DATA_PATA  ChanData,
_In_ PATA_DEVICE_REQUEST  Request 
)
static

Definition at line 305 of file pata_io.c.

308{
309 /* Command packet transfer */
310 if (ChanData->ChanInfo & CHANNEL_FLAG_IO32)
311 {
312 ATA_WRITE_BLOCK_32((PULONG)ChanData->Regs.Data,
313 (PULONG)Request->Cdb,
314 Request->Device->CdbSize / sizeof(USHORT),
315 ChanData,
316 MRES_TF);
317 }
318 else
319 {
320 ATA_WRITE_BLOCK_16((PUSHORT)ChanData->Regs.Data,
321 (PUSHORT)Request->Cdb,
322 Request->Device->CdbSize,
323 ChanData,
324 MRES_TF);
325 }
326}

Referenced by PataProcessAtapiRequest().

◆ PataStartIo()

BOOLEAN PataStartIo ( _In_ PVOID  ChannelContext,
_In_ PATA_DEVICE_REQUEST  Request 
)

Definition at line 895 of file pata_io.c.

898{
899 PCHANNEL_DATA_PATA ChanData = ChannelContext;
901 UCHAR IdeStatus;
902 BOOLEAN IsPollingNeeded;
903
904 ChanData->ActiveSlotsBitmap |= 1 << PATA_CHANNEL_SLOT;
905
906 /* Select the device */
907 ATA_SELECT_DEVICE(ChanData, DEV_NUMBER(Device), Device->DeviceSelect);
908
909 /* Wait for busy to clear */
910 IdeStatus = ATA_WAIT(ChanData, ATA_TIME_BUSY_SELECT, IDE_STATUS_BUSY, 0);
911 if (IdeStatus & IDE_STATUS_BUSY)
912 {
913 WARN("Device is busy 0x%02x\n", IdeStatus);
915 return TRUE;
916 }
917
918 /* Disable interrupts for the polled commands */
919 if (!!(Request->Flags & REQUEST_FLAG_POLL) != ChanData->IsPollingActive)
920 {
922 }
923
924 /* Execute the command */
926 IsPollingNeeded = PataExecutePacketCommand(ChanData, Device, Request);
927 else
928 IsPollingNeeded = PataExecuteAtaCommand(ChanData, Device, Request);
929
930 if (Request->Flags & REQUEST_FLAG_POLL)
931 {
932 /* Queue a DPC to poll for the command */
934 return FALSE;
935 }
936
938
939 if (!IsPollingNeeded)
940 return FALSE;
941
942 /* Need to wait for a valid status */
943 ATA_IO_WAIT();
944
945 /* Wait for busy to clear */
946 IdeStatus = ATA_WAIT(ChanData, ATA_TIME_BUSY_NORMAL, IDE_STATUS_BUSY, 0);
947 if (IdeStatus & IDE_STATUS_BUSY)
948 {
949 ERR("BSY timeout, status 0x%02x\n", IdeStatus);
950 PataCompleteCommand(ChanData, IdeStatus, SRB_STATUS_BUS_RESET);
951 return TRUE;
952 }
953
954 return PataProcessRequest(ChanData, IdeStatus, 0);
955}
#define SRB_STATUS_SELECTION_TIMEOUT
Definition: srb.h:350
#define REQUEST_FLAG_PACKET_COMMAND
Definition: hwidep.h:169
#define ATA_TIME_BUSY_NORMAL
500 ms
Definition: pata.h:170
static BOOLEAN PataExecutePacketCommand(_In_ PCHANNEL_DATA_PATA ChanData, _In_ PATA_IO_CONTEXT_COMMON Device, _In_ PATA_DEVICE_REQUEST Request)
Definition: pata_io.c:806
static VOID PataChangeInterruptMode(_In_ PCHANNEL_DATA_PATA ChanData, _In_ PATA_IO_CONTEXT_COMMON Device, _In_ PATA_DEVICE_REQUEST Request)
Definition: pata_io.c:271
static BOOLEAN PataExecuteAtaCommand(_In_ PCHANNEL_DATA_PATA ChanData, _In_ PATA_IO_CONTEXT_COMMON Device, _In_ PATA_DEVICE_REQUEST Request)
Definition: pata_io.c:847
BOOLEAN IsPollingActive
Definition: pciidex.h:311

◆ PciIdeChannelIsr()

BOOLEAN NTAPI PciIdeChannelIsr ( _In_ PKINTERRUPT  Interrupt,
_In_ PVOID  Context 
)

Definition at line 1058 of file pata_io.c.

1061{
1062 PCHANNEL_DATA_PATA ChanData = Context;
1063 UCHAR IdeStatus, DmaStatus;
1064 BOOLEAN WasCleared;
1065
1067
1068 if (ChanData->CheckInterrupt && !(ChanData->CheckInterrupt(ChanData)))
1069 return FALSE;
1070
1071 DmaStatus = PciIdeDmaReadStatus(ChanData);
1072 if (DmaStatus & PCIIDE_DMA_STATUS_INTERRUPT)
1073 {
1074 /* Always clear the DMA interrupt, even when the current command is a PIO command */
1076 PciIdeDmaStop(ChanData);
1077 else
1078 PciIdeDmaClearInterrupt(ChanData, DmaStatus);
1079
1080 WasCleared = TRUE;
1081 }
1082 else
1083 {
1085 return FALSE;
1086
1087 WasCleared = FALSE;
1088 }
1089
1090 /* Acknowledge the IDE interrupt */
1091 IdeStatus = ChanData->ReadStatus(ChanData);
1092
1093 /* This interrupt is not ours */
1094 if (!(ChanData->ActiveSlotsBitmap & (1 << PATA_CHANNEL_SLOT)) ||
1095 !(ChanData->CommandFlags & CMD_FLAG_AWAIT_INTERRUPT) ||
1096 (IdeStatus & IDE_STATUS_BUSY))
1097 {
1098 /* Do not log PCI shared interrupts */
1099 if (WasCleared)
1100 {
1101 WARN("Spurious bus-master interrupt %02x, %02x, flags %08lx\n",
1102 IdeStatus, DmaStatus, ChanData->CommandFlags);
1103 }
1104
1105 return WasCleared;
1106 }
1107
1108 PataProcessRequest(ChanData, IdeStatus, DmaStatus);
1109 return TRUE;
1110}
#define PCIIDE_DMA_STATUS_INTERRUPT
Definition: pata.h:127
static UCHAR PciIdeDmaReadStatus(_In_ PCHANNEL_DATA_PATA ChanData)
Definition: pata_io.c:199
static VOID PciIdeDmaClearInterrupt(_In_ PCHANNEL_DATA_PATA ChanData, _In_ UCHAR DmaStatus)
Definition: pata_io.c:262
VOID PciIdeDmaStop(_In_ PCHANNEL_DATA_PATA ChanData)
Definition: pata_io.c:247

◆ PciIdeCheckInterrupt()

BOOLEAN PciIdeCheckInterrupt ( _In_ PCHANNEL_DATA_PATA  ChanData)

Definition at line 1143 of file pata_io.c.

1145{
1146 UCHAR DmaStatus = PciIdeDmaReadStatus(ChanData);
1147
1148 /*
1149 * On some PATA controllers the DMA interrupt bit reflects the state
1150 * of the IDE interrupt pin. Such controllers assert the DMA interrupt
1151 * even if the current command is a PIO command.
1152 * We use this capability for better handling of PCI shared interrupts.
1153 */
1154 return !!(DmaStatus & PCIIDE_DMA_STATUS_INTERRUPT);
1155}

◆ PciIdeDmaClearInterrupt()

static VOID PciIdeDmaClearInterrupt ( _In_ PCHANNEL_DATA_PATA  ChanData,
_In_ UCHAR  DmaStatus 
)
static

Definition at line 262 of file pata_io.c.

265{
266 ATA_WRITE(ChanData->Regs.Dma + PCIIDE_DMA_STATUS, DmaStatus, ChanData, MRES_DMA);
267}
#define PCIIDE_DMA_STATUS
Definition: pata.h:107

Referenced by PciIdeChannelIsr().

◆ PciIdeDmaPrepare()

static VOID PciIdeDmaPrepare ( _In_ PCHANNEL_DATA_PATA  ChanData)
static

Definition at line 207 of file pata_io.c.

209{
210 PUCHAR IoBase = ChanData->Regs.Dma;
211
212 /* Clear the interrupt and error bits in the status register */
214 PCIIDE_DMA_COMMAND_STOP, ChanData, MRES_DMA);
217
218 /* Set the address to the beginning of the physical region descriptor table */
220 ChanData->PrdTablePhysicalAddress,
221 ChanData,
222 MRES_DMA);
223}
#define PCIIDE_DMA_COMMAND
Definition: pata.h:106
#define PCIIDE_DMA_COMMAND_STOP
Definition: pata.h:115
#define ATA_WRITE_ULONG(Port, Value, Ctx, MmioFlag)
Definition: pata.h:266
#define PCIIDE_DMA_PRDT_PHYSICAL_ADDRESS
Definition: pata.h:108

Referenced by PciIdePreparePrdTable().

◆ PciIdeDmaReadStatus()

static UCHAR PciIdeDmaReadStatus ( _In_ PCHANNEL_DATA_PATA  ChanData)
inlinestatic

Definition at line 199 of file pata_io.c.

201{
202 return ATA_READ(ChanData->Regs.Dma + PCIIDE_DMA_STATUS, ChanData, MRES_DMA);
203}

Referenced by PciIdeChannelIsr(), and PciIdeCheckInterrupt().

◆ PciIdeDmaStart()

static VOID PciIdeDmaStart ( _In_ PCHANNEL_DATA_PATA  ChanData,
_In_ PATA_DEVICE_REQUEST  Request 
)
static

Definition at line 227 of file pata_io.c.

230{
232
234
235 /* Transfer direction */
236 if (Request->Flags & REQUEST_FLAG_DATA_IN)
238 else
241
242 /* Begin transaction */
243 ATA_WRITE(ChanData->Regs.Dma + PCIIDE_DMA_COMMAND, Command, ChanData, MRES_DMA);
244}
#define REQUEST_FLAG_HAS_SG_LIST
Definition: ata_shared.h:330
#define PCIIDE_DMA_COMMAND_START
Definition: pata.h:116
#define PCIIDE_DMA_COMMAND_READ_FROM_SYSTEM_MEMORY
Definition: pata.h:117
#define PCIIDE_DMA_COMMAND_WRITE_TO_SYSTEM_MEMORY
Definition: pata.h:118
Definition: shell.h:41

Referenced by PataExecuteAtaCommand(), and PataProcessAtapiRequest().

◆ PciIdeDmaStop()

VOID PciIdeDmaStop ( _In_ PCHANNEL_DATA_PATA  ChanData)

Definition at line 247 of file pata_io.c.

249{
250 PUCHAR IoBase = ChanData->Regs.Dma;
251
252 /* Wait one PIO transfer cycle */
253 (VOID)ATA_READ(IoBase + PCIIDE_DMA_STATUS, ChanData, MRES_DMA);
254
255 /* Clear the interrupt bit in the status register */
256 ATA_WRITE(IoBase + PCIIDE_DMA_COMMAND, PCIIDE_DMA_COMMAND_STOP, ChanData, MRES_DMA);
257 ATA_WRITE(IoBase + PCIIDE_DMA_STATUS, PCIIDE_DMA_STATUS_INTERRUPT, ChanData, MRES_DMA);
258}
#define VOID
Definition: acefi.h:82

Referenced by PataResetChannel(), and PciIdeChannelIsr().

◆ PciIdePreparePrdTable()

VOID PciIdePreparePrdTable ( _In_ PVOID  ChannelContext,
_In_ PATA_DEVICE_REQUEST  Request,
_In_ SCATTER_GATHER_LIST *__restrict  SgList 
)

Definition at line 977 of file pata_io.c.

981{
982 PCHANNEL_DATA_PATA ChanData = ChannelContext;
983 PPCIIDE_PRD_TABLE_ENTRY PrdTableEntry;
984 ULONG i;
985 ULONG DescriptorNumber = 0;
986
987 DBG_UNREFERENCED_LOCAL_VARIABLE(DescriptorNumber);
988
989 ASSUME(SgList->NumberOfElements > 0);
990
991 PrdTableEntry = ChanData->PrdTable;
992
993 for (i = 0; i < SgList->NumberOfElements; ++i)
994 {
995 ULONG Address = SgList->Elements[i].Address.LowPart;
996 ULONG Length = SgList->Elements[i].Length;
997
998 ASSUME(Length != 0);
999
1000 /* 32-bit DMA */
1001 ASSERT(SgList->Elements[i].Address.HighPart == 0);
1002
1003 /* The address of memory region must be word aligned */
1005
1006 while (Length > 0)
1007 {
1008 ULONG TransferLength;
1009
1010 /* If the memory region would cross a 64 kB boundary, split it */
1011 TransferLength = PCIIDE_PRD_LIMIT - (Address & (PCIIDE_PRD_LIMIT - 1));
1012 TransferLength = min(TransferLength, Length);
1013
1014 /* The byte count must be word aligned */
1015 ASSERT((TransferLength % sizeof(USHORT)) == 0);
1016
1017 /* Make sure we do not write beyond the end of the PRD table */
1018 ASSERT(DescriptorNumber < ChanData->MaximumPhysicalPages);
1019 DescriptorNumber++;
1020
1021 PrdTableEntry->Address = Address;
1022 PrdTableEntry->Length = TransferLength & PCIIDE_PRD_LENGTH_MASK;
1023
1024 ++PrdTableEntry;
1025
1026 Address += TransferLength;
1027 Length -= TransferLength;
1028 }
1029 }
1030
1031 /* The PRD table cannot cross a 64 kB boundary */
1032 ASSERT((DescriptorNumber * sizeof(*PrdTableEntry)) < PCIIDE_PRD_LIMIT);
1033
1034 /* Last entry */
1035 --PrdTableEntry;
1036 PrdTableEntry->Length |= PCIIDE_PRD_END_OF_TABLE;
1037
1039
1040 PciIdeDmaPrepare(ChanData);
1041}
#define ATA_MIN_BUFFER_ALIGNMENT
Definition: ata_shared.h:30
#define ASSUME(cond)
Definition: atapi.h:165
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 DBG_UNREFERENCED_LOCAL_VARIABLE(L)
Definition: ntbasedef.h:331
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:102
#define PCIIDE_PRD_END_OF_TABLE
Definition: pata.h:210
#define PCIIDE_PRD_LENGTH_MASK
Definition: pata.h:209
#define PCIIDE_PRD_LIMIT
Definition: pata.h:215
static VOID PciIdeDmaPrepare(_In_ PCHANNEL_DATA_PATA ChanData)
Definition: pata_io.c:207
static WCHAR Address[46]
Definition: ping.c:68
#define KeFlushIoBuffers(_Mdl, _ReadOperation, _DmaOperation)
Definition: ke.h:174
PPCIIDE_PRD_TABLE_ENTRY PrdTable
Definition: pciidex.h:300
Definition: pata.h:206
ULONG Address
Definition: pata.h:207
ULONG Length
0 means 0x10000 bytes
Definition: pata.h:208
WDF_EXTERN_C_START typedef _In_ WDFDEVICE _In_ WDFCONTEXT _In_ WDF_DMA_DIRECTION _In_ PSCATTER_GATHER_LIST SgList