From 29d063166bda7c17fd90dc4bbaa47435500e07b2 Mon Sep 17 00:00:00 2001 From: Vizzini Date: Fri, 12 Mar 2004 03:36:32 +0000 Subject: [PATCH] - Added arc path support - Fixed disk change support - Fixed the priority boosts to be saner - Fixed some start/stop motor timing bugs - Figured out the Real Deal with Model 30 support (I hope...) - Cleaned up DMA init a bit - Improved return values, freed things on fail, etc - General code cleanup svn path=/trunk/; revision=8660 --- reactos/drivers/storage/floppy/floppy.c | 197 +++++++++++---------- reactos/drivers/storage/floppy/floppy.h | 18 +- reactos/drivers/storage/floppy/hardware.c | 53 +----- reactos/drivers/storage/floppy/hardware.h | 1 + reactos/drivers/storage/floppy/ioctl.c | 9 +- reactos/drivers/storage/floppy/ioctl.h | 1 + reactos/drivers/storage/floppy/readwrite.c | 37 ++-- 7 files changed, 157 insertions(+), 159 deletions(-) diff --git a/reactos/drivers/storage/floppy/floppy.c b/reactos/drivers/storage/floppy/floppy.c index 0428a781f3c..27c34ab1198 100644 --- a/reactos/drivers/storage/floppy/floppy.c +++ b/reactos/drivers/storage/floppy/floppy.c @@ -23,32 +23,21 @@ * REVISIONS: * 15-Feb-2004 vizzini - Created * NOTES: + * - This driver is only designed to work with ISA-bus floppy controllers. This + * won't work on PCI-based controllers or on anything else with level-sensitive + * interrupts without modification. I don't think these controllers exist. * * ---- General to-do items ---- - * TODO: Clean up properly on failed init - * TODO: Add arc-path support so we can boot from the floppy - * TODO: Fix all these stupid STATUS_UNSUCCESSFUL return values - * TODO: Think about IO_NO_INCREMENT - * TODO: Figure out why CreateClose isn't called any more on XP. Seems to correspond - * with the driver not being unloadable. Does it have to do with cleanup? - * TODO: Consider using the built-in device object pointer in the stack location - * rather than the context area + * TODO: Figure out why CreateClose isn't called any more. Seems to correspond + * with the driver not being unloadable. * TODO: Think about StopDpcQueued -- could be a race; too tired atm to tell + * TODO: Clean up drive start/stop responsibilities (currently a mess...) * * ---- Support for proper media detection ---- * TODO: Handle MFM flag * TODO: Un-hardcode the data rate from various places * TODO: Proper media detection (right now we're hardcoded to 1.44) * TODO: Media detection based on sector 1 - * - * ---- Support for normal floppy hardware ---- - * TODO: Support the three primary types of controller - * TODO: Figure out thinkpad compatibility (I've heard rumors of weirdness with them) - * - * ---- Support for non-ISA and/or non-slave-dma controllers, if they exist ---- - * TODO: Find controllers on non-ISA buses - * TODO: Think about making the interrupt shareable - * TODO: Support bus-master controllers. PCI will break ATM. */ #include @@ -101,7 +90,7 @@ static VOID NTAPI MotorStopDpcFunc(PKDPC UnusedDpc, HwTurnOffMotor(ControllerInfo); ControllerInfo->StopDpcQueued = FALSE; - KeSetEvent(&ControllerInfo->MotorStoppedEvent, IO_NO_INCREMENT, FALSE); + KeSetEvent(&ControllerInfo->MotorStoppedEvent, EVENT_INCREMENT, FALSE); } @@ -202,7 +191,7 @@ static NTSTATUS NTAPI CreateClose(PDEVICE_OBJECT DeviceObject, * - No state to track, so this routine is easy * - Can be called <= DISPATCH_LEVEL * - * TODO: Figure out why this isn't getting called any more, and remove the ASSERT once that happens + * TODO: Figure out why this isn't getting called */ { UNREFERENCED_PARAMETER(DeviceObject); @@ -212,7 +201,7 @@ static NTSTATUS NTAPI CreateClose(PDEVICE_OBJECT DeviceObject, Irp->IoStatus.Status = STATUS_SUCCESS; Irp->IoStatus.Information = FILE_OPENED; - IoCompleteRequest(Irp, IO_NO_INCREMENT); + IoCompleteRequest(Irp, IO_DISK_INCREMENT); return STATUS_SUCCESS; } @@ -225,7 +214,7 @@ static NTSTATUS NTAPI Recalibrate(PDRIVE_INFO DriveInfo) * DriveInfo: Pointer to the driveinfo struct associated with the targeted drive * RETURNS: * STATUS_SUCCESS on successful starting of the process - * STATUS_UNSUCCESSFUL if it fails + * STATUS_IO_DEVICE_ERROR if it fails * NOTES: * - Sometimes you have to do two recalibrations, particularly if the disk has <80 tracks. * - PAGED_CODE because we wait @@ -246,13 +235,17 @@ static NTSTATUS NTAPI Recalibrate(PDRIVE_INFO DriveInfo) if(HwSetDataRate(DriveInfo->ControllerInfo, 0) != STATUS_SUCCESS) { KdPrint(("floppy: Recalibrate: HwSetDataRate failed\n")); - return STATUS_UNSUCCESSFUL; + StopMotor(DriveInfo->ControllerInfo); + return STATUS_IO_DEVICE_ERROR; } /* clear the event just in case the last call forgot */ KeClearEvent(&DriveInfo->ControllerInfo->SynchEvent); - /* sometimes you have to do this twice */ + /* sometimes you have to do this twice; we'll just do it twice all the time since + * we don't know if the people calling this Recalibrate routine expect a disk to + * even be in the drive, and if so, if that disk is formatted. + */ for(i = 0; i < 2; i++) { /* Send the command */ @@ -312,10 +305,14 @@ NTSTATUS NTAPI ResetChangeFlag(PDRIVE_INFO DriveInfo) /* clear spurious interrupts in prep for seeks */ KeClearEvent(&DriveInfo->ControllerInfo->SynchEvent); + /* must re-start the drive because Recalibrate() stops it */ + StartMotor(DriveInfo); + /* Seek to 1 */ if(HwSeek(DriveInfo, 1) != STATUS_SUCCESS) { KdPrint(("floppy: ResetChangeFlag(): HwSeek failed; returning STATUS_IO_DEVICE_ERROR\n")); + StopMotor(DriveInfo->ControllerInfo); return STATUS_IO_DEVICE_ERROR; } @@ -324,6 +321,7 @@ NTSTATUS NTAPI ResetChangeFlag(PDRIVE_INFO DriveInfo) if(HwSenseInterruptStatus(DriveInfo->ControllerInfo) != STATUS_SUCCESS) { KdPrint(("floppy: ResetChangeFlag(): HwSenseInterruptStatus failed; bailing out\n")); + StopMotor(DriveInfo->ControllerInfo); return STATUS_IO_DEVICE_ERROR; } @@ -331,6 +329,7 @@ NTSTATUS NTAPI ResetChangeFlag(PDRIVE_INFO DriveInfo) if(HwSeek(DriveInfo, 1) != STATUS_SUCCESS) { KdPrint(("floppy: ResetChangeFlag(): HwSeek failed; returning STATUS_IO_DEVICE_ERROR\n")); + StopMotor(DriveInfo->ControllerInfo); return STATUS_IO_DEVICE_ERROR; } @@ -339,6 +338,7 @@ NTSTATUS NTAPI ResetChangeFlag(PDRIVE_INFO DriveInfo) if(HwSenseInterruptStatus(DriveInfo->ControllerInfo) != STATUS_SUCCESS) { KdPrint(("floppy: ResetChangeFlag(): HwSenseInterruptStatus #2 failed; bailing\n")); + StopMotor(DriveInfo->ControllerInfo); return STATUS_IO_DEVICE_ERROR; } @@ -346,9 +346,12 @@ NTSTATUS NTAPI ResetChangeFlag(PDRIVE_INFO DriveInfo) if(HwDiskChanged(DriveInfo, &DiskChanged) != STATUS_SUCCESS) { KdPrint(("floppy: ResetChangeFlag(): HwDiskChagned failed; returning STATUS_IO_DEVICE_ERROR\n")); + StopMotor(DriveInfo->ControllerInfo); return STATUS_IO_DEVICE_ERROR; } + StopMotor(DriveInfo->ControllerInfo); + /* if the change flag is still set, there's probably no media in the drive. */ if(DiskChanged) return STATUS_NO_MEDIA_IN_DEVICE; @@ -363,8 +366,6 @@ static VOID NTAPI Unload(PDRIVER_OBJECT DriverObject) * FUNCTION: Unload the driver from memory * ARGUMENTS: * DriverObject - The driver that is being unloaded - * - * TODO: Delete ARC links */ { ULONG i,j; @@ -380,16 +381,24 @@ static VOID NTAPI Unload(PDRIVER_OBJECT DriverObject) for(i = 0; i < gNumberOfControllers; i++) { - if(!gControllerInfo[i].Populated) + if(!gControllerInfo[i].Initialized) continue; for(j = 0; j < gControllerInfo[i].NumberOfDrives; j++) { + if(!gControllerInfo[i].DriveInfo[j].Initialized) + continue; + if(gControllerInfo[i].DriveInfo[j].DeviceObject) { UNICODE_STRING Link; + RtlInitUnicodeString(&Link, gControllerInfo[i].DriveInfo[j].SymLinkBuffer); IoDeleteSymbolicLink(&Link); + + RtlInitUnicodeString(&Link, gControllerInfo[i].DriveInfo[j].ArcPathBuffer); + IoDeassignArcName(&Link); + IoDeleteDevice(gControllerInfo[i].DriveInfo[j].DeviceObject); } } @@ -502,13 +511,9 @@ static NTSTATUS NTAPI ConfigCallback(PVOID Context, } if(AddressSpace == 0) - { - gControllerInfo[gNumberOfControllers].BaseAddress = MmMapIoSpace(TranslatedAddress, 8, MmNonCached); // symbolic constant? - } + gControllerInfo[gNumberOfControllers].BaseAddress = MmMapIoSpace(TranslatedAddress, FDC_PORT_BYTES, MmNonCached); else - { gControllerInfo[gNumberOfControllers].BaseAddress = (PUCHAR)TranslatedAddress.u.LowPart; - } } else if(PartialDescriptor->Type == CmResourceTypeDma) @@ -579,7 +584,6 @@ static BOOLEAN NTAPI Isr(PKINTERRUPT Interrupt, * triggered, this is safe to not do here, as we can just wait for the DPC. * - Either way, we don't want to do this here. The controller shouldn't interrupt again, so we'll * schedule a DPC to take care of it. - * TODO: * - This driver really cannot shrare interrupts, as I don't know how to conclusively say * whether it was our controller that interrupted or not. I just have to assume that any time * my ISR gets called, it was my board that called it. Dumb design, yes, but it goes back to @@ -640,7 +644,7 @@ VOID NTAPI DpcForIsr(PKDPC UnusedDpc, KdPrint(("floppy: DpcForIsr called\n")); - KeSetEvent(&ControllerInfo->SynchEvent, IO_NO_INCREMENT, FALSE); + KeSetEvent(&ControllerInfo->SynchEvent, EVENT_INCREMENT, FALSE); } @@ -651,7 +655,7 @@ static NTSTATUS NTAPI InitController(PCONTROLLER_INFO ControllerInfo) * ControllerInfo: pointer to the controller to be initialized * RETURNS: * STATUS_SUCCESS if the controller is successfully initialized - * STATUS_UNSUCCESSFUL otherwise + * STATUS_IO_DEVICE_ERROR otherwise */ { int i; @@ -666,26 +670,22 @@ static NTSTATUS NTAPI InitController(PCONTROLLER_INFO ControllerInfo) KeClearEvent(&ControllerInfo->SynchEvent); - //HwDumpRegisters(ControllerInfo); - KdPrint(("floppy: InitController: resetting the controller\n")); /* Reset the controller */ if(HwReset(ControllerInfo) != STATUS_SUCCESS) { KdPrint(("floppy: InitController: unable to reset controller\n")); - return STATUS_UNSUCCESSFUL; + return STATUS_IO_DEVICE_ERROR; } - //HwDumpRegisters(ControllerInfo); - KdPrint(("floppy: InitController: setting data rate\n")); /* Set data rate */ if(HwSetDataRate(ControllerInfo, DRSR_DSEL_500KBPS) != STATUS_SUCCESS) { KdPrint(("floppy: InitController: unable to set data rate\n")); - return STATUS_UNSUCCESSFUL; + return STATUS_IO_DEVICE_ERROR; } KdPrint(("floppy: InitController: waiting for initial interrupt\n")); @@ -697,27 +697,18 @@ static NTSTATUS NTAPI InitController(PCONTROLLER_INFO ControllerInfo) for(i = 0; i < MAX_DRIVES_PER_CONTROLLER; i++) { KdPrint(("floppy: InitController: Sensing interrupt %d\n", i)); - //HwDumpRegisters(ControllerInfo); if(HwSenseInterruptStatus(ControllerInfo) != STATUS_SUCCESS) { KdPrint(("floppy: InitController: Unable to clear interrupt 0x%x\n", i)); - return STATUS_UNSUCCESSFUL; + return STATUS_IO_DEVICE_ERROR; } } KdPrint(("floppy: InitController: done sensing interrupts\n")); - //HwDumpRegisters(ControllerInfo); - /* Next, see if we have the right version to do implied seek */ - if(HwGetVersion(ControllerInfo) != VERSION_ENHANCED) - { - KdPrint(("floppy: InitController: enhanced version not supported; disabling implied seeks\n")); - ControllerInfo->ImpliedSeeks = FALSE; - ControllerInfo->Model30 = FALSE; - } - else + if(HwGetVersion(ControllerInfo) == VERSION_ENHANCED) { /* If so, set that up -- all defaults below except first TRUE for EIS */ if(HwConfigure(ControllerInfo, TRUE, TRUE, FALSE, 0, 0) != STATUS_SUCCESS) @@ -731,7 +722,32 @@ static NTSTATUS NTAPI InitController(PCONTROLLER_INFO ControllerInfo) ControllerInfo->ImpliedSeeks = TRUE; } - ControllerInfo->Model30 = TRUE; + /* + * FIXME: Figure out the answer to the below + * + * I must admit that I'm really confused about the Model 30 issue. At least one + * important bit (the disk change bit in the DIR) is flipped if this is a Model 30 + * controller. However, at least one other floppy driver believes that there are only + * two computers that are guaranteed to have a Model 30 controller: + * - IBM Thinkpad 750 + * - IBM PS2e + * + * ...and another driver only lists a config option for "thinkpad", that flips + * the change line. A third driver doesn't mention the Model 30 issue at all. + * + * What I can't tell is whether or not the average, run-of-the-mill computer now has + * a Model 30 controller. For the time being, I'm going to wire this to FALSE, + * and just not support the computers mentioned above, while I try to figure out + * how ubiquitous these newfangled 30 thingies are. + */ + //ControllerInfo->Model30 = TRUE; + ControllerInfo->Model30 = FALSE; + } + else + { + KdPrint(("floppy: InitController: enhanced version not supported; disabling implied seeks\n")); + ControllerInfo->ImpliedSeeks = FALSE; + ControllerInfo->Model30 = FALSE; } /* Specify */ @@ -746,32 +762,25 @@ static NTSTATUS NTAPI InitController(PCONTROLLER_INFO ControllerInfo) if(HwSpecify(ControllerInfo, HeadLoadTime, HeadUnloadTime, StepRateTime, FALSE) != STATUS_SUCCESS) { KdPrint(("floppy: InitController: unable to specify options\n")); - return STATUS_UNSUCCESSFUL; + return STATUS_IO_DEVICE_ERROR; } - //HwDumpRegisters(ControllerInfo); - /* Init the stop stuff */ KeInitializeDpc(&ControllerInfo->MotorStopDpc, MotorStopDpcFunc, ControllerInfo); KeInitializeTimer(&ControllerInfo->MotorTimer); KeInitializeEvent(&ControllerInfo->MotorStoppedEvent, SynchronizationEvent, FALSE); ControllerInfo->StopDpcQueued = FALSE; - /* Recalibrate each drive on the controller (depends on StartMotor, which depends on the timer stuff above) */ - /* TODO: Handle failure of one or more drives */ + /* + * Recalibrate each drive on the controller (depends on StartMotor, which depends on the timer stuff above) + * We don't even know if there is a disk in the drive, so this may not work, but that's OK. + */ for(i = 0; i < ControllerInfo->NumberOfDrives; i++) { KdPrint(("floppy: InitController: recalibrating drive 0x%x on controller 0x%x\n", i, ControllerInfo)); - - if(Recalibrate(&ControllerInfo->DriveInfo[i]) != STATUS_SUCCESS) - { - KdPrint(("floppy: InitController: unable to recalibrate drive\n")); - return STATUS_UNSUCCESSFUL; - } + Recalibrate(&ControllerInfo->DriveInfo[i]); } - //HwDumpRegisters(ControllerInfo); - KdPrint(("floppy: InitController: done initializing; returning STATUS_SUCCESS\n")); return STATUS_SUCCESS; @@ -792,11 +801,7 @@ static BOOLEAN NTAPI AddControllers(PDRIVER_OBJECT DriverObject) * just test a boolean value in the first object to see if it was completely populated. The same value * is tested for each controller before we build device objects for it. * TODO: - * - Figure out a workable interrupt-sharing scheme and un-hardcode FALSE in IoConnectInterrupt - * - Add support for non-ISA buses, by looping through all of the bus types looking for floppy controllers * - Report resource usage to the HAL - * - Add ARC path support - * - Think more about error handling; atm most errors abort the start of the driver */ { INTERFACE_TYPE InterfaceType = Isa; @@ -814,7 +819,7 @@ static BOOLEAN NTAPI AddControllers(PDRIVER_OBJECT DriverObject) /* * w2k breaks the return val from ConfigCallback, so we have to hack around it, rather than just - * looking for a return value from ConfigCallback + * looking for a return value from ConfigCallback. We expect at least one controller. */ if(!gControllerInfo[0].Populated) { @@ -826,7 +831,7 @@ static BOOLEAN NTAPI AddControllers(PDRIVER_OBJECT DriverObject) for(i = 0; i < gNumberOfControllers; i++) { /* 0: Report resource usage to the kernel, to make sure they aren't assigned to anyone else */ - /* XXX do me baby */ + /* FIXME: Implement me. */ /* 1: Set up interrupt */ gControllerInfo[i].MappedVector = HalGetInterruptVector(gControllerInfo[i].InterfaceType, gControllerInfo[i].BusNumber, @@ -845,26 +850,18 @@ static BOOLEAN NTAPI AddControllers(PDRIVER_OBJECT DriverObject) FALSE, Affinity, 0) != STATUS_SUCCESS) { KdPrint(("floppy: AddControllers: unable to connect interrupt\n")); - return FALSE; + continue; } /* 2: Set up DMA */ - memset(&DeviceDescription, 0, sizeof(DeviceDescription)); DeviceDescription.Version = DEVICE_DESCRIPTION_VERSION; - DeviceDescription.Master = (gControllerInfo[i].InterfaceType == PCIBus ? TRUE : FALSE); /* guessing if not pci not master */ DeviceDescription.DmaChannel = gControllerInfo[i].Dma; DeviceDescription.InterfaceType = gControllerInfo[i].InterfaceType; DeviceDescription.BusNumber = gControllerInfo[i].BusNumber; - if(gControllerInfo[i].InterfaceType == PCIBus) - { - DeviceDescription.Dma32BitAddresses = TRUE; - DeviceDescription.DmaWidth = Width32Bits; - } - else - /* DMA 0,1,2,3 are 8-bit; 4,5,6,7 are 16-bit (4 is chain i think) */ - DeviceDescription.DmaWidth = gControllerInfo[i].Dma > 3 ? Width16Bits: Width8Bits; + /* DMA 0,1,2,3 are 8-bit; 4,5,6,7 are 16-bit (4 is chain i think) */ + DeviceDescription.DmaWidth = gControllerInfo[i].Dma > 3 ? Width16Bits: Width8Bits; gControllerInfo[i].AdapterObject = HalGetAdapter(&DeviceDescription, &gControllerInfo[i].MapRegisters); @@ -872,23 +869,27 @@ static BOOLEAN NTAPI AddControllers(PDRIVER_OBJECT DriverObject) { KdPrint(("floppy: AddControllers: unable to allocate an adapter object\n")); IoDisconnectInterrupt(gControllerInfo[i].InterruptObject); - return FALSE; + continue; } /* 2b: Initialize the new controller */ if(InitController(&gControllerInfo[i]) != STATUS_SUCCESS) { KdPrint(("floppy: AddControllers():Unable to set up controller %d - initialization failed\n", i)); - ASSERT(0); /* FIXME: clean up properly */ + IoDisconnectInterrupt(gControllerInfo[i].InterruptObject); continue; } + /* 2c: Set the controller's initlized flag so we know to release stuff in Unload */ + gControllerInfo[i].Initialized = TRUE; + /* 3: per-drive setup */ for(j = 0; j < gControllerInfo[i].NumberOfDrives; j++) { WCHAR DeviceNameBuf[MAX_DEVICE_NAME]; UNICODE_STRING DeviceName; UNICODE_STRING LinkName; + UNICODE_STRING ArcPath; UCHAR DriveNumber; KdPrint(("floppy: AddControllers(): Configuring drive %d on controller %d\n", i, j)); @@ -917,11 +918,18 @@ static BOOLEAN NTAPI AddControllers(PDRIVER_OBJECT DriverObject) { KdPrint(("floppy: AddControllers: unable to register a Device object\n")); IoDisconnectInterrupt(gControllerInfo[i].InterruptObject); - return FALSE; + continue; /* continue on to next drive */ } KdPrint(("floppy: AddControllers: New device: %S (0x%x)\n", DeviceNameBuf, gControllerInfo[i].DriveInfo[j].DeviceObject)); + /* 3b.5: Create an ARC path in case we're booting from this drive */ + swprintf(gControllerInfo[i].DriveInfo[j].ArcPathBuffer, + L"\\ArcName\\multi(%d)disk(%d)fdisk(%d)", gControllerInfo[i].BusNumber, i, DriveNumber); + + RtlInitUnicodeString(&ArcPath, gControllerInfo[i].DriveInfo[j].ArcPathBuffer); + IoAssignArcName(&ArcPath, &DeviceName); + /* 3c: Set flags up */ gControllerInfo[i].DriveInfo[j].DeviceObject->Flags |= DO_DIRECT_IO; @@ -932,8 +940,8 @@ static BOOLEAN NTAPI AddControllers(PDRIVER_OBJECT DriverObject) { KdPrint(("floppy: AddControllers: Unable to create a symlink for drive %d\n", DriveNumber)); IoDisconnectInterrupt(gControllerInfo[i].InterruptObject); - // delete devices too? - return FALSE; + IoDeassignArcName(&ArcPath); + continue; /* continue to next drive */ } /* 3e: Set up the DPC */ @@ -947,6 +955,9 @@ static BOOLEAN NTAPI AddControllers(PDRIVER_OBJECT DriverObject) /* 3h: set the initial media type to unknown */ memset(&gControllerInfo[i].DriveInfo[j].DiskGeometry, 0, sizeof(DISK_GEOMETRY)); gControllerInfo[i].DriveInfo[j].DiskGeometry.MediaType = Unknown; + + /* 3i: Now that we're done, set the Initialized flag so we know to free this in Unload */ + gControllerInfo[i].DriveInfo[j].Initialized = TRUE; } } @@ -1131,7 +1142,7 @@ NTSTATUS NTAPI DriverEntry(PDRIVER_OBJECT DriverObject, if(PsCreateSystemThread(&ThreadHandle, 0, 0, 0, 0, QueueThread, 0) != STATUS_SUCCESS) { KdPrint(("floppy: Unable to create system thread; failing init\n")); - return STATUS_UNSUCCESSFUL; + return STATUS_INSUFFICIENT_RESOURCES; } if(ObReferenceObjectByHandle(ThreadHandle, STANDARD_RIGHTS_ALL, NULL, KernelMode, &ThreadObject, NULL) != STATUS_SUCCESS) @@ -1140,6 +1151,11 @@ NTSTATUS NTAPI DriverEntry(PDRIVER_OBJECT DriverObject, return STATUS_UNSUCCESSFUL; } + /* + * Close the handle, now that we have the object pointer and a reference of our own. + * The handle will certainly not be valid in the context of the caller next time we + * need it, as handles are process-specific. + */ ZwClose(ThreadHandle); /* @@ -1148,9 +1164,8 @@ NTSTATUS NTAPI DriverEntry(PDRIVER_OBJECT DriverObject, KeInitializeEvent(&QueueThreadTerminate, NotificationEvent, FALSE); /* - * Start the device discovery proces. In theory, this should return STATUS_SUCCESS if - * it finds even one drive attached to one controller. In practice, the AddControllers - * routine doesn't handle all of the errors right just yet. FIXME. + * Start the device discovery proces. Returns STATUS_SUCCESS if + * it finds even one drive attached to one controller. */ if(!AddControllers(DriverObject)) return STATUS_NO_SUCH_DEVICE; diff --git a/reactos/drivers/storage/floppy/floppy.h b/reactos/drivers/storage/floppy/floppy.h index a1be952eaee..56967695c14 100644 --- a/reactos/drivers/storage/floppy/floppy.h +++ b/reactos/drivers/storage/floppy/floppy.h @@ -71,12 +71,15 @@ typedef struct _DRIVE_INFO DISK_GEOMETRY DiskGeometry; UCHAR BytesPerSectorCode; WCHAR SymLinkBuffer[MAX_DEVICE_NAME]; + WCHAR ArcPathBuffer[MAX_ARC_PATH_LEN]; ULONG DiskChangeCount; + BOOLEAN Initialized; } DRIVE_INFO, *PDRIVE_INFO; typedef struct _CONTROLLER_INFO { BOOLEAN Populated; + BOOLEAN Initialized; ULONG ControllerNumber; INTERFACE_TYPE InterfaceType; ULONG BusNumber; @@ -111,6 +114,14 @@ NTSTATUS NTAPI DriverEntry(PDRIVER_OBJECT DriverObject, VOID NTAPI SignalMediaChanged(PDEVICE_OBJECT DeviceObject, PIRP Irp); +VOID NTAPI WaitForControllerInterrupt(PCONTROLLER_INFO ControllerInfo); + +NTSTATUS NTAPI ResetChangeFlag(PDRIVE_INFO DriveInfo); + +VOID NTAPI StartMotor(PDRIVE_INFO DriveInfo); + +VOID NTAPI StopMotor(PCONTROLLER_INFO ControllerInfo); + /* * MEDIA TYPES * @@ -133,10 +144,3 @@ VOID NTAPI SignalMediaChanged(PDEVICE_OBJECT DeviceObject, #define GEOMETRY_144_SECTORSPERTRACK 18 #define GEOMETRY_144_BYTESPERSECTOR 512 -VOID NTAPI WaitForControllerInterrupt(PCONTROLLER_INFO ControllerInfo); - -NTSTATUS NTAPI ResetChangeFlag(PDRIVE_INFO DriveInfo); - -VOID NTAPI StartMotor(PDRIVE_INFO DriveInfo); -VOID NTAPI StopMotor(PCONTROLLER_INFO ControllerInfo); - diff --git a/reactos/drivers/storage/floppy/hardware.c b/reactos/drivers/storage/floppy/hardware.c index e8c4fd5f15d..9a9b3ec05b6 100644 --- a/reactos/drivers/storage/floppy/hardware.c +++ b/reactos/drivers/storage/floppy/hardware.c @@ -41,7 +41,6 @@ * thread. * - Some information taken from Intel 82077AA data sheet (order #290166-007) * - * TODO: Fix all of the stupid STATUS_UNSUCCESSFUL return codes * TODO: ATM the constants defined in hardware.h *might* be shifted to line up * with the bit position in the register, or they *might not*. This should * all be converted to standardize on absolute values or shifts. @@ -81,21 +80,11 @@ static BOOLEAN NTAPI ReadyForWrite(PCONTROLLER_INFO ControllerInfo) { UCHAR Status = READ_PORT_UCHAR(ControllerInfo->BaseAddress + MAIN_STATUS_REGISTER); - PAGED_CODE(); - if((Status & MSR_IO_DIRECTION)) /* 0 for out */ - { - //KdPrint(("floppy: ReadyForWrite returning false due to incorrect FIFO direction; Status = 0x%x\n", Status)); - //HwDumpRegisters(ControllerInfo); return FALSE; - } if(!(Status & MSR_DATA_REG_READY_FOR_IO)) - { - //KdPrint(("floppy: ReadyForWrite returning false due to MSR Not ready for I/O; Status = 0x%x\n", Status)); - //HwDumpRegisters(ControllerInfo); return FALSE; - } return TRUE; } @@ -116,21 +105,11 @@ static BOOLEAN NTAPI ReadyForRead(PCONTROLLER_INFO ControllerInfo) { UCHAR Status = READ_PORT_UCHAR(ControllerInfo->BaseAddress + MAIN_STATUS_REGISTER); - PAGED_CODE(); - if(!(Status & MSR_IO_DIRECTION)) /* Read = 1 */ - { -// KdPrint(("floppy: ReadyForRead returning FALSE due to incorrect FIFO direction; Status 0x%x\n", Status)); -// HwDumpRegisters(ControllerInfo); return FALSE; - } if(!(Status & MSR_DATA_REG_READY_FOR_IO)) - { -// KdPrint(("floppy: ReadyForRead returning FALSE due to MSR Not ready for I/O\n; Status 0x%x", Status)); -// HwDumpRegisters(ControllerInfo); return FALSE; - } return TRUE; } @@ -157,14 +136,13 @@ static NTSTATUS NTAPI Send_Byte(PCONTROLLER_INFO ControllerInfo, * maximum. * - This function is necessary because sometimes the FIFO reacts slowly * and isn't yet ready to read or write the next byte + * FIXME: time interval here and in Get_Byte */ { LARGE_INTEGER StartingTickCount; LARGE_INTEGER CurrentTickCount; PUCHAR Address; - //KdPrint(("floppy: Send_Byte called to write 0x%x at offset 0x%x\n", Byte, Offset)); - PAGED_CODE(); Address = ControllerInfo->BaseAddress + FIFO; @@ -193,8 +171,6 @@ static NTSTATUS NTAPI Send_Byte(PCONTROLLER_INFO ControllerInfo, ElapsedTicks = CurrentTickCount.QuadPart - StartingTickCount.QuadPart; TimeUnits = ElapsedTicks * TimeIncrement; - //KdPrint(("floppy: Send_Byte: failed to write; elapsed time %d\n", TimeUnits)); - if(TimeUnits > 25000000) break; @@ -263,8 +239,6 @@ static NTSTATUS NTAPI Get_Byte(PCONTROLLER_INFO ControllerInfo, ElapsedTicks = CurrentTickCount.QuadPart - StartingTickCount.QuadPart; TimeUnits = ElapsedTicks * TimeIncrement; - //KdPrint(("floppy: Get_Byte: failed to read; elapsed time %d\n", TimeUnits)); - if(TimeUnits > 25000000) break; @@ -273,8 +247,6 @@ static NTSTATUS NTAPI Get_Byte(PCONTROLLER_INFO ControllerInfo, *Byte = READ_PORT_UCHAR(Address); - //KdPrint(("floppy: Get_Byte read 0x%x from offset 0x%x\n", *Byte, Offset)); - return STATUS_SUCCESS; } @@ -334,14 +306,13 @@ NTSTATUS NTAPI HwTurnOnMotor(PDRIVE_INFO DriveInfo) * STATUS_UNSUCCESSFUL otherwise * NOTES: * - Doesn't interrupt + * - Currently cannot fail */ { PCONTROLLER_INFO ControllerInfo = DriveInfo->ControllerInfo; UCHAR Unit = DriveInfo->UnitNumber; UCHAR Buffer; - //KdPrint(("floppy: HwTurnOnMotor called; setting unit 0x%x to data rate 0x%x\n", Unit, DataRate)); - PAGED_CODE(); /* turn on motor */ @@ -435,8 +406,6 @@ NTSTATUS NTAPI HwReadWriteData(PCONTROLLER_INFO ControllerInfo, PAGED_CODE(); - //KdPrint(("floppy: HwReadWriteData called\n")); - /* Shouldn't be using DataLength in this driver */ ASSERT(DataLength == 0xff); @@ -469,7 +438,6 @@ NTSTATUS NTAPI HwReadWriteData(PCONTROLLER_INFO ControllerInfo, } } - //KdPrint(("floppy: HwReadWriteData: returning STATUS_SUCCESS\n")); return STATUS_SUCCESS; } @@ -487,7 +455,7 @@ NTSTATUS NTAPI HwRecalibrateResult(PCONTROLLER_INFO ControllerInfo) * whole thing down to a single SUCCESS or FAILURE result * - Called post-interrupt; does not interrupt * TODO - * - handle much more status + * - perhaps handle more status */ { UCHAR Buffer[2]; @@ -495,8 +463,6 @@ NTSTATUS NTAPI HwRecalibrateResult(PCONTROLLER_INFO ControllerInfo) PAGED_CODE(); - //KdPrint(("floppy: HwRecalibrateResult called\n")); - if(Send_Byte(ControllerInfo, COMMAND_SENSE_INTERRUPT_STATUS) != STATUS_SUCCESS) { KdPrint(("floppy: HwRecalibrateResult: Unable to write the controller\n")); @@ -552,15 +518,13 @@ NTSTATUS NTAPI HwReadWriteResult(PCONTROLLER_INFO ControllerInfo) * - This function tests the error conditions itself, and boils the * whole thing down to a single SUCCESS or FAILURE result * - Called post-interrupt; does not interrupt - * TODO - * - handle much more status + * TODO: + * - perhaps handle more status */ { UCHAR Buffer[7]; int i; - //KdPrint(("floppy: HwReadWriteResult called\n")); - PAGED_CODE(); for(i = 0; i < 7; i++) @@ -632,8 +596,6 @@ NTSTATUS NTAPI HwSenseInterruptStatus(PCONTROLLER_INFO ControllerInfo) PAGED_CODE(); - //KdPrint(("floppy: HwSenseInterruptStatus called\n")); - if(Send_Byte(ControllerInfo, COMMAND_SENSE_INTERRUPT_STATUS) != STATUS_SUCCESS) { KdPrint(("floppy: HwSenseInterruptStatus: failed to write controller\n")); @@ -885,9 +847,8 @@ NTSTATUS NTAPI HwDiskChanged(PDRIVE_INFO DriveInfo, { if(!(Buffer & DIR_DISKETTE_CHANGE)) { - /* FIXME FIXME FIXME: This is wrong */ KdPrint(("floppy: HdDiskChanged - Model30 - returning TRUE\n")); - *DiskChanged = FALSE; + *DiskChanged = TRUE; } else { @@ -957,7 +918,7 @@ NTSTATUS NTAPI HwReadIdResult(PCONTROLLER_INFO ControllerInfo, * whole thing down to a single SUCCESS or FAILURE result * - Called post-interrupt; does not interrupt * TODO - * - handle much more status + * - perhaps handle more status */ { UCHAR Buffer[7] = {0,0,0,0,0,0,0}; diff --git a/reactos/drivers/storage/floppy/hardware.h b/reactos/drivers/storage/floppy/hardware.h index 52cf5f0a87b..17b15ccc827 100644 --- a/reactos/drivers/storage/floppy/hardware.h +++ b/reactos/drivers/storage/floppy/hardware.h @@ -35,6 +35,7 @@ */ #define FLOPPY_DEFAULT_IRQ 0x6 +#define FDC_PORT_BYTES 0x8 /* Register offsets from base address (usually 0x3f8) */ #define STATUS_REGISTER_A 0x0 /* Read; PS/2 Only */ diff --git a/reactos/drivers/storage/floppy/ioctl.c b/reactos/drivers/storage/floppy/ioctl.c index 1cdc0f791e2..7242a3311d2 100644 --- a/reactos/drivers/storage/floppy/ioctl.c +++ b/reactos/drivers/storage/floppy/ioctl.c @@ -134,6 +134,11 @@ VOID NTAPI DeviceIoctlPassive(PDRIVE_INFO DriveInfo, return; } + /* + * Start the drive to see if the disk has changed + */ + StartMotor(DriveInfo); + /* * Check the change line, and if it's set, return */ @@ -143,6 +148,7 @@ VOID NTAPI DeviceIoctlPassive(PDRIVE_INFO DriveInfo, Irp->IoStatus.Status = STATUS_UNSUCCESSFUL; Irp->IoStatus.Information = 0; IoCompleteRequest(Irp, IO_NO_INCREMENT); + StopMotor(DriveInfo->ControllerInfo); return; } @@ -161,7 +167,7 @@ VOID NTAPI DeviceIoctlPassive(PDRIVE_INFO DriveInfo, Irp->IoStatus.Status = STATUS_NO_MEDIA_IN_DEVICE; IoCompleteRequest(Irp, IO_NO_INCREMENT); - + StopMotor(DriveInfo->ControllerInfo); return; } @@ -245,6 +251,7 @@ VOID NTAPI DeviceIoctlPassive(PDRIVE_INFO DriveInfo, KdPrint(("floppy: ioctl: completing with status 0x%x\n", Irp->IoStatus.Status)); IoCompleteRequest(Irp, IO_NO_INCREMENT); + StopMotor(DriveInfo->ControllerInfo); return; } diff --git a/reactos/drivers/storage/floppy/ioctl.h b/reactos/drivers/storage/floppy/ioctl.h index 935894a7804..ad55ad4ffdf 100644 --- a/reactos/drivers/storage/floppy/ioctl.h +++ b/reactos/drivers/storage/floppy/ioctl.h @@ -29,3 +29,4 @@ NTSTATUS NTAPI DeviceIoctl(PDEVICE_OBJECT DeviceObject, VOID NTAPI DeviceIoctlPassive(PDRIVE_INFO DriveInfo, PIRP Irp); + diff --git a/reactos/drivers/storage/floppy/readwrite.c b/reactos/drivers/storage/floppy/readwrite.c index fd4d8b6586d..8e7e80a90d0 100644 --- a/reactos/drivers/storage/floppy/readwrite.c +++ b/reactos/drivers/storage/floppy/readwrite.c @@ -45,7 +45,6 @@ * of RWComputeCHS. I've never seen Windows send a partial-sector request, though, so * this may not be a bad thing. Should be looked into, regardless. * - * TODO: Handle split reads and writes across multiple map registers * TODO: Break up ReadWritePassive and handle errors better * TODO: Figure out data rate issues * TODO: Media type detection @@ -85,7 +84,7 @@ static IO_ALLOCATION_ACTION NTAPI MapRegisterCallback(PDEVICE_OBJECT DeviceObjec ControllerInfo->MapRegisterBase = MapRegisterBase; KeSetEvent(&ControllerInfo->SynchEvent, 0, FALSE); - return KeepObject; /* FIXME: Should be something else if we find a bus master */ + return KeepObject; } @@ -184,6 +183,8 @@ static NTSTATUS NTAPI RWDetermineMediaType(PDRIVE_INFO DriveInfo) do { + int i; + /* Program data rate */ if(HwSetDataRate(DriveInfo->ControllerInfo, DRSR_DSEL_500KBPS) != STATUS_SUCCESS) { @@ -207,20 +208,29 @@ static NTSTATUS NTAPI RWDetermineMediaType(PDRIVE_INFO DriveInfo) KeClearEvent(&DriveInfo->ControllerInfo->SynchEvent); /* Recalibrate --> head over first track */ - /* FIXME: should be done in a loop? */ - if(HwRecalibrate(DriveInfo) != STATUS_SUCCESS) + for(i=0; i < 2; i++) { - KdPrint(("floppy: RWDetermineMediaType(): Recalibrate failed\n")); - return STATUS_UNSUCCESSFUL; - } + NTSTATUS RecalStatus; - /* Wait for the recalibrate to finish */ - WaitForControllerInterrupt(DriveInfo->ControllerInfo); + if(HwRecalibrate(DriveInfo) != STATUS_SUCCESS) + { + KdPrint(("floppy: RWDetermineMediaType(): Recalibrate failed\n")); + return STATUS_UNSUCCESSFUL; + } - if(HwRecalibrateResult(DriveInfo->ControllerInfo) != STATUS_SUCCESS) - { - KdPrint(("floppy: RWDetermineMediaType(): RecalibrateResult failed\n")); - return STATUS_UNSUCCESSFUL; + /* Wait for the recalibrate to finish */ + WaitForControllerInterrupt(DriveInfo->ControllerInfo); + + RecalStatus = HwRecalibrateResult(DriveInfo->ControllerInfo); + + if(RecalStatus == STATUS_SUCCESS) + break; + + if(i == 1) /* failed for 2nd time */ + { + KdPrint(("floppy: RWDetermineMediaType(): RecalibrateResult failed\n")); + return STATUS_UNSUCCESSFUL; + } } /* clear any spurious interrupts */ @@ -574,7 +584,6 @@ VOID NTAPI ReadWritePassive(PDRIVE_INFO DriveInfo, */ /* Get map registers for DMA */ - /* FIXME: Just request all of our map regiters for now */ KeRaiseIrql(DISPATCH_LEVEL, &OldIrql); Status = IoAllocateAdapterChannel(DriveInfo->ControllerInfo->AdapterObject, DeviceObject, DriveInfo->ControllerInfo->MapRegisters, MapRegisterCallback, DriveInfo->ControllerInfo);