ReactOS 0.4.16-dev-197-g92996da
readwrite.c File Reference
#include "precomp.h"
#include <debug.h>
Include dependency graph for readwrite.c:

Go to the source code of this file.

Functions

static IO_ALLOCATION_ACTION NTAPI MapRegisterCallback (PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID MapRegisterBase, PVOID Context)
 
NTSTATUS NTAPI ReadWrite (PDEVICE_OBJECT DeviceObject, PIRP Irp)
 
static VOID NTAPI RWFreeAdapterChannel (PADAPTER_OBJECT AdapterObject)
 
NTSTATUS NTAPI RWDetermineMediaType (PDRIVE_INFO DriveInfo, BOOLEAN OneShot)
 
static NTSTATUS NTAPI RWSeekToCylinder (PDRIVE_INFO DriveInfo, UCHAR Cylinder)
 
static NTSTATUS NTAPI RWComputeCHS (PDRIVE_INFO IN DriveInfo, ULONG IN DiskByteOffset, PUCHAR OUT Cylinder, PUCHAR OUT Head, PUCHAR OUT Sector)
 
VOID NTAPI ReadWritePassive (PDRIVE_INFO DriveInfo, PIRP Irp)
 

Function Documentation

◆ MapRegisterCallback()

static IO_ALLOCATION_ACTION NTAPI MapRegisterCallback ( PDEVICE_OBJECT  DeviceObject,
PIRP  Irp,
PVOID  MapRegisterBase,
PVOID  Context 
)
static

Definition at line 60 of file readwrite.c.

75{
79
80 TRACE_(FLOPPY, "MapRegisterCallback Called\n");
81
82 ControllerInfo->MapRegisterBase = MapRegisterBase;
83 KeSetEvent(&ControllerInfo->SynchEvent, 0, FALSE);
84
85 return KeepObject;
86}
_In_ PIRP Irp
Definition: csq.h:116
#define FALSE
Definition: types.h:117
#define TRACE_(x)
Definition: compat.h:76
struct _CONTROLLER_INFO * PCONTROLLER_INFO
#define KeSetEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:476
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:317
KEVENT SynchEvent
Definition: floppy.h:74
PVOID MapRegisterBase
Definition: floppy.h:72
_In_ PDEVICE_OBJECT DeviceObject
Definition: wdfdevice.h:2055
_Inout_ struct _IRP _In_ PVOID MapRegisterBase
Definition: iotypes.h:213
@ KeepObject
Definition: iotypes.h:202

Referenced by ReadWritePassive().

◆ ReadWrite()

NTSTATUS NTAPI ReadWrite ( PDEVICE_OBJECT  DeviceObject,
PIRP  Irp 
)

Definition at line 90 of file readwrite.c.

105{
106 TRACE_(FLOPPY, "ReadWrite called\n");
107
109 ASSERT(Irp);
110
111 if(!Irp->MdlAddress)
112 {
113 WARN_(FLOPPY, "ReadWrite(): MDL not found in IRP - Completing with STATUS_INVALID_PARAMETER\n");
114 Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
115 Irp->IoStatus.Information = 0;
118 }
119
120 /*
121 * Queue the irp to the thread.
122 * The de-queue thread will look in DriverContext[0] for the Device Object.
123 */
124 Irp->Tail.Overlay.DriverContext[0] = DeviceObject;
126
127 return STATUS_PENDING;
128}
NTKERNELAPI VOID NTAPI IoCsqInsertIrp(_Inout_ PIO_CSQ Csq, _Inout_ PIRP Irp, _Out_opt_ PIO_CSQ_IRP_CONTEXT Context)
Insert an IRP into the CSQ.
Definition: csq.c:177
IO_CSQ Csq
Definition: csqrtns.c:46
#define STATUS_PENDING
Definition: d3dkmdt.h:43
#define NULL
Definition: types.h:112
#define ASSERT(a)
Definition: mode.c:44
#define IoCompleteRequest
Definition: irp.c:1240
#define WARN_(ch,...)
Definition: debug.h:157
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define IO_NO_INCREMENT
Definition: iotypes.h:598

◆ ReadWritePassive()

VOID NTAPI ReadWritePassive ( PDRIVE_INFO  DriveInfo,
PIRP  Irp 
)

Definition at line 403 of file readwrite.c.

