ReactOS 0.4.16-dev-2633-g8dc9e50
pata_io.c
Go to the documentation of this file.
1/*
2 * PROJECT: ReactOS ATA Bus Driver
3 * LICENSE: MIT (https://spdx.org/licenses/MIT)
4 * PURPOSE: PATA I/O request handling
5 * COPYRIGHT: Copyright 2026 Dmitry Borisov <di.sean@protonmail.com>
6 */
7
8/* INCLUDES *******************************************************************/
9
10#include "pciidex.h"
11
12/* FUNCTIONS ******************************************************************/
13
14VOID
19 _In_ ULONG MmioFlags)
20{
21 ASSERT(Buffer != NULL);
22 ASSERT(Count != 0);
23
24 if (MmioFlags)
26 else
28}
29
30VOID
35 _In_ ULONG MmioFlags)
36{
37 ASSERT(Buffer != NULL);
38 ASSERT(Count != 0);
39
40 if (MmioFlags)
42 else
44}
45
46VOID
51 _In_ ULONG MmioFlags)
52{
53 ASSERT(Buffer != NULL);
54 ASSERT(Count != 0);
55
56 if (MmioFlags)
58 else
60}
61
62VOID
67 _In_ ULONG MmioFlags)
68{
69 ASSERT(Buffer != NULL);
70 ASSERT(Count != 0);
71
72 if (MmioFlags)
74 else
76}
77
81 _In_ ULONG MmioFlags)
82{
83 if (MmioFlags)
85 else
86 return READ_PORT_UCHAR(Port);
87}
88
89VOID
93 _In_ ULONG MmioFlags)
94{
95 if (MmioFlags)
97 else
99}
100
101VOID
105 _In_ ULONG MmioFlags)
106{
107 if (MmioFlags)
109 else
111}
112
113VOID
115 _In_ PCHANNEL_DATA_PATA ChanData,
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}
144
145UCHAR
147 _In_ PCHANNEL_DATA_PATA ChanData)
148{
149 return ATA_READ(ChanData->Regs.Status, ChanData, MRES_TF);
150}
151
152static
153VOID
155 _In_ PCHANNEL_DATA_PATA ChanData,
156 _In_ UCHAR IdeStatus,
157 _In_ UCHAR SrbStatus)
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}
195
196static
197inline
198UCHAR
200 _In_ PCHANNEL_DATA_PATA ChanData)
201{
202 return ATA_READ(ChanData->Regs.Dma + PCIIDE_DMA_STATUS, ChanData, MRES_DMA);
203}
204
205static
206VOID
208 _In_ PCHANNEL_DATA_PATA ChanData)
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}
224
225static
226VOID
228 _In_ PCHANNEL_DATA_PATA ChanData,
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}
245
246VOID
248 _In_ PCHANNEL_DATA_PATA ChanData)
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}
259
260static
261VOID
263 _In_ PCHANNEL_DATA_PATA ChanData,
264 _In_ UCHAR DmaStatus)
265{
266 ATA_WRITE(ChanData->Regs.Dma + PCIIDE_DMA_STATUS, DmaStatus, ChanData, MRES_DMA);
267}
268
269static
270VOID
272 _In_ PCHANNEL_DATA_PATA ChanData,
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}
302
303static
304VOID
306 _In_ PCHANNEL_DATA_PATA ChanData,
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}
327
328static
329VOID
331 _In_ PCHANNEL_DATA_PATA ChanData,
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}
378
379static
380VOID
382 _In_ PCHANNEL_DATA_PATA ChanData,
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}
429
430static
431UCHAR
433 _In_ PCHANNEL_DATA_PATA ChanData,
435 _In_ UCHAR IdeStatus)
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}
584
585static
586UCHAR
588 _In_ PCHANNEL_DATA_PATA ChanData,
590 _In_ UCHAR IdeStatus)
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}
716
717static
720 _In_ PCHANNEL_DATA_PATA ChanData,
721 _In_ UCHAR IdeStatus,
722 _In_ UCHAR DmaStatus)
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}
776
777VOID
779 _In_ PCHANNEL_DATA_PATA ChanData,
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}
803
804static
807 _In_ PCHANNEL_DATA_PATA ChanData,
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}
844
845static
848 _In_ PCHANNEL_DATA_PATA ChanData,
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}
893
896 _In_ PVOID ChannelContext,
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}
956
957VOID
959 _In_ PVOID ChannelContext,
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}
975
976VOID
978 _In_ PVOID ChannelContext,
980 _In_ SCATTER_GATHER_LIST* __restrict SgList)
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}
1042
1043BOOLEAN
1045 _In_ PVOID ChannelContext,
1048{
1049 UNREFERENCED_PARAMETER(ChannelContext);
1052
1053 return TRUE;
1054}
1055
1056BOOLEAN
1057NTAPI
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}
1111
1112BOOLEAN
1113NTAPI
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}
1141
1142BOOLEAN
1144 _In_ PCHANNEL_DATA_PATA ChanData)
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}
1156
1157static
1158BOOLEAN
1160 _In_ PCHANNEL_DATA_PATA ChanData)
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}
1185
1186VOID
1187NTAPI
1189 _In_ PKDPC Dpc,
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}
#define VOID
Definition: acefi.h:82
unsigned char BOOLEAN
Definition: actypes.h:127
#define WRITE_REGISTER_ULONG(r, v)
Definition: arm.h:11
#define IDE_STATUS_DEVICE_FAULT
Definition: ata.h:624
#define REQUEST_FLAG_DATA_IN
Definition: ata_shared.h:287
#define DEVICE_IS_NEC_CDR260
Definition: ata_shared.h:168
_In_ PATA_DEVICE_REQUEST _In_ BOOLEAN Allocate
Definition: ata_shared.h:437
#define DEVICE_HAS_CDB_INTERRUPT
Definition: ata_shared.h:166
#define REQUEST_FLAG_DATA_OUT
Definition: ata_shared.h:290
#define REQUEST_FLAG_HAS_SG_LIST
Definition: ata_shared.h:330
#define REQUEST_FLAG_SAVE_TASK_FILE
Definition: ata_shared.h:309
#define REQUEST_FLAG_POLL
Definition: ata_shared.h:353
#define REQUEST_FLAG_DMA
Definition: ata_shared.h:278
#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 ATA_MIN_BUFFER_ALIGNMENT
Definition: ata_shared.h:30
#define IDE_FEATURE_DMA
Definition: atapi.h:219
#define IDE_HIGH_ORDER_BYTE
Definition: atapi.h:213
#define ASSUME(cond)
Definition: atapi.h:165
#define IDE_STATUS_BUSY
Definition: atapi.h:132
#define IDE_STATUS_ERROR
Definition: atapi.h:125
#define IDE_COMMAND_ATAPI_IDENTIFY
Definition: atapi.h:110
#define IDE_COMMAND_IDENTIFY
Definition: atapi.h:118
#define IDE_STATUS_DRQ
Definition: atapi.h:128
#define IDE_COMMAND_ATAPI_PACKET
Definition: atapi.h:109
#define IDE_DC_DISABLE_INTERRUPTS
Definition: atapi.h:145
#define WARN(fmt,...)
Definition: precomp.h:61
#define ERR(fmt,...)
Definition: precomp.h:57
#define WRITE_PORT_BUFFER_ULONG(port, buffer, count)
Definition: hardware.h:35
#define WRITE_PORT_BUFFER_USHORT(port, buffer, count)
Definition: hardware.h:34
#define READ_PORT_BUFFER_ULONG(port, buffer, count)
Definition: hardware.h:32
#define READ_PORT_BUFFER_USHORT(port, buffer, count)
Definition: hardware.h:31
static BOOLEAN WarningsGiven[5]
Definition: bussupp.c:425
Definition: bufpool.h:45
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define DECLSPEC_ALIGN(x)
Definition: corecrt.h:141
BOOLEAN NTAPI KeInsertQueueDpc(IN PKDPC Dpc, IN PVOID SystemArgument1, IN PVOID SystemArgument2)
Definition: dpc.c:725
#define SRB_STATUS_BUS_RESET
Definition: srb.h:353
#define SRB_STATUS_DATA_OVERRUN
Definition: srb.h:357
#define SRB_STATUS_PENDING
Definition: srb.h:340
#define SRB_STATUS_ERROR
Definition: srb.h:344
#define SRB_STATUS_SELECTION_TIMEOUT
Definition: srb.h:350
#define SRB_STATUS_SUCCESS
Definition: srb.h:341
UCHAR KIRQL
Definition: env_spec_w32.h:591
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
VOID NTAPI WRITE_PORT_ULONG(IN PULONG Port, IN ULONG Value)
Definition: portio.c:123
CPPORT Port[4]
Definition: headless.c:38
#define ATA_IO_WAIT()
Definition: hwidep.h:39
#define ATAPI_INT_REASON_STATUS_NEC
Definition: hwidep.h:62
#define REQUEST_FLAG_LBA48
Definition: hwidep.h:167
#define ATA_WRITE_BLOCK_16(Port, Buffer, Count)
Definition: hwidep.h:83
#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 ATA_TIME_BUSY_POLL
5 s
Definition: hwidep.h:70
#define ATAPI_INT_REASON_STATUS
Definition: hwidep.h:63
#define REQUEST_FLAG_READ_WRITE_MULTIPLE
Definition: hwidep.h:168
#define ATAPI_INT_REASON_MASK
Definition: hwidep.h:60
#define REQUEST_FLAG_PACKET_COMMAND
Definition: hwidep.h:169
#define ATA_TIME_DRQ_CLEAR
10 ms
Definition: hwidep.h:74
#define IDE_FEATURE_PIO
Definition: hwidep.h:52
#define ATA_WRITE(Port, Value)
Definition: hwidep.h:80
#define ATAPI_INT_REASON_AWAIT_CDB
Definition: hwidep.h:64
#define ATA_READ_BLOCK_16(Port, Buffer, Count)
Definition: hwidep.h:92
#define IDE_DC_ALWAYS
Definition: hwidep.h:54
#define ATA_READ_BLOCK_32(Port, Buffer, Count)
Definition: hwidep.h:95
#define ATAPI_INT_REASON_DATA_IN
Definition: hwidep.h:65
#define ATA_TIME_BUSY_SELECT
20 ms
Definition: hwidep.h:69
#define REQUEST_FLAG_SET_DEVICE_REGISTER
Definition: hwidep.h:170
#define ATA_WRITE_BLOCK_32(Port, Buffer, Count)
Definition: hwidep.h:86
#define ATA_READ(Port)
Definition: hwidep.h:89
#define ASSERT(a)
Definition: mode.c:44
#define min(a, b)
Definition: monoChain.cc:55
#define _Inout_
Definition: no_sal2.h:162
#define _In_
Definition: no_sal2.h:158
#define _In_opt_
Definition: no_sal2.h:212
int Count
Definition: noreturn.cpp:7
#define DBG_UNREFERENCED_LOCAL_VARIABLE(L)
Definition: ntbasedef.h:331
#define UNREACHABLE
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:329
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:102
KIRQL NTAPI KeAcquireInterruptSpinLock(IN PKINTERRUPT Interrupt)
Definition: spinlock.c:154
VOID NTAPI KeReleaseInterruptSpinLock(IN PKINTERRUPT Interrupt, IN KIRQL OldIrql)
Definition: spinlock.c:171
#define ATAPI_MAX_DRQ_DATA_BLOCK
Definition: pata.h:65
#define CMD_FLAG_TRANSFER_MASK
Definition: pata.h:182
#define PCIIDE_PRD_END_OF_TABLE
Definition: pata.h:210
#define PATA_CHANNEL_SLOT
Definition: pata.h:193
#define PCIIDE_DMA_STATUS
Definition: pata.h:107
#define CMD_FLAG_ATAPI_PIO_TRANSFER
Definition: pata.h:188
#define PCIIDE_DMA_STATUS_INTERRUPT
Definition: pata.h:127
#define PCIIDE_PRD_LENGTH_MASK
Definition: pata.h:209
#define PCIIDE_PRD_LIMIT
Definition: pata.h:215
#define PCI_VEN_VIA
Definition: pata.h:15
#define CMD_FLAG_ATA_PIO_TRANSFER
Definition: pata.h:189
#define CMD_FLAG_AWAIT_CDB
Definition: pata.h:183
#define PCIIDE_DMA_COMMAND_START
Definition: pata.h:116
#define CMD_FLAG_DMA_TRANSFER
Definition: pata.h:190
#define PCIIDE_DMA_COMMAND
Definition: pata.h:106
#define PCIIDE_DMA_COMMAND_READ_FROM_SYSTEM_MEMORY
Definition: pata.h:117
#define PCIIDE_DMA_COMMAND_WRITE_TO_SYSTEM_MEMORY
Definition: pata.h:118
FORCEINLINE VOID ATA_SELECT_DEVICE(_In_ PCHANNEL_DATA_PATA ChanData, _In_ UCHAR DeviceNumber, _In_ UCHAR DeviceSelect)
Definition: pata.h:271
#define ATA_TIME_BUSY_NORMAL
500 ms
Definition: pata.h:170
#define PCIIDE_DMA_COMMAND_STOP
Definition: pata.h:115
#define ATA_WRITE_ULONG(Port, Value, Ctx, MmioFlag)
Definition: pata.h:266
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 PCIIDE_DMA_STATUS_ERROR
Definition: pata.h:126
#define ATAPI_INT_REASON_DATA_OUT
Definition: pata.h:160
#define CMD_FLAG_DATA_OUT
Definition: pata.h:185
#define CMD_FLAG_AWAIT_INTERRUPT
Definition: pata.h:186
#define CMD_FLAG_DATA_IN
Definition: pata.h:184
#define PCIIDE_DMA_PRDT_PHYSICAL_ADDRESS
Definition: pata.h:108
static UCHAR PciIdeDmaReadStatus(_In_ PCHANNEL_DATA_PATA ChanData)
Definition: pata_io.c:199
VOID AtaWritePortUchar(_In_ PUCHAR Port, _In_ UCHAR Value, _In_ ULONG MmioFlags)
Definition: pata_io.c:90
static VOID PataPioDataOut(_In_ PCHANNEL_DATA_PATA ChanData, _In_ ULONG ByteCount)
Definition: pata_io.c:381
static VOID PciIdeDmaPrepare(_In_ PCHANNEL_DATA_PATA ChanData)
Definition: pata_io.c:207
static BOOLEAN PataPoll(_In_ PCHANNEL_DATA_PATA ChanData)
Definition: pata_io.c:1159
static VOID PciIdeDmaClearInterrupt(_In_ PCHANNEL_DATA_PATA ChanData, _In_ UCHAR DmaStatus)
Definition: pata_io.c:262
static BOOLEAN PataProcessRequest(_In_ PCHANNEL_DATA_PATA ChanData, _In_ UCHAR IdeStatus, _In_ UCHAR DmaStatus)
Definition: pata_io.c:719
static VOID PataPioDataIn(_In_ PCHANNEL_DATA_PATA ChanData, _In_ ULONG ByteCount)
Definition: pata_io.c:330
VOID AtaWritePortUlong(_In_ PULONG Port, _In_ ULONG Value, _In_ ULONG MmioFlags)
Definition: pata_io.c:102
static VOID PataSendCdb(_In_ PCHANNEL_DATA_PATA ChanData, _In_ PATA_DEVICE_REQUEST Request)
Definition: pata_io.c:305
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 PciIdeDmaStart(_In_ PCHANNEL_DATA_PATA ChanData, _In_ PATA_DEVICE_REQUEST Request)
Definition: pata_io.c:227
VOID AtaReadBlock16(_In_ PUSHORT Port, _In_ PUSHORT Buffer, _In_ ULONG Count, _In_ ULONG MmioFlags)
Definition: pata_io.c:31
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
VOID AtaWriteBlock16(_In_ PUSHORT Port, _In_ PUSHORT Buffer, _In_ ULONG Count, _In_ ULONG MmioFlags)
Definition: pata_io.c:15
VOID AtaReadBlock32(_In_ PULONG Port, _In_ PULONG Buffer, _In_ ULONG Count, _In_ ULONG MmioFlags)
Definition: pata_io.c:63
VOID PciIdeDmaStop(_In_ PCHANNEL_DATA_PATA ChanData)
Definition: pata_io.c:247
static UCHAR PataProcessAtapiRequest(_In_ PCHANNEL_DATA_PATA ChanData, _In_ PATA_DEVICE_REQUEST Request, _In_ UCHAR IdeStatus)
Definition: pata_io.c:432
UCHAR AtaReadPortUchar(_In_ PUCHAR Port, _In_ ULONG MmioFlags)
Definition: pata_io.c:79
static VOID PataChangeInterruptMode(_In_ PCHANNEL_DATA_PATA ChanData, _In_ PATA_IO_CONTEXT_COMMON Device, _In_ PATA_DEVICE_REQUEST Request)
Definition: pata_io.c:271
VOID AtaWriteBlock32(_In_ PULONG Port, _In_ PULONG Buffer, _In_ ULONG Count, _In_ ULONG MmioFlags)
Definition: pata_io.c:47
static BOOLEAN PataExecuteAtaCommand(_In_ PCHANNEL_DATA_PATA ChanData, _In_ PATA_IO_CONTEXT_COMMON Device, _In_ PATA_DEVICE_REQUEST Request)
Definition: pata_io.c:847
#define READ_PORT_UCHAR(p)
Definition: pc98vid.h:22
#define WRITE_PORT_UCHAR(p, d)
Definition: pc98vid.h:21
CHANNEL_PREPARE_IO PataPrepareIo
Definition: pciidex.h:700
CHANNEL_LOAD_TASK_FILE PataLoadTaskFile
Definition: pciidex.h:705
KDEFERRED_ROUTINE PataPollingTimerDpc
Definition: pciidex.h:708
CHANNEL_START_IO PataStartIo
Definition: pciidex.h:701
#define DEV_NUMBER(Device)
Definition: pciidex.h:56
#define CHANNEL_FLAG_IO32
Definition: pciidex.h:260
KSERVICE_ROUTINE PciIdeChannelIsr
Definition: pciidex.h:703
CHANNEL_SAVE_TASK_FILE PataSaveTaskFile
Definition: pciidex.h:706
#define CHANNEL_FLAG_DMA_BEFORE_CMD
Definition: pciidex.h:279
CHANNEL_ALLOCATE_SLOT PataAllocateSlot
Definition: pciidex.h:698
KSERVICE_ROUTINE PataChannelIsr
Definition: pciidex.h:702
CHANNEL_CHECK_INTERRUPT PciIdeCheckInterrupt
Definition: pciidex.h:704
CHANNEL_READ_STATUS PataReadStatus
Definition: pciidex.h:707
CHANNEL_PREPARE_PRD_TABLE PciIdePreparePrdTable
Definition: pciidex.h:699
unsigned short USHORT
Definition: pedump.c:61
static WCHAR Address[46]
Definition: ping.c:68
#define __fallthrough
Definition: sal_old.h:314
#define KeFlushIoBuffers(_Mdl, _ReadOperation, _DmaOperation)
Definition: ke.h:174
#define TRACE(s)
Definition: solgame.cpp:4
_In_ PVOID Context
Definition: storport.h:2269
Definition: shell.h:41
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
PUCHAR DataBuffer
Definition: pciidex.h:304
PCHANNEL_CHECK_INTERRUPT CheckInterrupt
Definition: pciidex.h:303
PCHANNEL_READ_STATUS ReadStatus
Definition: pciidex.h:299
ULONG CommandFlags
Definition: pciidex.h:306
ULONG BytesToTransfer
Definition: pciidex.h:305
BOOLEAN IsPollingActive
Definition: pciidex.h:311
KDPC PollingTimerDpc
Definition: pciidex.h:312
PPCIIDE_PRD_TABLE_ENTRY PrdTable
Definition: pciidex.h:300
Definition: ketypes.h:751
Definition: pata.h:206
ULONG Address
Definition: pata.h:207
ULONG Length
0 means 0x10000 bytes
Definition: pata.h:208
uint32_t * PULONG
Definition: typedefs.h:59
unsigned char UCHAR
Definition: typedefs.h:53
#define NTAPI
Definition: typedefs.h:36
ULONG_PTR SIZE_T
Definition: typedefs.h:80
uint16_t * PUSHORT
Definition: typedefs.h:56
unsigned char * PUCHAR
Definition: typedefs.h:53
uint32_t ULONG
Definition: typedefs.h:59
_In_ PUCHAR BufferEnd
Definition: usbdlib.h:189
_Must_inspect_result_ _In_ WDFDEVICE Device
Definition: wdfchildlist.h:474
_In_ WDFREQUEST Request
Definition: wdfdevice.h:547
WDF_EXTERN_C_START typedef _In_ WDFDEVICE _In_ WDFCONTEXT _In_ WDF_DMA_DIRECTION _In_ PSCATTER_GATHER_LIST SgList
_Must_inspect_result_ _In_ PWDF_DPC_CONFIG _In_ PWDF_OBJECT_ATTRIBUTES _Out_ WDFDPC * Dpc
Definition: wdfdpc.h:112
_Must_inspect_result_ _In_ WDFDEVICE _In_ PWDF_INTERRUPT_CONFIG _In_opt_ PWDF_OBJECT_ATTRIBUTES _Out_ WDFINTERRUPT * Interrupt
Definition: wdfinterrupt.h:379
_Must_inspect_result_ _In_ WDFKEY _In_ PCUNICODE_STRING _Out_opt_ PUSHORT _Inout_opt_ PUNICODE_STRING Value
Definition: wdfregistry.h:413
_In_ WDF_WMI_PROVIDER_CONTROL Control
Definition: wdfwmi.h:166
NTKERNELAPI VOID NTAPI WRITE_REGISTER_UCHAR(IN PUCHAR Register, IN UCHAR Value)
NTKERNELAPI VOID NTAPI READ_REGISTER_BUFFER_USHORT(IN PUSHORT Register, IN PUSHORT Buffer, IN ULONG Count)
NTKERNELAPI VOID NTAPI READ_REGISTER_BUFFER_ULONG(IN PULONG Register, IN PULONG Buffer, IN ULONG Count)
NTKERNELAPI VOID NTAPI WRITE_REGISTER_BUFFER_ULONG(IN PULONG Register, IN PULONG Buffer, IN ULONG Count)
NTKERNELAPI VOID NTAPI WRITE_REGISTER_BUFFER_USHORT(IN PUSHORT Register, IN PUSHORT Buffer, IN ULONG Count)
NTKERNELAPI UCHAR NTAPI READ_REGISTER_UCHAR(IN PUCHAR Register)
struct _SCATTER_GATHER_LIST SCATTER_GATHER_LIST
Definition: iotypes.h:2206
_Must_inspect_result_ typedef _In_ PHYSICAL_ADDRESS _In_ LARGE_INTEGER ByteCount
Definition: iotypes.h:1099
_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
#define IsNEC_98
Definition: ketypes.h:963
_In_opt_ PVOID _In_opt_ PVOID _In_opt_ PVOID SystemArgument2
Definition: ketypes.h:741