431{
436 ULONG DiskByteOffset;
439 BOOLEAN DiskChanged;
440 ULONG_PTR TransferByteOffset;
441 UCHAR Gap;
442
443 PAGED_CODE();
444
445 TRACE_(FLOPPY, "ReadWritePassive called to %s 0x%x bytes from offset 0x%x\n",
446 (Stack->MajorFunction == IRP_MJ_READ ? "read" : "write"),
447 (Stack->MajorFunction == IRP_MJ_READ ? Stack->Parameters.Read.Length : Stack->Parameters.Write.Length),
448 (Stack->MajorFunction == IRP_MJ_READ ? Stack->Parameters.Read.ByteOffset.u.LowPart :
449 Stack->Parameters.Write.ByteOffset.u.LowPart));
450
451 /* Default return codes */
452 Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
453 Irp->IoStatus.Information = 0;
454
455 /*
456 * Check to see if the volume needs to be verified. If so,
457 * we can get out of here quickly.
458 */
460 {
461 INFO_(FLOPPY, "ReadWritePassive(): DO_VERIFY_VOLUME set; Completing with STATUS_VERIFY_REQUIRED\n");
462 Irp->IoStatus.Status = STATUS_VERIFY_REQUIRED;
464 return;
465 }
466
467 /*
468 * Check the change line, and if it's set, return
469 */
470 StartMotor(DriveInfo);
471 if(HwDiskChanged(DeviceObject->DeviceExtension, &DiskChanged) != STATUS_SUCCESS)
472 {
473 WARN_(FLOPPY, "ReadWritePassive(): unable to detect disk change; Completing with STATUS_UNSUCCESSFUL\n");
475 StopMotor(DriveInfo->ControllerInfo);
476 return;
477 }
478
479 if(DiskChanged)
480 {
481 INFO_(FLOPPY, "ReadWritePhase1(): detected disk changed: signalling media change and completing\n");
482
483 /* The following call sets IoStatus.Status and IoStatus.Information */
485 ResetChangeFlag(DriveInfo);
486
488 StopMotor(DriveInfo->ControllerInfo);
489 return;
490 }
491
492 /*
493 * Figure out the media type, if we don't know it already
494 */
495 if(DriveInfo->DiskGeometry.MediaType == Unknown)
496 {
497 if(RWDetermineMediaType(DriveInfo, FALSE) != STATUS_SUCCESS)
498 {
499 WARN_(FLOPPY, "ReadWritePassive(): unable to determine media type; completing with STATUS_UNSUCCESSFUL\n");
501 StopMotor(DriveInfo->ControllerInfo);
502 return;
503 }
504
505 if(DriveInfo->DiskGeometry.MediaType == Unknown)
506 {
507 WARN_(FLOPPY, "ReadWritePassive(): Unknown media in drive; completing with STATUS_UNRECOGNIZED_MEDIA\n");
508 Irp->IoStatus.Status = STATUS_UNRECOGNIZED_MEDIA;
510 StopMotor(DriveInfo->ControllerInfo);
511 return;
512 }
513 }
514
515 /* Set up parameters for read or write */
516 if(Stack->MajorFunction == IRP_MJ_READ)
517 {
518 Length = Stack->Parameters.Read.Length;
519 DiskByteOffset = Stack->Parameters.Read.ByteOffset.u.LowPart;
521 }
522 else
523 {
524 Length = Stack->Parameters.Write.Length;
525 DiskByteOffset = Stack->Parameters.Write.ByteOffset.u.LowPart;
527 }
528
529 /*
530 * FIXME:
531 * FloppyDeviceData.ReadWriteGapLength specify the value for the physical drive.
532 * We should set this value depend on the format of the inserted disk and possible
533 * depend on the request (read or write). A value of 0 results in one rotation
534 * between the sectors (7.2sec for reading a track).
535 */
536 Gap = DriveInfo->FloppyDeviceData.ReadWriteGapLength;
537
538 /*
539 * Set up DMA transfer
540 *
541 * This is as good of a place as any to document something that used to confuse me
542 * greatly (and I even wrote some of the kernel's DMA code, so if it confuses me, it
543 * probably confuses at least a couple of other people too).
544 *
545 * MmGetMdlVirtualAddress() returns the virtual address, as mapped in the buffer's original
546 * process context, of the MDL. In other words: say you start with a buffer at address X, then
547 * you build an MDL out of that buffer called Mdl. If you call MmGetMdlVirtualAddress(Mdl), it
548 * will return X.
549 *
550 * There are two parameters that the function looks at to produce X again, given the MDL: the
551 * first is the StartVa, which is the base virtual address of the page that the buffer starts
552 * in. If your buffer's virtual address is 0x12345678, StartVa will be 0x12345000, assuming 4K pages
553 * (which is (almost) always the case on x86). Note well: this address is only valid in the
554 * process context that you initially built the MDL from. The physical pages that make up
555 * the MDL might perhaps be mapped in other process contexts too (or even in the system space,
556 * above 0x80000000 (default; 0xc0000000 on current ReactOS or /3GB Windows)), but it will
557 * (possibly) be mapped at a different address.
558 *
559 * The second parameter is the ByteOffset. Given an original buffer address of 0x12345678,
560 * the ByteOffset would be 0x678. Because MDLs can only describe full pages (and therefore
561 * StartVa always points to the start address of a page), the ByteOffset must be used to
562 * find the real start of the buffer.
563 *
564 * In general, if you add the StartVa and ByteOffset together, you get back your original
565 * buffer pointer, which you are free to use if you're sure you're in the right process
566 * context. You could tell by accessing the (hidden and not-to-be-used) Process member of
567 * the MDL, but in general, if you have to ask whether or not you are in the right context,
568 * then you shouldn't be using this address for anything anyway. There are also security implications
569 * (big ones, really, I wouldn't kid about this) to directly accessing a user's buffer by VA, so
570 * Don't Do That.
571 *
572 * There is a somewhat weird but very common use of the virtual address associated with a MDL
573 * that pops up often in the context of DMA. DMA APIs (particularly MapTransfer()) need to
574 * know where the memory is that they should DMA into and out of. This memory is described
575 * by a MDL. The controller eventually needs to know a physical address on the host side,
576 * which is generally a 32-bit linear address (on x86), and not just a page address. Therefore,
577 * the DMA APIs look at the ByteOffset field of the MDL to reconstruct the real address that
578 * should be programmed into the DMA controller.
579 *
580 * It is often the case that a transfer needs to be broken down over more than one DMA operation,
581 * particularly when it is a big transfer and the HAL doesn't give you enough map registers
582 * to map the whole thing at once. Therefore, the APIs need a way to tell how far into the MDL
583 * they should look to transfer the next chunk of bytes. Now, Microsoft could have designed
584 * MapTransfer to take a "MDL offset" argument, starting with 0, for how far into the buffer to
585 * start, but it didn't. Instead, MapTransfer asks for the virtual address of the MDL as an "index" into
586 * the MDL. The way it computes how far into the page to start the transfer is by masking off all but
587 * the bottom 12 bits (on x86) of the number you supply as the CurrentVa and using *that* as the
588 * ByteOffset instead of the one in the MDL. (OK, this varies a bit by OS and version, but this
589 * is the effect).
590 *
591 * In other words, you get a number back from MmGetMdlVirtualAddress that represents the start of your
592 * buffer, and you pass it to the first MapTransfer call. Then, for each successive operation
593 * on the same buffer, you increment that address to point to the next spot in the MDL that
594 * you want to DMA to/from. The fact that the virtual address you're manipulating is probably not
595 * mapped into the process context that you're running in is irrelevant, since it's only being
596 * used to index into the MDL.
597 */
598
599 /* Get map registers for DMA */
601 Status = IoAllocateAdapterChannel(DriveInfo->ControllerInfo->AdapterObject, DeviceObject,
602 DriveInfo->ControllerInfo->MapRegisters, MapRegisterCallback, DriveInfo->ControllerInfo);
604
606 {
607 WARN_(FLOPPY, "ReadWritePassive(): unable allocate an adapter channel; completing with STATUS_UNSUCCESSFUL\n");
609 StopMotor(DriveInfo->ControllerInfo);
610 return ;
611 }
612
613
614 /*
615 * Read from (or write to) the device
616 *
617 * This has to be called in a loop, as you can only transfer data to/from a single track at
618 * a time.
619 */
620 TransferByteOffset = 0;
621 while(TransferByteOffset < Length)
622 {
623 UCHAR Cylinder;
624 UCHAR Head;
625 UCHAR StartSector;
626 ULONG CurrentTransferBytes;
627 UCHAR CurrentTransferSectors;
628
629 INFO_(FLOPPY, "ReadWritePassive(): iterating in while (TransferByteOffset = 0x%x of 0x%x total) - allocating %d registers\n",
630 TransferByteOffset, Length, DriveInfo->ControllerInfo->MapRegisters);
631
632 KeClearEvent(&DriveInfo->ControllerInfo->SynchEvent);
633
634 /*
635 * Compute starting CHS
636 */
637 if(RWComputeCHS(DriveInfo, DiskByteOffset+TransferByteOffset, &Cylinder, &Head, &StartSector) != STATUS_SUCCESS)
638 {
639 WARN_(FLOPPY, "ReadWritePassive(): unable to compute CHS; completing with STATUS_UNSUCCESSFUL\n");
640 RWFreeAdapterChannel(DriveInfo->ControllerInfo->AdapterObject);
642 StopMotor(DriveInfo->ControllerInfo);
643 return;
644 }
645
646 /*
647 * Seek to the right track
648 */
649 if(!DriveInfo->ControllerInfo->ImpliedSeeks)
650 {
651 if(RWSeekToCylinder(DriveInfo, Cylinder) != STATUS_SUCCESS)
652 {
653 WARN_(FLOPPY, "ReadWritePassive(): unable to seek; completing with STATUS_UNSUCCESSFUL\n");
654 RWFreeAdapterChannel(DriveInfo->ControllerInfo->AdapterObject);
656 StopMotor(DriveInfo->ControllerInfo);
657 return ;
658 }
659 }
660
661 /*
662 * Compute last sector
663 *
664 * We can only ask for a transfer up to the end of the track. Then we have to re-seek and do more.
665 * TODO: Support the MT bit
666 */
667 INFO_(FLOPPY, "ReadWritePassive(): computing number of sectors to transfer (StartSector 0x%x): ", StartSector);
668
669 /* 1-based sector number */
670 if( (((DriveInfo->DiskGeometry.TracksPerCylinder - Head) * DriveInfo->DiskGeometry.SectorsPerTrack - StartSector) + 1 ) <
671 (Length - TransferByteOffset) / DriveInfo->DiskGeometry.BytesPerSector)
672 {
673 CurrentTransferSectors = (UCHAR)((DriveInfo->DiskGeometry.TracksPerCylinder - Head) * DriveInfo->DiskGeometry.SectorsPerTrack - StartSector) + 1;
674 }
675 else
676 {
677 CurrentTransferSectors = (UCHAR)((Length - TransferByteOffset) / DriveInfo->DiskGeometry.BytesPerSector);
678 }
679
680 INFO_(FLOPPY, "0x%x\n", CurrentTransferSectors);
681
682 CurrentTransferBytes = CurrentTransferSectors * DriveInfo->DiskGeometry.BytesPerSector;
683
684 /*
685 * Adjust to map registers
686 * BUG: Does this take into account page crossings?
687 */
688 INFO_(FLOPPY, "ReadWritePassive(): Trying to transfer 0x%x bytes\n", CurrentTransferBytes);
689
690 ASSERT(CurrentTransferBytes);
691
692 if(BYTES_TO_PAGES(CurrentTransferBytes) > DriveInfo->ControllerInfo->MapRegisters)
693 {
694 CurrentTransferSectors = (UCHAR)((DriveInfo->ControllerInfo->MapRegisters * PAGE_SIZE) /
695 DriveInfo->DiskGeometry.BytesPerSector);
696
697 CurrentTransferBytes = CurrentTransferSectors * DriveInfo->DiskGeometry.BytesPerSector;
698
699 INFO_(FLOPPY, "ReadWritePassive: limiting transfer to 0x%x bytes (0x%x sectors) due to map registers\n",
700 CurrentTransferBytes, CurrentTransferSectors);
701 }
702
703 /* set up this round's dma operation */
704 /* param 2 is ReadOperation --> opposite of WriteToDevice that IoMapTransfer takes. BAD MS. */
705 KeFlushIoBuffers(Irp->MdlAddress, !WriteToDevice, TRUE);
706
707 IoMapTransfer(DriveInfo->ControllerInfo->AdapterObject, Irp->MdlAddress,
708 DriveInfo->ControllerInfo->MapRegisterBase,
709 (PVOID)((ULONG_PTR)MmGetMdlVirtualAddress(Irp->MdlAddress) + TransferByteOffset),
710 &CurrentTransferBytes, WriteToDevice);
711
712 /*
713 * Read or Write
714 */
715 KeClearEvent(&DriveInfo->ControllerInfo->SynchEvent);
716
717 /* Issue the read/write command to the controller. Note that it expects the opposite of WriteToDevice. */
718 if(HwReadWriteData(DriveInfo->ControllerInfo, !WriteToDevice, DriveInfo->UnitNumber, Cylinder, Head, StartSector,
719 DriveInfo->BytesPerSectorCode, DriveInfo->DiskGeometry.SectorsPerTrack, Gap, 0xff) != STATUS_SUCCESS)
720 {
721 WARN_(FLOPPY, "ReadWritePassive(): HwReadWriteData returned failure; unable to read; completing with STATUS_UNSUCCESSFUL\n");
722 RWFreeAdapterChannel(DriveInfo->ControllerInfo->AdapterObject);
724 StopMotor(DriveInfo->ControllerInfo);
725 return ;
726 }
727
728 INFO_(FLOPPY, "ReadWritePassive(): HwReadWriteData returned -- waiting on event\n");
729
730 /*
731 * At this point, we block and wait for an interrupt
732 * FIXME: this seems to take too long
733 */
735
736 /* Read is complete; flush & free adapter channel */
737 IoFlushAdapterBuffers(DriveInfo->ControllerInfo->AdapterObject, Irp->MdlAddress,
738 DriveInfo->ControllerInfo->MapRegisterBase,
739 (PVOID)((ULONG_PTR)MmGetMdlVirtualAddress(Irp->MdlAddress) + TransferByteOffset),
740 CurrentTransferBytes, WriteToDevice);
741
742 /* Read the results from the drive */
744 {
745 WARN_(FLOPPY, "ReadWritePassive(): HwReadWriteResult returned failure; unable to read; completing with STATUS_UNSUCCESSFUL\n");
747 RWFreeAdapterChannel(DriveInfo->ControllerInfo->AdapterObject);
749 StopMotor(DriveInfo->ControllerInfo);
750 return ;
751 }
752
753 TransferByteOffset += CurrentTransferBytes;
754 }
755
756 RWFreeAdapterChannel(DriveInfo->ControllerInfo->AdapterObject);
757
758 /* That's all folks! */
759 INFO_(FLOPPY, "ReadWritePassive(): success; Completing with STATUS_SUCCESS\n");
760 Irp->IoStatus.Status = STATUS_SUCCESS;
761 Irp->IoStatus.Information = Length;
763 StopMotor(DriveInfo->ControllerInfo);
764}
static PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(PIRP Irp)
#define PAGED_CODE()
unsigned char BOOLEAN
LONG NTSTATUS
Definition: precomp.h:26
return
Definition: dirsup.c:529
_In_ PSCSI_REQUEST_BLOCK _In_opt_ PVOID _In_ ULONG _In_ BOOLEAN WriteToDevice
Definition: cdrom.h:992
#define TRUE
Definition: types.h:120
NTSTATUS NTAPI HwReadWriteResult(PCONTROLLER_INFO ControllerInfo)
Definition: hardware.c:462
VOID NTAPI HwDumpRegisters(PCONTROLLER_INFO ControllerInfo)
Definition: hardware.c:1029
NTSTATUS NTAPI HwReadWriteData(PCONTROLLER_INFO ControllerInfo, BOOLEAN Read, UCHAR Unit, UCHAR Cylinder, UCHAR Head, UCHAR Sector, UCHAR BytesPerSector, UCHAR EndOfTrack, UCHAR Gap3Length, UCHAR DataLength)
Definition: hardware.c:322
NTSTATUS NTAPI HwDiskChanged(PDRIVE_INFO DriveInfo, PBOOLEAN DiskChanged)
Definition: hardware.c:785
static IO_ALLOCATION_ACTION NTAPI MapRegisterCallback(PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID MapRegisterBase, PVOID Context)
Definition: readwrite.c:60
static NTSTATUS NTAPI RWComputeCHS(PDRIVE_INFO IN DriveInfo, ULONG IN DiskByteOffset, PUCHAR OUT Cylinder, PUCHAR OUT Head, PUCHAR OUT Sector)
Definition: readwrite.c:346
static VOID NTAPI RWFreeAdapterChannel(PADAPTER_OBJECT AdapterObject)
Definition: readwrite.c:132
NTSTATUS NTAPI RWDetermineMediaType(PDRIVE_INFO DriveInfo, BOOLEAN OneShot)
Definition: readwrite.c:153
static NTSTATUS NTAPI RWSeekToCylinder(PDRIVE_INFO DriveInfo, UCHAR Cylinder)
Definition: readwrite.c:281
UCHAR KIRQL
Definition: env_spec_w32.h:591
#define KeRaiseIrql(irql, oldIrql)
Definition: env_spec_w32.h:597
#define DO_VERIFY_VOLUME
Definition: env_spec_w32.h:393
#define PAGE_SIZE
Definition: env_spec_w32.h:49
#define KeLowerIrql(oldIrql)
Definition: env_spec_w32.h:602
#define DISPATCH_LEVEL
Definition: env_spec_w32.h:696
VOID NTAPI KeClearEvent(IN PKEVENT Event)
Definition: eventobj.c:22
NTSTATUS NTAPI WaitForControllerInterrupt(PCONTROLLER_INFO ControllerInfo, PLARGE_INTEGER Timeout)
Definition: floppy.c:163
NTSTATUS NTAPI ResetChangeFlag(PDRIVE_INFO DriveInfo)
Definition: floppy.c:291
VOID NTAPI SignalMediaChanged(PDEVICE_OBJECT DeviceObject, PIRP Irp)
Definition: floppy.c:1097
VOID NTAPI StartMotor(PDRIVE_INFO DriveInfo)
Definition: floppy.c:96
VOID NTAPI StopMotor(PCONTROLLER_INFO ControllerInfo)
Definition: floppy.c:135
Status
Definition: gdiplustypes.h:25
BOOLEAN NTAPI IoFlushAdapterBuffers(IN PADAPTER_OBJECT AdapterObject, IN PMDL Mdl, IN PVOID MapRegisterBase, IN PVOID CurrentVa, IN ULONG Length, IN BOOLEAN WriteToDevice)
Definition: dma.c:127
PHYSICAL_ADDRESS NTAPI IoMapTransfer(IN PADAPTER_OBJECT AdapterObject, IN PMDL Mdl, IN PVOID MapRegisterBase, IN PVOID CurrentVa, IN OUT PULONG Length, IN BOOLEAN WriteToDevice)
Definition: dma.c:144
@ Unknown
Definition: i8042prt.h:114
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:102
NTSTATUS NTAPI IoAllocateAdapterChannel(IN PADAPTER_OBJECT AdapterObject, IN PDEVICE_OBJECT DeviceObject, IN ULONG NumberOfMapRegisters, IN PDRIVER_CONTROL ExecutionRoutine, IN PVOID Context)
Definition: adapter.c:30
#define IRP_MJ_READ
Definition: rdpdr.c:46
#define INFO_(ch,...)
Definition: debug.h:159
#define KeFlushIoBuffers(_Mdl, _ReadOperation, _DmaOperation)
Definition: ke.h:174
#define STATUS_SUCCESS
Definition: shellext.h:65
MEDIA_TYPE MediaType
Definition: ntdddisk.h:401
ULONG TracksPerCylinder
Definition: ntdddisk.h:402
ULONG SectorsPerTrack
Definition: ntdddisk.h:403
ULONG BytesPerSector
Definition: ntdddisk.h:404
struct _CONTROLLER_INFO * ControllerInfo
Definition: fdc.h:23
PDEVICE_OBJECT DeviceObject
Definition: fdc.h:26
CM_FLOPPY_DEVICE_DATA FloppyDeviceData
Definition: fdc.h:27
UCHAR BytesPerSectorCode
Definition: floppy.h:50
DISK_GEOMETRY DiskGeometry
Definition: floppy.h:49
UCHAR UnitNumber
Definition: fdc.h:24
uint32_t ULONG_PTR
Definition: typedefs.h:65
uint32_t ULONG
Definition: typedefs.h:59
#define STATUS_UNRECOGNIZED_MEDIA
Definition: udferr_usr.h:142
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
#define STATUS_VERIFY_REQUIRED
Definition: udferr_usr.h:130
_In_ WDFREQUEST _In_ PIO_STACK_LOCATION Stack
Definition: wdfrequest.h:639
#define SL_OVERRIDE_VERIFY_VOLUME
Definition: iotypes.h:1823
#define IO_DISK_INCREMENT
Definition: iotypes.h:600
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:778
#define MmGetMdlVirtualAddress(_Mdl)
#define BYTES_TO_PAGES(Size)
unsigned char UCHAR
Definition: xmlstorage.h:181

Referenced by QueueThread().

◆ RWComputeCHS()

static NTSTATUS NTAPI RWComputeCHS ( PDRIVE_INFO IN  DriveInfo,
ULONG IN  DiskByteOffset,
PUCHAR OUT  Cylinder,
PUCHAR OUT  Head,
PUCHAR OUT  Sector 
)
static

Definition at line 346 of file readwrite.c.

367{
368 ULONG AbsoluteSector;
369 UCHAR SectorsPerCylinder = (UCHAR)DriveInfo->DiskGeometry.SectorsPerTrack * (UCHAR)DriveInfo->DiskGeometry.TracksPerCylinder;
370
371 TRACE_(FLOPPY, "RWComputeCHS: Called with offset 0x%x\n", DiskByteOffset);
372
373 /* First calculate the 1-based "absolute sector" based on the byte offset */
374 ASSERT(!(DiskByteOffset % DriveInfo->DiskGeometry.BytesPerSector)); /* FIXME: Only handle full sector transfers atm */
375
376 /* AbsoluteSector is zero-based to make the math a little easier */
377 AbsoluteSector = DiskByteOffset / DriveInfo->DiskGeometry.BytesPerSector; /* Num full sectors */
378
379 /* Cylinder number is floor(AbsoluteSector / SectorsPerCylinder) */
380 *Cylinder = (CHAR)(AbsoluteSector / SectorsPerCylinder);
381
382 /* Head number is 0 if the sector within the cylinder < SectorsPerTrack; 1 otherwise */
383 *Head = AbsoluteSector % SectorsPerCylinder < DriveInfo->DiskGeometry.SectorsPerTrack ? 0 : 1;
384
385 /*
386 * Sector number is the sector within the cylinder if on head 0; that minus SectorsPerTrack if it's on head 1
387 * (lots of casts to placate msvc). 1-based!
388 */
389 *Sector = ((UCHAR)(AbsoluteSector % SectorsPerCylinder) + 1) - ((*Head) * (UCHAR)DriveInfo->DiskGeometry.SectorsPerTrack);
390
391 INFO_(FLOPPY, "RWComputeCHS: offset 0x%x is c:0x%x h:0x%x s:0x%x\n", DiskByteOffset, *Cylinder, *Head, *Sector);
392
393 /* Sanity checking */
394 ASSERT(*Cylinder <= DriveInfo->DiskGeometry.Cylinders.QuadPart);
395 ASSERT(*Head <= DriveInfo->DiskGeometry.TracksPerCylinder);
396 ASSERT(*Sector <= DriveInfo->DiskGeometry.SectorsPerTrack);
397
398 return STATUS_SUCCESS;
399}
#define CHAR(Char)

Referenced by ReadWritePassive().

◆ RWDetermineMediaType()

NTSTATUS NTAPI RWDetermineMediaType ( PDRIVE_INFO  DriveInfo,
BOOLEAN  OneShot 
)

Definition at line 153 of file readwrite.c.

169{
170 UCHAR HeadLoadTime;
171 UCHAR HeadUnloadTime;
172 UCHAR StepRateTime;
174
175 PAGED_CODE();
176
177 TRACE_(FLOPPY, "RWDetermineMediaType called\n");
178
179 /*
180 * This algorithm assumes that a 1.44MB floppy is in the drive. If it's not,
181 * it works backwards until the read works unless OneShot try is asked.
182 * Note that only 1.44 has been tested at all.
183 */
184
185 Timeout.QuadPart = -10000000; /* 1 second. Is that enough? */
186
187 do
188 {
189 int i;
191
192 /* Program data rate */
194 {
195 WARN_(FLOPPY, "RWDetermineMediaType(): unable to set data rate\n");
196 return STATUS_UNSUCCESSFUL;
197 }
198
199 /* Specify */
200 HeadLoadTime = SPECIFY_HLT_500K;
201 HeadUnloadTime = SPECIFY_HUT_500K;
202 StepRateTime = SPECIFY_SRT_500K;
203
204 /* Don't disable DMA --> enable dma (dumb & confusing) */
205 if(HwSpecify(DriveInfo->ControllerInfo, HeadLoadTime, HeadUnloadTime, StepRateTime, FALSE) != STATUS_SUCCESS)
206 {
207 WARN_(FLOPPY, "RWDetermineMediaType(): specify failed\n");
208 return STATUS_UNSUCCESSFUL;
209 }
210
211 /* clear any spurious interrupts in preparation for recalibrate */
212 KeClearEvent(&DriveInfo->ControllerInfo->SynchEvent);
213
214 /* Recalibrate --> head over first track */
215 for(i=0; i < 2; i++)
216 {
217 NTSTATUS RecalStatus;
218
219 if(HwRecalibrate(DriveInfo) != STATUS_SUCCESS)
220 {
221 WARN_(FLOPPY, "RWDetermineMediaType(): Recalibrate failed\n");
222 return STATUS_UNSUCCESSFUL;
223 }
224
225 /* Wait for the recalibrate to finish */
227
228 RecalStatus = HwRecalibrateResult(DriveInfo->ControllerInfo);
229
230 if(RecalStatus == STATUS_SUCCESS)
231 break;
232
233 if(i == 1) /* failed for 2nd time */
234 {
235 WARN_(FLOPPY, "RWDetermineMediaType(): RecalibrateResult failed\n");
236 return STATUS_UNSUCCESSFUL;
237 }
238 }
239
240 /* clear any spurious interrupts */
241 KeClearEvent(&DriveInfo->ControllerInfo->SynchEvent);
242
243 /* Try to read an ID */
244 if(HwReadId(DriveInfo, 0) != STATUS_SUCCESS) /* read the first ID we find, from head 0 */
245 {
246 WARN_(FLOPPY, "RWDetermineMediaType(): ReadId failed\n");
247 return STATUS_UNSUCCESSFUL; /* if we can't even write to the controller, it's hopeless */
248 }
249
250 /* Wait for the ReadID to finish */
252
254 {
255 WARN_(FLOPPY, "RWDetermineMediaType(): ReadIdResult failed; continuing\n");
256 if (OneShot)
257 break;
258 else
259 continue;
260 }
261
262 /* Found the media; populate the geometry now */
263 WARN_(FLOPPY, "Hardcoded media type!\n");
264 INFO_(FLOPPY, "RWDetermineMediaType(): Found 1.44 media; returning success\n");
271 return STATUS_SUCCESS;
272 }
273 while(TRUE);
274
275 TRACE_(FLOPPY, "RWDetermineMediaType(): failed to find media\n");
277}
#define STATUS_TIMEOUT
Definition: d3dkmdt.h:49
NTSTATUS NTAPI HwRecalibrateResult(PCONTROLLER_INFO ControllerInfo)
Definition: hardware.c:394
NTSTATUS NTAPI HwSetDataRate(PCONTROLLER_INFO ControllerInfo, UCHAR DataRate)
Definition: hardware.c:204
NTSTATUS NTAPI HwRecalibrate(PDRIVE_INFO DriveInfo)
Definition: hardware.c:503
NTSTATUS NTAPI HwSpecify(PCONTROLLER_INFO ControllerInfo, UCHAR HeadLoadTime, UCHAR HeadUnloadTime, UCHAR StepRateTime, BOOLEAN NonDma)
Definition: hardware.c:925
NTSTATUS NTAPI HwReadId(PDRIVE_INFO DriveInfo, UCHAR Head)
Definition: hardware.c:576
NTSTATUS NTAPI HwReadIdResult(PCONTROLLER_INFO ControllerInfo, PUCHAR CurCylinder, PUCHAR CurHead)
Definition: hardware.c:864
#define HW_512_BYTES_PER_SECTOR
Definition: hardware.h:259
#define SPECIFY_HLT_500K
Definition: hardware.h:219
#define SPECIFY_HUT_500K
Definition: hardware.h:223
#define DRSR_DSEL_500KBPS
Definition: hardware.h:106
#define SPECIFY_SRT_500K
Definition: hardware.h:227
#define GEOMETRY_144_SECTORSPERTRACK
Definition: floppy.h:126
#define GEOMETRY_144_MEDIATYPE
Definition: floppy.h:123
#define GEOMETRY_144_CYLINDERS
Definition: floppy.h:124
#define GEOMETRY_144_TRACKSPERCYLINDER
Definition: floppy.h:125
#define GEOMETRY_144_BYTESPERSECTOR
Definition: floppy.h:127
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
static ULONG Timeout
Definition: ping.c:61
LARGE_INTEGER Cylinders
Definition: ntdddisk.h:400
LONGLONG QuadPart
Definition: typedefs.h:114

Referenced by AddControllers(), and ReadWritePassive().

◆ RWFreeAdapterChannel()

static VOID NTAPI RWFreeAdapterChannel ( PADAPTER_OBJECT  AdapterObject)
static

Definition at line 132 of file readwrite.c.

141{
142 KIRQL Irql;
143
145
147 IoFreeAdapterChannel(AdapterObject);
149}
_Out_ PKIRQL Irql
Definition: csq.h:179
#define KeGetCurrentIrql()
Definition: env_spec_w32.h:706
VOID NTAPI IoFreeAdapterChannel(IN PADAPTER_OBJECT AdapterObject)
Definition: dma.c:103

Referenced by ReadWritePassive().

◆ RWSeekToCylinder()

static NTSTATUS NTAPI RWSeekToCylinder ( PDRIVE_INFO  DriveInfo,
UCHAR  Cylinder 
)
static

Definition at line 281 of file readwrite.c.

293{
294 UCHAR CurCylinder;
295
296 PAGED_CODE();
297
298 TRACE_(FLOPPY, "RWSeekToCylinder called drive 0x%p cylinder %d\n", DriveInfo, Cylinder);
299
300 /* Clear any spurious interrupts */
301 KeClearEvent(&DriveInfo->ControllerInfo->SynchEvent);
302
303 /* queue seek command */
304 if(HwSeek(DriveInfo, Cylinder) != STATUS_SUCCESS)
305 {
306 WARN_(FLOPPY, "RWSeekToTrack(): unable to seek\n");
307 return STATUS_UNSUCCESSFUL;
308 }
309
311
313 {
314 WARN_(FLOPPY, "RWSeekToTrack(): unable to get seek results\n");
315 return STATUS_UNSUCCESSFUL;
316 }
317
318 /* read ID mark from head 0 to verify */
319 if(HwReadId(DriveInfo, 0) != STATUS_SUCCESS)
320 {
321 WARN_(FLOPPY, "RWSeekToTrack(): unable to queue ReadId\n");
322 return STATUS_UNSUCCESSFUL;
323 }
324
326
327 if(HwReadIdResult(DriveInfo->ControllerInfo, &CurCylinder, NULL) != STATUS_SUCCESS)
328 {
329 WARN_(FLOPPY, "RWSeekToTrack(): unable to get ReadId result\n");
330 return STATUS_UNSUCCESSFUL;
331 }
332
333 if(CurCylinder != Cylinder)
334 {
335 WARN_(FLOPPY, "RWSeekToTrack(): Seek to track failed; current cylinder is 0x%x\n", CurCylinder);
336 return STATUS_UNSUCCESSFUL;
337 }
338
339 INFO_(FLOPPY, "RWSeekToCylinder: returning successfully, now on cyl %d\n", Cylinder);
340
341 return STATUS_SUCCESS;
342}
NTSTATUS NTAPI HwSeek(PDRIVE_INFO DriveInfo, UCHAR Cylinder)
Definition: hardware.c:659
NTSTATUS NTAPI HwSenseInterruptStatus(PCONTROLLER_INFO ControllerInfo)
Definition: hardware.c:539

Referenced by ReadWritePassive().