3 * Copyright (C) 2001, 2002 ReactOS Team
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 * COPYRIGHT: See COPYING in the top level directory
22 * PROJECT: ReactOS ATAPI miniport driver
23 * FILE: services/storage/atapi/atapi.c
24 * PURPOSE: ATAPI miniport driver
25 * PROGRAMMERS: Eric Kohl (ekohl@rz-online.de)
32 * This driver is derived from Rex Jolliff's ide driver. Lots of his
33 * routines are still in here although they belong into the higher level
34 * drivers. They will be moved away as soon as possible.
39 * - implement sending of atapi commands
40 * - handle removable atapi non-cdrom drives
44 #define ENABLE_NATIVE_PCI
47 // -------------------------------------------------------------------------
49 #include <ddk/ntddk.h>
52 #include <ddk/ntddscsi.h>
59 #define VERSION "0.0.1"
62 // ------------------------------------------------------- File Static Data
64 // ATAPI_MINIPORT_EXTENSION
67 // Extension to be placed in each port device object
70 // Allocated from NON-PAGED POOL
71 // Available at any IRQL
74 typedef struct _ATAPI_MINIPORT_EXTENSION
76 IDE_DRIVE_IDENTIFY DeviceParams[2];
78 ULONG TransferSize[2];
80 ULONG CommandPortBase;
81 ULONG ControlPortBase;
82 ULONG BusMasterRegisterBase;
84 BOOLEAN ExpectingInterrupt;
85 PSCSI_REQUEST_BLOCK CurrentSrb;
89 ULONG DataTransferLength;
90 } ATAPI_MINIPORT_EXTENSION, *PATAPI_MINIPORT_EXTENSION;
93 #define DEVICE_PRESENT 0x00000001
94 #define DEVICE_ATAPI 0x00000002
95 #define DEVICE_MULTI_SECTOR_CMD 0x00000004
96 #define DEVICE_DWORD_IO 0x00000008
97 #define DEVICE_48BIT_ADDRESS 0x00000010
98 #define DEVICE_MEDIA_STATUS 0x00000020
101 typedef struct _UNIT_EXTENSION
104 } UNIT_EXTENSION, *PUNIT_EXTENSION;
106 PCI_SLOT_NUMBER LastSlotNumber;
108 #ifdef ENABLE_NATIVE_PCI
109 typedef struct _PCI_NATIVE_CONTROLLER
114 PCI_NATIVE_CONTROLLER, *PPCI_NATIVE_CONTROLLER;
116 PCI_NATIVE_CONTROLLER const PciNativeController[] =
120 0x4D68, // PDC20268, Ultra100TX2
124 0x4D30, // PDC20267, Ultra100
130 // ----------------------------------------------- Discardable Declarations
134 // make the initialization routines discardable, so that they
137 #pragma alloc_text(init, DriverEntry)
138 #pragma alloc_text(init, IDECreateController)
139 #pragma alloc_text(init, IDEPolledRead)
141 // make the PASSIVE_LEVEL routines pageable, so that they don't
142 // waste nonpaged memory
144 #pragma alloc_text(page, IDEShutdown)
145 #pragma alloc_text(page, IDEDispatchOpenClose)
146 #pragma alloc_text(page, IDEDispatchRead)
147 #pragma alloc_text(page, IDEDispatchWrite)
149 #endif /* ALLOC_PRAGMA */
151 // ---------------------------------------------------- Forward Declarations
154 AtapiFindCompatiblePciController(PVOID DeviceExtension,
156 PVOID BusInformation,
157 PCHAR ArgumentString,
158 PPORT_CONFIGURATION_INFORMATION ConfigInfo,
162 AtapiFindIsaBusController(PVOID DeviceExtension,
164 PVOID BusInformation,
165 PCHAR ArgumentString,
166 PPORT_CONFIGURATION_INFORMATION ConfigInfo,
170 AtapiFindNativePciController(PVOID DeviceExtension,
172 PVOID BusInformation,
173 PCHAR ArgumentString,
174 PPORT_CONFIGURATION_INFORMATION ConfigInfo,
177 static BOOLEAN STDCALL
178 AtapiInitialize(IN PVOID DeviceExtension);
180 static BOOLEAN STDCALL
181 AtapiResetBus(IN PVOID DeviceExtension,
184 static BOOLEAN STDCALL
185 AtapiStartIo(IN PVOID DeviceExtension,
186 IN PSCSI_REQUEST_BLOCK Srb);
188 static BOOLEAN STDCALL
189 AtapiInterrupt(IN PVOID DeviceExtension);
192 AtapiFindDevices(PATAPI_MINIPORT_EXTENSION DeviceExtension,
193 PPORT_CONFIGURATION_INFORMATION ConfigInfo);
196 AtapiIdentifyDevice(IN ULONG CommandPort,
197 IN ULONG ControlPort,
200 OUT PIDE_DRIVE_IDENTIFY DrvParms);
203 IDEResetController(IN ULONG CommandPort,
204 IN ULONG ControlPort);
207 AtapiPolledRead(IN ULONG CommandPort,
208 IN ULONG ControlPort,
213 IN BYTE CylinderHigh,
221 AtapiSendAtapiCommand(IN PATAPI_MINIPORT_EXTENSION DeviceExtension,
222 IN PSCSI_REQUEST_BLOCK Srb);
225 AtapiSendIdeCommand(IN PATAPI_MINIPORT_EXTENSION DeviceExtension,
226 IN PSCSI_REQUEST_BLOCK Srb);
229 AtapiInquiry(IN PATAPI_MINIPORT_EXTENSION DeviceExtension,
230 IN PSCSI_REQUEST_BLOCK Srb);
233 AtapiReadCapacity(IN PATAPI_MINIPORT_EXTENSION DeviceExtension,
234 IN PSCSI_REQUEST_BLOCK Srb);
237 AtapiReadWrite(IN PATAPI_MINIPORT_EXTENSION DeviceExtension,
238 IN PSCSI_REQUEST_BLOCK Srb);
241 AtapiFlushCache(PATAPI_MINIPORT_EXTENSION DeviceExtension,
242 PSCSI_REQUEST_BLOCK Srb);
245 AtapiTestUnitReady(PATAPI_MINIPORT_EXTENSION DeviceExtension,
246 PSCSI_REQUEST_BLOCK Srb);
249 AtapiErrorToScsi(PVOID DeviceExtension,
250 PSCSI_REQUEST_BLOCK Srb);
253 AtapiScsiSrbToAtapi (PSCSI_REQUEST_BLOCK Srb);
255 // ---------------------------------------------------------------- Inlines
258 IDESwapBytePairs(char *Buf,
264 for (i = 0; i < Cnt; i += 2)
273 // ------------------------------------------------------- Public Interface
278 // This function initializes the driver, locates and claims
279 // hardware resources, and creates various NT objects needed
280 // to process I/O requests.
286 // IN PDRIVER_OBJECT DriverObject System allocated Driver Object
288 // IN PUNICODE_STRING RegistryPath Name of registry driver service
295 DriverEntry(IN PDRIVER_OBJECT DriverObject,
296 IN PUNICODE_STRING RegistryPath)
298 HW_INITIALIZATION_DATA InitData;
301 DPRINT("ATAPI Driver %s\n", VERSION);
302 DPRINT("RegistryPath: '%wZ'\n", RegistryPath);
304 /* Initialize data structure */
305 RtlZeroMemory(&InitData,
306 sizeof(HW_INITIALIZATION_DATA));
307 InitData.HwInitializationDataSize = sizeof(HW_INITIALIZATION_DATA);
308 InitData.HwInitialize = AtapiInitialize;
309 InitData.HwResetBus = AtapiResetBus;
310 InitData.HwStartIo = AtapiStartIo;
311 InitData.HwInterrupt = AtapiInterrupt;
313 InitData.DeviceExtensionSize = sizeof(ATAPI_MINIPORT_EXTENSION);
314 InitData.SpecificLuExtensionSize = sizeof(UNIT_EXTENSION);
316 InitData.MapBuffers = TRUE;
319 /* Search the PCI bus for compatibility mode ide controllers */
321 InitData.HwFindAdapter = AtapiFindCompatiblePciController;
322 InitData.NumberOfAccessRanges = 3;
323 InitData.AdapterInterfaceType = PCIBus;
325 InitData.VendorId = NULL;
326 InitData.VendorIdLength = 0;
327 InitData.DeviceId = NULL;
328 InitData.DeviceIdLength = 0;
330 Status = ScsiPortInitialize(DriverObject,
334 // if (newStatus < statusToReturn)
335 // statusToReturn = newStatus;
338 /* Search the PCI bus for all ide controllers */
339 #ifdef ENABLE_NATIVE_PCI
341 InitData.HwFindAdapter = AtapiFindNativePciController;
342 InitData.NumberOfAccessRanges = 3;
343 InitData.AdapterInterfaceType = PCIBus;
345 InitData.VendorId = 0;
346 InitData.VendorIdLength = 0;
347 InitData.DeviceId = 0;
348 InitData.DeviceIdLength = 0;
350 LastSlotNumber.u.AsULONG = 0xFFFFFFFF;
352 Status = ScsiPortInitialize(DriverObject,
356 // if (newStatus < statusToReturn)
357 // statusToReturn = newStatus;
360 /* Search the ISA bus for ide controllers */
362 InitData.HwFindAdapter = AtapiFindIsaBusController;
363 InitData.NumberOfAccessRanges = 2;
364 InitData.AdapterInterfaceType = Isa;
366 InitData.VendorId = NULL;
367 InitData.VendorIdLength = 0;
368 InitData.DeviceId = NULL;
369 InitData.DeviceIdLength = 0;
371 Status = ScsiPortInitialize(DriverObject,
375 // if (newStatus < statusToReturn)
376 // statusToReturn = newStatus;
379 DPRINT("Returning from DriverEntry\n");
386 AtapiClaimHwResources(PATAPI_MINIPORT_EXTENSION DevExt,
387 PPORT_CONFIGURATION_INFORMATION ConfigInfo,
388 INTERFACE_TYPE InterfaceType,
389 ULONG CommandPortBase,
390 ULONG ControlPortBase,
391 ULONG BusMasterPortBase,
392 ULONG InterruptVector)
394 SCSI_PHYSICAL_ADDRESS IoAddress;
397 IoAddress = ScsiPortConvertUlongToPhysicalAddress(CommandPortBase);
398 IoBase = ScsiPortGetDeviceBase((PVOID)DevExt,
400 ConfigInfo->SystemIoBusNumber,
408 DevExt->CommandPortBase = (ULONG)IoBase;
409 ConfigInfo->AccessRanges[0].RangeStart = IoAddress;
410 ConfigInfo->AccessRanges[0].RangeLength = 8;
411 ConfigInfo->AccessRanges[0].RangeInMemory = FALSE;
415 IoAddress = ScsiPortConvertUlongToPhysicalAddress(ControlPortBase + 2);
416 IoBase = ScsiPortGetDeviceBase((PVOID)DevExt,
418 ConfigInfo->SystemIoBusNumber,
424 ScsiPortFreeDeviceBase((PVOID)DevExt,
425 (PVOID)DevExt->CommandPortBase);
428 DevExt->ControlPortBase = (ULONG)IoBase;
429 ConfigInfo->AccessRanges[1].RangeStart = IoAddress;
430 ConfigInfo->AccessRanges[1].RangeLength = 1;
431 ConfigInfo->AccessRanges[1].RangeInMemory = FALSE;
433 if (BusMasterPortBase)
435 IoAddress = ScsiPortConvertUlongToPhysicalAddress(BusMasterPortBase);
436 IoBase = ScsiPortGetDeviceBase((PVOID)DevExt,
438 ConfigInfo->SystemIoBusNumber,
444 ScsiPortFreeDeviceBase((PVOID)DevExt, (PVOID)DevExt->CommandPortBase);
445 ScsiPortFreeDeviceBase((PVOID)DevExt, (PVOID)DevExt->ControlPortBase);
448 ConfigInfo->AccessRanges[2].RangeStart = IoAddress;
449 ConfigInfo->AccessRanges[2].RangeLength = 8;
450 ConfigInfo->AccessRanges[2].RangeInMemory = FALSE;
452 ConfigInfo->BusInterruptLevel = InterruptVector;
453 ConfigInfo->BusInterruptVector = InterruptVector;
454 ConfigInfo->InterruptMode = (InterfaceType == Isa) ? Latched : LevelSensitive;
456 if ((CommandPortBase == 0x1F0 || ControlPortBase == 0x3F4) && !ConfigInfo->AtdiskPrimaryClaimed)
458 ConfigInfo->AtdiskPrimaryClaimed = TRUE;
460 if ((CommandPortBase == 0x170 || ControlPortBase == 0x374) && !ConfigInfo->AtdiskSecondaryClaimed)
462 ConfigInfo->AtdiskSecondaryClaimed = TRUE;
470 AtapiFindCompatiblePciController(PVOID DeviceExtension,
472 PVOID BusInformation,
473 PCHAR ArgumentString,
474 PPORT_CONFIGURATION_INFORMATION ConfigInfo,
477 PATAPI_MINIPORT_EXTENSION DevExt = (PATAPI_MINIPORT_EXTENSION)DeviceExtension;
478 PCI_SLOT_NUMBER SlotNumber;
479 PCI_COMMON_CONFIG PciConfig;
481 ULONG StartDeviceNumber;
483 ULONG StartFunctionNumber;
484 ULONG FunctionNumber;
485 BOOLEAN ChannelFound;
487 ULONG BusMasterBasePort = 0;
489 DPRINT("AtapiFindCompatiblePciController() Bus: %lu Slot: %lu\n",
490 ConfigInfo->SystemIoBusNumber,
491 ConfigInfo->SlotNumber);
495 /* both channels were claimed: exit */
496 if (ConfigInfo->AtdiskPrimaryClaimed == TRUE &&
497 ConfigInfo->AtdiskSecondaryClaimed == TRUE)
498 return(SP_RETURN_NOT_FOUND);
500 SlotNumber.u.AsULONG = ConfigInfo->SlotNumber;
501 StartDeviceNumber = SlotNumber.u.bits.DeviceNumber;
502 StartFunctionNumber = SlotNumber.u.bits.FunctionNumber;
503 for (DeviceNumber = StartDeviceNumber; DeviceNumber < PCI_MAX_DEVICES; DeviceNumber++)
505 SlotNumber.u.bits.DeviceNumber = DeviceNumber;
506 for (FunctionNumber = StartFunctionNumber; FunctionNumber < PCI_MAX_FUNCTION; FunctionNumber++)
508 SlotNumber.u.bits.FunctionNumber = FunctionNumber;
509 ChannelFound = FALSE;
512 DataSize = ScsiPortGetBusData(DeviceExtension,
514 ConfigInfo->SystemIoBusNumber,
515 SlotNumber.u.AsULONG,
517 PCI_COMMON_HDR_LENGTH);
518 if (DataSize != PCI_COMMON_HDR_LENGTH)
520 if (FunctionNumber == 0)
530 DPRINT("%x %x\n", PciConfig.BaseClass, PciConfig.SubClass);
531 if (PciConfig.BaseClass == 0x01 &&
532 PciConfig.SubClass == 0x01) // &&
533 // (PciConfig.ProgIf & 0x05) == 0)
535 /* both channels are in compatibility mode */
536 DPRINT("Bus %1lu Device %2lu Func %1lu VenID 0x%04hx DevID 0x%04hx\n",
537 ConfigInfo->SystemIoBusNumber,
538 SlotNumber.u.bits.DeviceNumber,
539 SlotNumber.u.bits.FunctionNumber,
542 DPRINT("ProgIF 0x%02hx\n", PciConfig.ProgIf);
544 DPRINT("Found IDE controller in compatibility mode!\n");
546 ConfigInfo->NumberOfBuses = 1;
547 ConfigInfo->MaximumNumberOfTargets = 2;
548 ConfigInfo->MaximumTransferLength = 0x10000; /* max 64Kbyte */
550 if (PciConfig.ProgIf & 0x80)
552 DPRINT("Found IDE Bus Master controller!\n");
553 if (PciConfig.u.type0.BaseAddresses[4] & PCI_ADDRESS_IO_SPACE)
555 BusMasterBasePort = PciConfig.u.type0.BaseAddresses[4] & PCI_ADDRESS_IO_ADDRESS_MASK;
556 DPRINT(" IDE Bus Master Registers at IO %lx\n", BusMasterBasePort);
559 if (ConfigInfo->AtdiskPrimaryClaimed == FALSE)
561 /* Both channels unclaimed: Claim primary channel */
562 DPRINT("Primary channel!\n");
563 ChannelFound = AtapiClaimHwResources(DevExt,
572 else if (ConfigInfo->AtdiskSecondaryClaimed == FALSE)
574 /* Primary channel already claimed: claim secondary channel */
575 DPRINT("Secondary channel!\n");
577 ChannelFound = AtapiClaimHwResources(DevExt,
582 BusMasterBasePort ? BusMasterBasePort + 8 : 0,
586 /* Find attached devices */
589 DeviceFound = AtapiFindDevices(DevExt, ConfigInfo);
590 ConfigInfo->SlotNumber = SlotNumber.u.AsULONG;
591 DPRINT("AtapiFindCompatiblePciController() returns: SP_RETURN_FOUND\n");
592 return(SP_RETURN_FOUND);
595 if (FunctionNumber == 0 && !(PciConfig.HeaderType & PCI_MULTIFUNCTION))
600 StartFunctionNumber = 0;
602 DPRINT("AtapiFindCompatiblePciController() returns: SP_RETURN_NOT_FOUND\n");
604 return(SP_RETURN_NOT_FOUND);
611 AtapiFindIsaBusController(PVOID DeviceExtension,
613 PVOID BusInformation,
614 PCHAR ArgumentString,
615 PPORT_CONFIGURATION_INFORMATION ConfigInfo,
618 PATAPI_MINIPORT_EXTENSION DevExt = (PATAPI_MINIPORT_EXTENSION)DeviceExtension;
619 BOOLEAN ChannelFound = FALSE;
620 BOOLEAN DeviceFound = FALSE;
622 DPRINT("AtapiFindIsaBusController() called!\n");
626 ConfigInfo->NumberOfBuses = 1;
627 ConfigInfo->MaximumNumberOfTargets = 2;
628 ConfigInfo->MaximumTransferLength = 0x10000; /* max 64Kbyte */
630 if (ConfigInfo->AtdiskPrimaryClaimed == FALSE)
632 /* Both channels unclaimed: Claim primary channel */
633 DPRINT("Primary channel!\n");
635 ChannelFound = AtapiClaimHwResources(DevExt,
644 else if (ConfigInfo->AtdiskSecondaryClaimed == FALSE)
646 /* Primary channel already claimed: claim secondary channel */
647 DPRINT("Secondary channel!\n");
649 ChannelFound = AtapiClaimHwResources(DevExt,
660 DPRINT("AtapiFindIsaBusController() both channels claimed. Returns: SP_RETURN_NOT_FOUND\n");
662 return(SP_RETURN_NOT_FOUND);
665 /* Find attached devices */
668 DeviceFound = AtapiFindDevices(DevExt,
670 DPRINT("AtapiFindIsaBusController() returns: SP_RETURN_FOUND\n");
671 return(SP_RETURN_FOUND);
674 return SP_RETURN_NOT_FOUND;
679 #ifdef ENABLE_NATIVE_PCI
681 AtapiFindNativePciController(PVOID DeviceExtension,
683 PVOID BusInformation,
684 PCHAR ArgumentString,
685 PPORT_CONFIGURATION_INFORMATION ConfigInfo,
688 PATAPI_MINIPORT_EXTENSION DevExt = (PATAPI_MINIPORT_EXTENSION)DeviceExtension;
689 PCI_COMMON_CONFIG PciConfig;
690 PCI_SLOT_NUMBER SlotNumber;
693 ULONG StartDeviceNumber;
694 ULONG FunctionNumber;
695 ULONG StartFunctionNumber;
696 ULONG BusMasterBasePort;
698 BOOLEAN ChannelFound;
700 DPRINT("AtapiFindNativePciController() called!\n");
702 SlotNumber.u.AsULONG = ConfigInfo->SlotNumber;
703 StartDeviceNumber = SlotNumber.u.bits.DeviceNumber;
704 StartFunctionNumber = SlotNumber.u.bits.FunctionNumber;
705 for (DeviceNumber = StartDeviceNumber; DeviceNumber < PCI_MAX_DEVICES; DeviceNumber++)
707 SlotNumber.u.bits.DeviceNumber = DeviceNumber;
708 for (FunctionNumber = StartFunctionNumber; FunctionNumber < PCI_MAX_FUNCTION; FunctionNumber++)
710 SlotNumber.u.bits.FunctionNumber = FunctionNumber;
711 DataSize = ScsiPortGetBusData(DeviceExtension,
713 ConfigInfo->SystemIoBusNumber,
714 SlotNumber.u.AsULONG,
716 PCI_COMMON_HDR_LENGTH);
717 if (DataSize != PCI_COMMON_HDR_LENGTH)
721 for (Count = 0; Count < sizeof(PciNativeController)/sizeof(PCI_NATIVE_CONTROLLER); Count++)
723 if (PciConfig.VendorID == PciNativeController[Count].VendorID &&
724 PciConfig.DeviceID == PciNativeController[Count].DeviceID)
729 if (Count < sizeof(PciNativeController)/sizeof(PCI_NATIVE_CONTROLLER))
731 /* We have found a known native pci ide controller */
732 if ((PciConfig.ProgIf & 0x80) && (PciConfig.u.type0.BaseAddresses[4] & PCI_ADDRESS_IO_SPACE))
734 DPRINT("Found IDE Bus Master controller!\n");
735 BusMasterBasePort = PciConfig.u.type0.BaseAddresses[4] & PCI_ADDRESS_IO_ADDRESS_MASK;
736 DPRINT(" IDE Bus Master Registers at IO %lx\n", BusMasterBasePort);
740 BusMasterBasePort = 0;
743 DPRINT("VendorID: %04x, DeviceID: %04x\n", PciConfig.VendorID, PciConfig.DeviceID);
744 ConfigInfo->NumberOfBuses = 1;
745 ConfigInfo->MaximumNumberOfTargets = 2;
746 ConfigInfo->MaximumTransferLength = 0x10000; /* max 64Kbyte */
749 We must not store and use the last tested slot number. If there is a recall
750 to the some device and we will claim the primary channel again than the call
751 to ScsiPortGetDeviceBase in AtapiClaimHwResource will fail and we can try to
752 claim the secondary channel.
754 ChannelFound = FALSE;
755 if (LastSlotNumber.u.AsULONG != SlotNumber.u.AsULONG)
757 /* try to claim primary channel */
758 if ((PciConfig.u.type0.BaseAddresses[0] & PCI_ADDRESS_IO_SPACE) &&
759 (PciConfig.u.type0.BaseAddresses[1] & PCI_ADDRESS_IO_SPACE))
761 /* primary channel is enabled */
762 ChannelFound = AtapiClaimHwResources(DevExt,
765 PciConfig.u.type0.BaseAddresses[0] & PCI_ADDRESS_IO_ADDRESS_MASK,
766 PciConfig.u.type0.BaseAddresses[1] & PCI_ADDRESS_IO_ADDRESS_MASK,
768 PciConfig.u.type0.InterruptLine);
771 AtapiFindDevices(DevExt, ConfigInfo);
773 ConfigInfo->SlotNumber = LastSlotNumber.u.AsULONG = SlotNumber.u.AsULONG;
774 return SP_RETURN_FOUND;
780 /* try to claim secondary channel */
781 if ((PciConfig.u.type0.BaseAddresses[2] & PCI_ADDRESS_IO_SPACE) &&
782 (PciConfig.u.type0.BaseAddresses[3] & PCI_ADDRESS_IO_SPACE))
784 /* secondary channel is enabled */
785 ChannelFound = AtapiClaimHwResources(DevExt,
788 PciConfig.u.type0.BaseAddresses[2] & PCI_ADDRESS_IO_ADDRESS_MASK,
789 PciConfig.u.type0.BaseAddresses[3] & PCI_ADDRESS_IO_ADDRESS_MASK,
790 BusMasterBasePort ? BusMasterBasePort + 8 : 0,
791 PciConfig.u.type0.InterruptLine);
794 AtapiFindDevices(DevExt, ConfigInfo);
796 LastSlotNumber.u.AsULONG = 0xFFFFFFFF;
797 return SP_RETURN_FOUND;
803 StartFunctionNumber = 0;
806 LastSlotNumber.u.AsULONG = 0xFFFFFFFF;
807 DPRINT("AtapiFindNativePciController() done!\n");
809 return(SP_RETURN_NOT_FOUND);
814 static BOOLEAN STDCALL
815 AtapiInitialize(IN PVOID DeviceExtension)
821 static BOOLEAN STDCALL
822 AtapiResetBus(IN PVOID DeviceExtension,
829 static BOOLEAN STDCALL
830 AtapiStartIo(IN PVOID DeviceExtension,
831 IN PSCSI_REQUEST_BLOCK Srb)
833 PATAPI_MINIPORT_EXTENSION DevExt;
836 DPRINT("AtapiStartIo() called\n");
838 DevExt = (PATAPI_MINIPORT_EXTENSION)DeviceExtension;
840 switch (Srb->Function)
842 case SRB_FUNCTION_EXECUTE_SCSI:
843 DevExt->CurrentSrb = Srb;
844 if (DevExt->DeviceFlags[Srb->TargetId] & DEVICE_ATAPI)
846 Result = AtapiSendAtapiCommand(DevExt,
851 Result = AtapiSendIdeCommand(DevExt,
856 case SRB_FUNCTION_ABORT_COMMAND:
857 if (DevExt->CurrentSrb != NULL)
859 Result = SRB_STATUS_ABORT_FAILED;
863 Result = SRB_STATUS_SUCCESS;
868 Result = SRB_STATUS_INVALID_REQUEST;
872 Srb->SrbStatus = Result;
875 if (Result != SRB_STATUS_PENDING)
877 DevExt->CurrentSrb = NULL;
878 Srb->SrbStatus = (UCHAR)Result;
880 ScsiPortNotification(RequestComplete,
883 ScsiPortNotification(NextRequest,
889 DPRINT("SrbStatus = SRB_STATUS_PENDING\n");
892 DPRINT("AtapiStartIo() done\n");
898 static BOOLEAN STDCALL
899 AtapiInterrupt(IN PVOID DeviceExtension)
901 PATAPI_MINIPORT_EXTENSION DevExt;
902 PSCSI_REQUEST_BLOCK Srb;
903 ULONG CommandPortBase;
904 ULONG ControlPortBase;
909 PUCHAR TargetAddress;
914 DPRINT("AtapiInterrupt() called!\n");
916 DevExt = (PATAPI_MINIPORT_EXTENSION)DeviceExtension;
918 CommandPortBase = DevExt->CommandPortBase;
919 ControlPortBase = DevExt->ControlPortBase;
921 if (DevExt->ExpectingInterrupt == FALSE)
923 DeviceStatus = IDEReadStatus(CommandPortBase);
924 DPRINT("AtapiInterrupt(): Unexpected interrupt (port=%x)\n", CommandPortBase);
928 /* check if it was our irq */
929 if ((DeviceStatus = IDEReadAltStatus(ControlPortBase)) & IDE_SR_BUSY)
931 ScsiPortStallExecution(1);
932 if ((DeviceStatus = IDEReadAltStatus(ControlPortBase) & IDE_SR_BUSY))
934 DPRINT("AtapiInterrupt(): Unexpected interrupt (port=%x)\n", CommandPortBase);
939 Srb = DevExt->CurrentSrb;
940 DPRINT("Srb: %p\n", Srb);
942 DPRINT("CommandPortBase: %lx ControlPortBase: %lx\n", CommandPortBase, ControlPortBase);
944 IsAtapi = (DevExt->DeviceFlags[Srb->TargetId] & DEVICE_ATAPI);
945 DPRINT("IsAtapi == %s\n", (IsAtapi) ? "TRUE" : "FALSE");
949 DeviceStatus = IDEReadStatus(CommandPortBase);
950 DPRINT("DeviceStatus: %x\n", DeviceStatus);
952 if ((DeviceStatus & IDE_SR_ERR) &&
953 (Srb->Cdb[0] != SCSIOP_REQUEST_SENSE))
955 /* Report error condition */
956 Srb->SrbStatus = SRB_STATUS_ERROR;
961 if (Srb->SrbFlags & SRB_FLAGS_DATA_IN)
963 DPRINT("Read data\n");
965 /* Update controller/device state variables */
966 TargetAddress = DevExt->DataBuffer;
970 TransferSize = IDEReadCylinderLow(CommandPortBase);
971 TransferSize += IDEReadCylinderHigh(CommandPortBase) << 8;
975 TransferSize = DevExt->TransferSize[Srb->TargetId];
978 DPRINT("TransferLength: %lu\n", Srb->DataTransferLength);
979 DPRINT("TransferSize: %lu\n", TransferSize);
981 if (DevExt->DataTransferLength <= TransferSize)
983 JunkSize = TransferSize - DevExt->DataTransferLength;
984 TransferSize = DevExt->DataTransferLength;
989 DPRINT1("Junk data: %lu bytes\n", JunkSize);
993 DevExt->DataTransferLength = 0;
998 DevExt->DataTransferLength -= TransferSize;
1001 DevExt->DataBuffer += TransferSize;
1002 DPRINT("IsLastBlock == %s\n", (IsLastBlock) ? "TRUE" : "FALSE");
1004 /* Wait for DRQ assertion */
1005 for (Retries = 0; Retries < IDE_MAX_DRQ_RETRIES &&
1006 !(IDEReadStatus(CommandPortBase) & IDE_SR_DRQ);
1009 KeStallExecutionProcessor(10);
1012 /* Copy the block of data */
1013 if (DevExt->DeviceFlags[Srb->TargetId] & DEVICE_DWORD_IO)
1015 IDEReadBlock32(CommandPortBase,
1021 IDEReadBlock(CommandPortBase,
1029 /* Read remaining junk from device */
1030 while (JunkSize > 0)
1032 IDEReadBlock(CommandPortBase,
1038 for (Retries = 0; Retries < IDE_MAX_BUSY_RETRIES &&
1039 (IDEReadStatus(CommandPortBase) & IDE_SR_BUSY);
1042 KeStallExecutionProcessor(10);
1045 /* Check for data overrun */
1046 while (IDEReadStatus(CommandPortBase) & IDE_SR_DRQ)
1048 DPRINT1("AtapiInterrupt(): reading overrun data!\n");
1049 IDEReadWord(CommandPortBase);
1053 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1055 else if (Srb->SrbFlags & SRB_FLAGS_DATA_OUT)
1057 DPRINT("Write data\n");
1059 if (DevExt->DataTransferLength == 0)
1061 /* Check for data overrun */
1062 if (DeviceStatus & IDE_SR_DRQ)
1064 /* FIXME: Handle error! */
1065 /* This can occure if the irq is shared with an other and if the
1066 ide controller has a write buffer. We have write the last sectors
1067 and the other device has a irq before ours. The isr is called but
1068 we haven't a interrupt. The controller writes the sector buffer
1069 and the status register shows DRQ because the write is not ended. */
1070 DPRINT("AtapiInterrupt(): data overrun error!\n");
1076 /* Update DevExt data */
1077 TransferSize = DevExt->TransferSize[Srb->TargetId];
1078 if (DevExt->DataTransferLength < TransferSize)
1080 TransferSize = DevExt->DataTransferLength;
1083 TargetAddress = DevExt->DataBuffer;
1084 DevExt->DataBuffer += TransferSize;
1085 DevExt->DataTransferLength -= TransferSize;
1087 /* Write the sector */
1088 if (DevExt->DeviceFlags[Srb->TargetId] & DEVICE_DWORD_IO)
1090 IDEWriteBlock32(CommandPortBase,
1096 IDEWriteBlock(CommandPortBase,
1102 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1106 DPRINT("Unspecified transfer direction!\n");
1107 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1113 if (Srb->SrbStatus == SRB_STATUS_ERROR)
1115 Srb->SrbStatus = AtapiErrorToScsi(DeviceExtension,
1120 /* complete this packet */
1123 DevExt->ExpectingInterrupt = FALSE;
1125 ScsiPortNotification(RequestComplete,
1129 ScsiPortNotification(NextRequest,
1134 DPRINT("AtapiInterrupt() done!\n");
1139 // ---------------------------------------------------- Discardable statics
1142 /**********************************************************************
1147 * Searches for devices on the given port.
1154 * Port device specific information.
1157 * Port configuration information.
1160 * TRUE: At least one device is attached to the port.
1161 * FALSE: No device is attached to the port.
1165 AtapiFindDevices(PATAPI_MINIPORT_EXTENSION DeviceExtension,
1166 PPORT_CONFIGURATION_INFORMATION ConfigInfo)
1168 BOOLEAN DeviceFound = FALSE;
1169 ULONG CommandPortBase;
1170 ULONG ControlPortBase;
1175 DPRINT("AtapiFindDevices() called\n");
1177 CommandPortBase = ScsiPortConvertPhysicalAddressToUlong(ConfigInfo->AccessRanges[0].RangeStart);
1178 DPRINT(" CommandPortBase: %x\n", CommandPortBase);
1180 ControlPortBase = ScsiPortConvertPhysicalAddressToUlong(ConfigInfo->AccessRanges[1].RangeStart);
1181 DPRINT(" ControlPortBase: %x\n", ControlPortBase);
1183 for (UnitNumber = 0; UnitNumber < 2; UnitNumber++)
1186 IDEWriteDriveHead(CommandPortBase,
1187 IDE_DH_FIXED | (UnitNumber ? IDE_DH_DRV1 : 0));
1188 ScsiPortStallExecution(500);
1190 /* Disable interrupts */
1191 IDEWriteDriveControl(ControlPortBase,
1193 ScsiPortStallExecution(500);
1195 /* Check if a device is attached to the interface */
1196 IDEWriteCylinderHigh(CommandPortBase, 0xaa);
1197 IDEWriteCylinderLow(CommandPortBase, 0x55);
1199 High = IDEReadCylinderHigh(CommandPortBase);
1200 Low = IDEReadCylinderLow(CommandPortBase);
1202 IDEWriteCylinderHigh(CommandPortBase, 0);
1203 IDEWriteCylinderLow(CommandPortBase, 0);
1205 if (Low != 0x55 || High != 0xaa)
1207 DPRINT("No Drive found. UnitNumber %d CommandPortBase %x\n", UnitNumber, CommandPortBase);
1211 IDEWriteCommand(CommandPortBase, IDE_CMD_RESET);
1213 for (Retries = 0; Retries < 20000; Retries++)
1215 if (!(IDEReadStatus(CommandPortBase) & IDE_SR_BUSY))
1219 ScsiPortStallExecution(150);
1221 if (Retries >= 20000)
1223 DPRINT("Timeout on drive %lu\n", UnitNumber);
1224 DeviceExtension->DeviceFlags[UnitNumber] &= ~DEVICE_PRESENT;
1228 High = IDEReadCylinderHigh(CommandPortBase);
1229 Low = IDEReadCylinderLow(CommandPortBase);
1231 DPRINT(" Check drive %lu: High 0x%x Low 0x%x\n",
1236 if (High == 0xEB && Low == 0x14)
1238 if (AtapiIdentifyDevice(CommandPortBase,
1242 &DeviceExtension->DeviceParams[UnitNumber]))
1244 DPRINT(" ATAPI drive found!\n");
1245 DeviceExtension->DeviceFlags[UnitNumber] |= DEVICE_PRESENT;
1246 DeviceExtension->DeviceFlags[UnitNumber] |= DEVICE_ATAPI;
1247 DeviceExtension->TransferSize[UnitNumber] =
1248 DeviceExtension->DeviceParams[UnitNumber].BytesPerSector;
1253 DPRINT(" No ATAPI drive found!\n");
1258 if (AtapiIdentifyDevice(CommandPortBase,
1262 &DeviceExtension->DeviceParams[UnitNumber]))
1264 DPRINT(" IDE drive found!\n");
1265 DeviceExtension->DeviceFlags[UnitNumber] |= DEVICE_PRESENT;
1266 DeviceExtension->TransferSize[UnitNumber] = DeviceExtension->DeviceParams[UnitNumber].BytesPerSector;
1267 if ((DeviceExtension->DeviceParams[UnitNumber].RWMultImplemented & 0x8000) &&
1268 (DeviceExtension->DeviceParams[UnitNumber].RWMultImplemented & 0xff) &&
1269 (DeviceExtension->DeviceParams[UnitNumber].RWMultCurrent & 0x100) &&
1270 (DeviceExtension->DeviceParams[UnitNumber].RWMultCurrent & 0xff))
1272 DeviceExtension->TransferSize[UnitNumber] *= (DeviceExtension->DeviceParams[UnitNumber].RWMultCurrent & 0xff);
1273 DeviceExtension->DeviceFlags[UnitNumber] |= DEVICE_MULTI_SECTOR_CMD;
1276 if (DeviceExtension->DeviceParams[UnitNumber].DWordIo)
1278 DeviceExtension->DeviceFlags[UnitNumber] |= DEVICE_DWORD_IO;
1285 DPRINT(" No IDE drive found!\n");
1290 /* Reset pending interrupts */
1291 IDEReadStatus(CommandPortBase);
1292 /* Reenable interrupts */
1293 IDEWriteDriveControl(ControlPortBase, 0);
1294 ScsiPortStallExecution(500);
1295 /* Return with drive 0 selected */
1296 IDEWriteDriveHead(CommandPortBase, IDE_DH_FIXED);
1297 ScsiPortStallExecution(500);
1299 DPRINT("AtapiFindDrives() done (DeviceFound %s)\n", (DeviceFound) ? "TRUE" : "FALSE");
1301 return(DeviceFound);
1305 // AtapiResetController
1308 // Reset the controller and report completion status
1314 // IN WORD CommandPort The address of the command port
1315 // IN WORD ControlPort The address of the control port
1321 AtapiResetController(IN ULONG CommandPort,
1322 IN ULONG ControlPort)
1326 /* Assert drive reset line */
1327 IDEWriteDriveControl(ControlPort, IDE_DC_SRST);
1329 /* Wait for min. 25 microseconds */
1330 ScsiPortStallExecution(IDE_RESET_PULSE_LENGTH);
1332 /* Negate drive reset line */
1333 IDEWriteDriveControl(ControlPort, 0);
1335 /* Wait for BUSY negation */
1336 for (Retries = 0; Retries < IDE_RESET_BUSY_TIMEOUT * 1000; Retries++)
1338 if (!(IDEReadStatus(CommandPort) & IDE_SR_BUSY))
1342 ScsiPortStallExecution(10);
1345 if (Retries >= IDE_RESET_BUSY_TIMEOUT * 1000)
1350 // return TRUE if controller came back to life. and
1351 // the registers are initialized correctly
1352 return(IDEReadError(CommandPort) == 1);
1356 * AtapiIdentifyDevice
1359 * Get the identification block from the drive
1366 * Address of the command port
1368 * Address of the control port
1370 * The drive index (0,1)
1372 * Send an ATA(FALSE) or an ATAPI(TRUE) identify comand
1374 * Address to write drive ident block
1377 * TRUE: The drive identification block was retrieved successfully
1378 * FALSE: an error ocurred
1382 AtapiIdentifyDevice(IN ULONG CommandPort,
1383 IN ULONG ControlPort,
1386 OUT PIDE_DRIVE_IDENTIFY DrvParms)
1390 /* Get the Drive Identify block from drive or die */
1391 if (AtapiPolledRead(CommandPort,
1398 (DriveNum ? IDE_DH_DRV1 : 0),
1399 (Atapi ? IDE_CMD_IDENT_ATAPI_DRV : IDE_CMD_IDENT_ATA_DRV),
1400 (BYTE *)DrvParms) != 0)
1402 DPRINT("IDEPolledRead() failed\n");
1406 /* Report on drive parameters if debug mode */
1407 IDESwapBytePairs(DrvParms->SerialNumber, 20);
1408 IDESwapBytePairs(DrvParms->FirmwareRev, 8);
1409 IDESwapBytePairs(DrvParms->ModelNumber, 40);
1410 DPRINT("Config:%04x Cyls:%5d Heads:%2d Sectors/Track:%3d Gaps:%02d %02d\n",
1411 DrvParms->ConfigBits,
1412 DrvParms->LogicalCyls,
1413 DrvParms->LogicalHeads,
1414 DrvParms->SectorsPerTrack,
1415 DrvParms->InterSectorGap,
1416 DrvParms->InterSectorGapSize);
1417 DPRINT("Bytes/PLO:%3d Vendor Cnt:%2d Serial number:[%.20s]\n",
1418 DrvParms->BytesInPLO,
1419 DrvParms->VendorUniqueCnt,
1420 DrvParms->SerialNumber);
1421 DPRINT("Cntlr type:%2d BufSiz:%5d ECC bytes:%3d Firmware Rev:[%.8s]\n",
1422 DrvParms->ControllerType,
1423 DrvParms->BufferSize * IDE_SECTOR_BUF_SZ,
1424 DrvParms->ECCByteCnt,
1425 DrvParms->FirmwareRev);
1426 DPRINT("Model:[%.40s]\n", DrvParms->ModelNumber);
1427 DPRINT("RWMultMax?:%04x RWMult?:%02x LBA:%d DMA:%d MinPIO:%d ns MinDMA:%d ns\n",
1428 (DrvParms->RWMultImplemented),
1429 (DrvParms->RWMultCurrent) & 0xff,
1430 (DrvParms->Capabilities & IDE_DRID_LBA_SUPPORTED) ? 1 : 0,
1431 (DrvParms->Capabilities & IDE_DRID_DMA_SUPPORTED) ? 1 : 0,
1432 DrvParms->MinPIOTransTime,
1433 DrvParms->MinDMATransTime);
1434 DPRINT("TM:Cyls:%d Heads:%d Sectors/Trk:%d Capacity:%ld\n",
1435 DrvParms->TMCylinders,
1437 DrvParms->TMSectorsPerTrk,
1438 (ULONG)(DrvParms->TMCapacityLo + (DrvParms->TMCapacityHi << 16)));
1439 DPRINT("TM:SectorCount: 0x%04x%04x = %lu\n",
1440 DrvParms->TMSectorCountHi,
1441 DrvParms->TMSectorCountLo,
1442 (ULONG)((DrvParms->TMSectorCountHi << 16) + DrvParms->TMSectorCountLo));
1444 if (! Atapi && 0 != (DrvParms->Capabilities & IDE_DRID_LBA_SUPPORTED))
1446 /* LBA ATA drives always have a sector size of 512 */
1447 DrvParms->BytesPerSector = 512;
1451 DPRINT("BytesPerSector %d\n", DrvParms->BytesPerSector);
1452 if (DrvParms->BytesPerSector == 0)
1454 DrvParms->BytesPerSector = 512;
1458 for (i = 15; i >= 0; i--)
1460 if (DrvParms->BytesPerSector & (1 << i))
1462 DrvParms->BytesPerSector = 1 << i;
1468 DPRINT("BytesPerSector %d\n", DrvParms->BytesPerSector);
1477 // Read a sector of data from the drive in a polled fashion.
1483 // IN WORD Address Address of command port for drive
1484 // IN BYTE PreComp Value to write to precomp register
1485 // IN BYTE SectorCnt Value to write to sectorCnt register
1486 // IN BYTE SectorNum Value to write to sectorNum register
1487 // IN BYTE CylinderLow Value to write to CylinderLow register
1488 // IN BYTE CylinderHigh Value to write to CylinderHigh register
1489 // IN BYTE DrvHead Value to write to Drive/Head register
1490 // IN BYTE Command Value to write to Command register
1491 // OUT BYTE *Buffer Buffer for output data
1494 // int 0 is success, non 0 is an error code
1498 AtapiPolledRead(IN ULONG CommandPort,
1499 IN ULONG ControlPort,
1503 IN BYTE CylinderLow,
1504 IN BYTE CylinderHigh,
1509 ULONG SectorCount = 0;
1511 BOOLEAN Junk = FALSE;
1515 /* Wait for BUSY to clear */
1516 for (RetryCount = 0; RetryCount < IDE_MAX_BUSY_RETRIES; RetryCount++)
1518 Status = IDEReadStatus(CommandPort);
1519 if (!(Status & IDE_SR_BUSY))
1523 ScsiPortStallExecution(10);
1525 DPRINT("status=%02x\n", Status);
1526 DPRINT("waited %ld usecs for busy to clear\n", RetryCount * 10);
1527 if (RetryCount >= IDE_MAX_BUSY_RETRIES)
1529 DPRINT("Drive is BUSY for too long\n");
1530 return(IDE_ER_ABRT);
1534 /* Write Drive/Head to select drive */
1535 IDEWriteDriveHead(CommandPort, IDE_DH_FIXED | DrvHead);
1536 ScsiPortStallExecution(500);
1538 /* Disable interrupts */
1539 IDEWriteDriveControl(ControlPort, IDE_DC_nIEN);
1540 ScsiPortStallExecution(500);
1543 /* Wait for STATUS.BUSY and STATUS.DRQ to clear */
1544 for (RetryCount = 0; RetryCount < IDE_MAX_BUSY_RETRIES; RetryCount++)
1546 Status = IDEReadStatus(CommandPort);
1547 if (!(Status & IDE_SR_BUSY) && !(Status & IDE_SR_DRQ))
1551 ScsiPortStallExecution(10);
1553 if (RetryCount >= IDE_MAX_BUSY_RETRIES)
1559 /* Issue command to drive */
1560 if (DrvHead & IDE_DH_LBA)
1562 DPRINT("READ:DRV=%d:LBA=1:BLK=%08d:SC=%02x:CM=%02x\n",
1563 DrvHead & IDE_DH_DRV1 ? 1 : 0,
1564 ((DrvHead & 0x0f) << 24) + (CylinderHigh << 16) + (CylinderLow << 8) + SectorNum,
1570 DPRINT("READ:DRV=%d:LBA=0:CH=%02x:CL=%02x:HD=%01x:SN=%02x:SC=%02x:CM=%02x\n",
1571 DrvHead & IDE_DH_DRV1 ? 1 : 0,
1580 /* Setup command parameters */
1581 IDEWritePrecomp(CommandPort, PreComp);
1582 IDEWriteSectorCount(CommandPort, SectorCnt);
1583 IDEWriteSectorNum(CommandPort, SectorNum);
1584 IDEWriteCylinderHigh(CommandPort, CylinderHigh);
1585 IDEWriteCylinderLow(CommandPort, CylinderLow);
1586 IDEWriteDriveHead(CommandPort, IDE_DH_FIXED | DrvHead);
1588 /* Issue the command */
1589 IDEWriteCommand(CommandPort, Command);
1590 ScsiPortStallExecution(50);
1592 /* wait for DRQ or error */
1593 for (RetryCount = 0; RetryCount < IDE_MAX_POLL_RETRIES; RetryCount++)
1595 Status = IDEReadStatus(CommandPort);
1596 if (!(Status & IDE_SR_BUSY))
1598 if (Status & IDE_SR_ERR)
1600 IDEWriteDriveControl(ControlPort, 0);
1601 ScsiPortStallExecution(50);
1602 IDEReadStatus(CommandPort);
1604 return(IDE_ER_ABRT);
1606 if (Status & IDE_SR_DRQ)
1612 IDEWriteDriveControl(ControlPort, 0);
1613 ScsiPortStallExecution(50);
1614 IDEReadStatus(CommandPort);
1616 return(IDE_ER_ABRT);
1619 ScsiPortStallExecution(10);
1623 if (RetryCount >= IDE_MAX_POLL_RETRIES)
1625 IDEWriteDriveControl(ControlPort, 0);
1626 ScsiPortStallExecution(50);
1627 IDEReadStatus(CommandPort);
1629 return(IDE_ER_ABRT);
1634 /* Read data into buffer */
1637 IDEReadBlock(CommandPort, Buffer, IDE_SECTOR_BUF_SZ);
1638 Buffer += IDE_SECTOR_BUF_SZ;
1642 UCHAR JunkBuffer[IDE_SECTOR_BUF_SZ];
1643 IDEReadBlock(CommandPort, JunkBuffer, IDE_SECTOR_BUF_SZ);
1647 /* Check for error or more sectors to read */
1648 for (RetryCount = 0; RetryCount < IDE_MAX_BUSY_RETRIES; RetryCount++)
1650 Status = IDEReadStatus(CommandPort);
1651 if (!(Status & IDE_SR_BUSY))
1653 if (Status & IDE_SR_ERR)
1655 IDEWriteDriveControl(ControlPort, 0);
1656 ScsiPortStallExecution(50);
1657 IDEReadStatus(CommandPort);
1659 return(IDE_ER_ABRT);
1661 if (Status & IDE_SR_DRQ)
1663 if (SectorCount >= SectorCnt)
1665 DPRINT("Buffer size exceeded!\n");
1672 if (SectorCount > SectorCnt)
1674 DPRINT("Read %lu sectors of junk!\n",
1675 SectorCount - SectorCnt);
1677 IDEWriteDriveControl(ControlPort, 0);
1678 ScsiPortStallExecution(50);
1679 IDEReadStatus(CommandPort);
1689 // ------------------------------------------- Nondiscardable statics
1692 AtapiSendAtapiCommand(IN PATAPI_MINIPORT_EXTENSION DeviceExtension,
1693 IN PSCSI_REQUEST_BLOCK Srb)
1695 UCHAR ByteCountHigh;
1701 DPRINT("AtapiSendAtapiCommand() called!\n");
1703 if (Srb->PathId != 0)
1705 Srb->SrbStatus = SRB_STATUS_INVALID_PATH_ID;
1706 return(SRB_STATUS_INVALID_PATH_ID);
1709 if (Srb->TargetId > 1)
1711 Srb->SrbStatus = SRB_STATUS_INVALID_TARGET_ID;
1712 return(SRB_STATUS_INVALID_TARGET_ID);
1717 Srb->SrbStatus = SRB_STATUS_INVALID_LUN;
1718 return(SRB_STATUS_INVALID_LUN);
1721 if (!(DeviceExtension->DeviceFlags[Srb->TargetId] & DEVICE_PRESENT))
1723 Srb->SrbStatus = SRB_STATUS_NO_DEVICE;
1724 return(SRB_STATUS_NO_DEVICE);
1727 DPRINT("AtapiSendAtapiCommand(): TargetId: %lu\n",
1730 if (Srb->Cdb[0] == SCSIOP_INQUIRY)
1731 return(AtapiInquiry(DeviceExtension,
1734 /* Set pointer to data buffer. */
1735 DeviceExtension->DataBuffer = (PUCHAR)Srb->DataBuffer;
1736 DeviceExtension->DataTransferLength = Srb->DataTransferLength;
1737 DeviceExtension->CurrentSrb = Srb;
1739 /* Wait for BUSY to clear */
1740 for (Retries = 0; Retries < IDE_MAX_BUSY_RETRIES; Retries++)
1742 Status = IDEReadStatus(DeviceExtension->CommandPortBase);
1743 if (!(Status & IDE_SR_BUSY))
1747 ScsiPortStallExecution(10);
1749 DPRINT("status=%02x\n", Status);
1750 DPRINT("waited %ld usecs for busy to clear\n", Retries * 10);
1751 if (Retries >= IDE_MAX_BUSY_RETRIES)
1753 DPRINT("Drive is BUSY for too long\n");
1754 return(SRB_STATUS_BUSY);
1757 /* Select the desired drive */
1758 IDEWriteDriveHead(DeviceExtension->CommandPortBase,
1759 IDE_DH_FIXED | (Srb->TargetId ? IDE_DH_DRV1 : 0));
1761 /* Wait a little while */
1762 ScsiPortStallExecution(50);
1765 /* Wait for BUSY to clear and DRDY to assert */
1766 for (Retries = 0; Retries < IDE_MAX_BUSY_RETRIES; Retries++)
1768 Status = IDEReadStatus(DeviceExtension->CommandPortBase);
1769 if (!(Status & IDE_SR_BUSY) && (Status & IDE_SR_DRDY))
1773 ScsiPortStallExecution(10);
1775 DPRINT("waited %ld usecs for busy to clear after drive select\n", Retries * 10);
1776 if (Retries >= IDE_MAX_BUSY_RETRIES)
1778 DPRINT("Drive is BUSY for too long after drive select\n");
1779 return(SRB_STATUS_BUSY);
1783 if (DeviceExtension->DataTransferLength < 0x10000)
1785 ByteCountLow = (UCHAR)(DeviceExtension->DataTransferLength & 0xFF);
1786 ByteCountHigh = (UCHAR)(DeviceExtension->DataTransferLength >> 8);
1790 ByteCountLow = 0xFF;
1791 ByteCountHigh = 0xFF;
1794 /* Set feature register */
1795 IDEWritePrecomp(DeviceExtension->CommandPortBase, 0);
1797 /* Set command packet length */
1798 IDEWriteCylinderHigh(DeviceExtension->CommandPortBase, ByteCountHigh);
1799 IDEWriteCylinderLow(DeviceExtension->CommandPortBase, ByteCountLow);
1801 /* Issue command to drive */
1802 IDEWriteCommand(DeviceExtension->CommandPortBase, IDE_CMD_PACKET);
1804 /* Wait for DRQ to assert */
1805 for (Retries = 0; Retries < IDE_MAX_BUSY_RETRIES; Retries++)
1807 Status = IDEReadStatus(DeviceExtension->CommandPortBase);
1808 if ((Status & IDE_SR_DRQ))
1812 ScsiPortStallExecution(10);
1815 /* Convert special SCSI SRBs to ATAPI format */
1816 switch (Srb->Cdb[0])
1818 case SCSIOP_FORMAT_UNIT:
1819 case SCSIOP_MODE_SELECT:
1820 case SCSIOP_MODE_SENSE:
1821 AtapiScsiSrbToAtapi (Srb);
1825 CdbSize = (DeviceExtension->DeviceParams[Srb->TargetId].ConfigBits & 0x3 == 1) ? 16 : 12;
1826 DPRINT("CdbSize: %lu\n", CdbSize);
1828 /* Write command packet */
1829 IDEWriteBlock(DeviceExtension->CommandPortBase,
1833 DeviceExtension->ExpectingInterrupt = TRUE;
1835 DPRINT("AtapiSendAtapiCommand() done\n");
1837 return(SRB_STATUS_PENDING);
1842 AtapiSendIdeCommand(IN PATAPI_MINIPORT_EXTENSION DeviceExtension,
1843 IN PSCSI_REQUEST_BLOCK Srb)
1845 ULONG SrbStatus = SRB_STATUS_SUCCESS;
1847 DPRINT("AtapiSendIdeCommand() called!\n");
1849 DPRINT("PathId: %lu TargetId: %lu Lun: %lu\n",
1854 if (Srb->PathId != 0)
1856 Srb->SrbStatus = SRB_STATUS_INVALID_PATH_ID;
1857 return(SRB_STATUS_INVALID_PATH_ID);
1860 if (Srb->TargetId > 1)
1862 Srb->SrbStatus = SRB_STATUS_INVALID_TARGET_ID;
1863 return(SRB_STATUS_INVALID_TARGET_ID);
1868 Srb->SrbStatus = SRB_STATUS_INVALID_LUN;
1869 return(SRB_STATUS_INVALID_LUN);
1872 if (!(DeviceExtension->DeviceFlags[Srb->TargetId] & DEVICE_PRESENT))
1874 Srb->SrbStatus = SRB_STATUS_NO_DEVICE;
1875 return(SRB_STATUS_NO_DEVICE);
1878 switch (Srb->Cdb[0])
1880 case SCSIOP_INQUIRY:
1881 SrbStatus = AtapiInquiry(DeviceExtension,
1885 case SCSIOP_READ_CAPACITY:
1886 SrbStatus = AtapiReadCapacity(DeviceExtension,
1892 SrbStatus = AtapiReadWrite(DeviceExtension,
1896 case SCSIOP_SYNCHRONIZE_CACHE:
1897 SrbStatus = AtapiFlushCache(DeviceExtension,
1901 case SCSIOP_TEST_UNIT_READY:
1902 SrbStatus = AtapiTestUnitReady(DeviceExtension,
1906 case SCSIOP_MODE_SENSE:
1909 case SCSIOP_START_STOP_UNIT:
1910 case SCSIOP_REQUEST_SENSE:
1914 DbgPrint("AtapiSendIdeCommand():unknown command %x\n",
1916 SrbStatus = SRB_STATUS_INVALID_REQUEST;
1920 DPRINT("AtapiSendIdeCommand() done!\n");
1927 AtapiInquiry(PATAPI_MINIPORT_EXTENSION DeviceExtension,
1928 PSCSI_REQUEST_BLOCK Srb)
1930 PIDE_DRIVE_IDENTIFY DeviceParams;
1931 PINQUIRYDATA InquiryData;
1934 DPRINT("SCSIOP_INQUIRY: DeviceExtension %p TargetId: %lu\n",
1935 DeviceExtension, Srb->TargetId);
1937 InquiryData = Srb->DataBuffer;
1938 DeviceParams = &DeviceExtension->DeviceParams[Srb->TargetId];
1941 for (i = 0; i < Srb->DataTransferLength; i++)
1943 ((PUCHAR)Srb->DataBuffer)[i] = 0;
1946 /* set device class */
1947 if (DeviceExtension->DeviceFlags[Srb->TargetId] & DEVICE_ATAPI)
1949 /* get it from the ATAPI configuration word */
1950 InquiryData->DeviceType = (DeviceParams->ConfigBits >> 8) & 0x1F;
1951 DPRINT("Device class: %u\n", InquiryData->DeviceType);
1956 InquiryData->DeviceType = DIRECT_ACCESS_DEVICE;
1959 DPRINT("ConfigBits: 0x%x\n", DeviceParams->ConfigBits);
1960 if (DeviceParams->ConfigBits & 0x80)
1962 DPRINT("Removable media!\n");
1963 InquiryData->RemovableMedia = 1;
1966 for (i = 0; i < 20; i += 2)
1968 InquiryData->VendorId[i] =
1969 ((PUCHAR)DeviceParams->ModelNumber)[i];
1970 InquiryData->VendorId[i+1] =
1971 ((PUCHAR)DeviceParams->ModelNumber)[i+1];
1974 for (i = 0; i < 4; i++)
1976 InquiryData->ProductId[12+i] = ' ';
1979 for (i = 0; i < 4; i += 2)
1981 InquiryData->ProductRevisionLevel[i] =
1982 ((PUCHAR)DeviceParams->FirmwareRev)[i];
1983 InquiryData->ProductRevisionLevel[i+1] =
1984 ((PUCHAR)DeviceParams->FirmwareRev)[i+1];
1987 DPRINT("VendorId: '%.20s'\n", InquiryData->VendorId);
1989 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1990 return(SRB_STATUS_SUCCESS);
1995 AtapiReadCapacity(PATAPI_MINIPORT_EXTENSION DeviceExtension,
1996 PSCSI_REQUEST_BLOCK Srb)
1998 PREAD_CAPACITY_DATA CapacityData;
1999 PIDE_DRIVE_IDENTIFY DeviceParams;
2002 DPRINT("SCSIOP_READ_CAPACITY: TargetId: %lu\n", Srb->TargetId);
2003 CapacityData = (PREAD_CAPACITY_DATA)Srb->DataBuffer;
2004 DeviceParams = &DeviceExtension->DeviceParams[Srb->TargetId];
2006 /* Set sector (block) size to 512 bytes (big-endian). */
2007 CapacityData->BytesPerBlock = 0x20000;
2009 /* Calculate last sector (big-endian). */
2010 if (DeviceParams->Capabilities & IDE_DRID_LBA_SUPPORTED)
2012 LastSector = (ULONG)((DeviceParams->TMSectorCountHi << 16) +
2013 DeviceParams->TMSectorCountLo) - 1;
2017 LastSector = (ULONG)(DeviceParams->LogicalCyls *
2018 DeviceParams->LogicalHeads *
2019 DeviceParams->SectorsPerTrack)-1;
2022 CapacityData->LogicalBlockAddress = (((PUCHAR)&LastSector)[0] << 24) |
2023 (((PUCHAR)&LastSector)[1] << 16) |
2024 (((PUCHAR)&LastSector)[2] << 8) |
2025 ((PUCHAR)&LastSector)[3];
2027 DPRINT("LastCount: %lu (%08lx / %08lx)\n",
2030 CapacityData->LogicalBlockAddress);
2032 Srb->SrbStatus = SRB_STATUS_SUCCESS;
2033 return(SRB_STATUS_SUCCESS);
2038 AtapiReadWrite(PATAPI_MINIPORT_EXTENSION DeviceExtension,
2039 PSCSI_REQUEST_BLOCK Srb)
2041 PIDE_DRIVE_IDENTIFY DeviceParams;
2042 ULONG StartingSector;
2052 DPRINT("AtapiReadWrite() called!\n");
2053 DPRINT("SCSIOP_WRITE: TargetId: %lu\n",
2056 DeviceParams = &DeviceExtension->DeviceParams[Srb->TargetId];
2058 /* Get starting sector number from CDB. */
2059 StartingSector = ((PCDB)Srb->Cdb)->CDB10.LogicalBlockByte3 |
2060 ((PCDB)Srb->Cdb)->CDB10.LogicalBlockByte2 << 8 |
2061 ((PCDB)Srb->Cdb)->CDB10.LogicalBlockByte1 << 16 |
2062 ((PCDB)Srb->Cdb)->CDB10.LogicalBlockByte0 << 24;
2064 SectorCount = (Srb->DataTransferLength + DeviceParams->BytesPerSector - 1) /
2065 DeviceParams->BytesPerSector;
2067 DPRINT("Starting sector %lu Number of bytes %lu Sectors %lu\n",
2069 Srb->DataTransferLength,
2072 if (DeviceParams->Capabilities & IDE_DRID_LBA_SUPPORTED)
2074 SectorNumber = StartingSector & 0xff;
2075 CylinderLow = (StartingSector >> 8) & 0xff;
2076 CylinderHigh = (StartingSector >> 16) & 0xff;
2077 DrvHead = ((StartingSector >> 24) & 0x0f) |
2078 (Srb->TargetId ? IDE_DH_DRV1 : 0) |
2083 SectorNumber = (StartingSector % DeviceParams->SectorsPerTrack) + 1;
2084 StartingSector /= DeviceParams->SectorsPerTrack;
2085 DrvHead = (StartingSector % DeviceParams->LogicalHeads) |
2086 (Srb->TargetId ? IDE_DH_DRV1 : 0);
2087 StartingSector /= DeviceParams->LogicalHeads;
2088 CylinderLow = StartingSector & 0xff;
2089 CylinderHigh = StartingSector >> 8;
2093 if (Srb->SrbFlags & SRB_FLAGS_DATA_IN)
2095 Command = (DeviceExtension->DeviceFlags[Srb->TargetId] & DEVICE_MULTI_SECTOR_CMD) ? IDE_CMD_READ_MULTIPLE : IDE_CMD_READ;
2099 Command = (DeviceExtension->DeviceFlags[Srb->TargetId] & DEVICE_MULTI_SECTOR_CMD) ? IDE_CMD_WRITE_MULTIPLE : IDE_CMD_WRITE;
2102 if (DrvHead & IDE_DH_LBA)
2104 DPRINT("%s:BUS=%04x:DRV=%d:LBA=1:BLK=%08d:SC=%02x:CM=%02x\n",
2105 (Srb->SrbFlags & SRB_FLAGS_DATA_IN) ? "READ" : "WRITE",
2106 DeviceExtension->CommandPortBase,
2107 DrvHead & IDE_DH_DRV1 ? 1 : 0,
2108 ((DrvHead & 0x0f) << 24) +
2109 (CylinderHigh << 16) + (CylinderLow << 8) + SectorNumber,
2115 DPRINT("%s:BUS=%04x:DRV=%d:LBA=0:CH=%02x:CL=%02x:HD=%01x:SN=%02x:SC=%02x:CM=%02x\n",
2116 (Srb->SrbFlags & SRB_FLAGS_DATA_IN) ? "READ" : "WRITE",
2117 DeviceExtension->CommandPortBase,
2118 DrvHead & IDE_DH_DRV1 ? 1 : 0,
2127 /* Set pointer to data buffer. */
2128 DeviceExtension->DataBuffer = (PUCHAR)Srb->DataBuffer;
2129 DeviceExtension->DataTransferLength = Srb->DataTransferLength;
2131 DeviceExtension->CurrentSrb = Srb;
2133 /* wait for BUSY to clear */
2134 for (Retries = 0; Retries < IDE_MAX_BUSY_RETRIES; Retries++)
2136 Status = IDEReadStatus(DeviceExtension->CommandPortBase);
2137 if (!(Status & IDE_SR_BUSY))
2141 ScsiPortStallExecution(10);
2143 DPRINT("status=%02x\n", Status);
2144 DPRINT("waited %ld usecs for busy to clear\n", Retries * 10);
2145 if (Retries >= IDE_MAX_BUSY_RETRIES)
2147 DPRINT ("Drive is BUSY for too long\n");
2148 return(SRB_STATUS_BUSY);
2151 /* Select the desired drive */
2152 IDEWriteDriveHead(DeviceExtension->CommandPortBase,
2153 IDE_DH_FIXED | DrvHead);
2155 ScsiPortStallExecution(10);
2157 /* wait for BUSY to clear and DRDY to assert */
2158 for (Retries = 0; Retries < IDE_MAX_BUSY_RETRIES; Retries++)
2160 Status = IDEReadStatus(DeviceExtension->CommandPortBase);
2161 if (!(Status & IDE_SR_BUSY) && (Status & IDE_SR_DRDY))
2165 ScsiPortStallExecution(10);
2167 DPRINT("waited %ld usecs for busy to clear after drive select\n", Retries * 10);
2168 if (Retries >= IDE_MAX_BUSY_RETRIES)
2170 DPRINT("Drive is BUSY for too long after drive select\n");
2171 return(SRB_STATUS_BUSY);
2175 /* Setup command parameters */
2176 IDEWritePrecomp(DeviceExtension->CommandPortBase, 0);
2177 IDEWriteSectorCount(DeviceExtension->CommandPortBase, SectorCount);
2178 IDEWriteSectorNum(DeviceExtension->CommandPortBase, SectorNumber);
2179 IDEWriteCylinderHigh(DeviceExtension->CommandPortBase, CylinderHigh);
2180 IDEWriteCylinderLow(DeviceExtension->CommandPortBase, CylinderLow);
2181 IDEWriteDriveHead(DeviceExtension->CommandPortBase, IDE_DH_FIXED | DrvHead);
2183 /* Indicate expecting an interrupt. */
2184 DeviceExtension->ExpectingInterrupt = TRUE;
2186 /* Issue command to drive */
2187 IDEWriteCommand(DeviceExtension->CommandPortBase, Command);
2189 /* Write data block */
2190 if (Srb->SrbFlags & SRB_FLAGS_DATA_OUT)
2192 PUCHAR TargetAddress;
2195 /* Wait for controller ready */
2196 for (Retries = 0; Retries < IDE_MAX_WRITE_RETRIES; Retries++)
2198 BYTE Status = IDEReadStatus(DeviceExtension->CommandPortBase);
2199 if (!(Status & IDE_SR_BUSY) || (Status & IDE_SR_ERR))
2203 KeStallExecutionProcessor(10);
2205 if (Retries >= IDE_MAX_WRITE_RETRIES)
2207 DPRINT1("Drive is BUSY for too long after sending write command\n");
2208 return(SRB_STATUS_BUSY);
2211 /* Update DeviceExtension data */
2212 TransferSize = DeviceExtension->TransferSize[Srb->TargetId];
2213 if (DeviceExtension->DataTransferLength < TransferSize)
2215 TransferSize = DeviceExtension->DataTransferLength;
2218 TargetAddress = DeviceExtension->DataBuffer;
2219 DeviceExtension->DataBuffer += TransferSize;
2220 DeviceExtension->DataTransferLength -= TransferSize;
2222 /* Write data block */
2223 if (DeviceExtension->DeviceFlags[Srb->TargetId] & DEVICE_DWORD_IO)
2225 IDEWriteBlock32(DeviceExtension->CommandPortBase,
2231 IDEWriteBlock(DeviceExtension->CommandPortBase,
2237 DPRINT("AtapiReadWrite() done!\n");
2239 /* Wait for interrupt. */
2240 return(SRB_STATUS_PENDING);
2245 AtapiFlushCache(PATAPI_MINIPORT_EXTENSION DeviceExtension,
2246 PSCSI_REQUEST_BLOCK Srb)
2251 DPRINT("AtapiFlushCache() called!\n");
2252 DPRINT("SCSIOP_SYNCRONIZE_CACHE: TargetId: %lu\n",
2255 /* Wait for BUSY to clear */
2256 for (Retries = 0; Retries < IDE_MAX_BUSY_RETRIES; Retries++)
2258 Status = IDEReadStatus(DeviceExtension->CommandPortBase);
2259 if (!(Status & IDE_SR_BUSY))
2263 ScsiPortStallExecution(10);
2265 DPRINT("Status=%02x\n", Status);
2266 DPRINT("Waited %ld usecs for busy to clear\n", Retries * 10);
2267 if (Retries >= IDE_MAX_BUSY_RETRIES)
2269 DPRINT1("Drive is BUSY for too long\n");
2270 return(SRB_STATUS_BUSY);
2273 /* Select the desired drive */
2274 IDEWriteDriveHead(DeviceExtension->CommandPortBase,
2275 IDE_DH_FIXED | (Srb->TargetId ? IDE_DH_DRV1 : 0));
2276 ScsiPortStallExecution(10);
2278 /* Issue command to drive */
2279 IDEWriteCommand(DeviceExtension->CommandPortBase, IDE_CMD_FLUSH_CACHE);
2281 /* Wait for controller ready */
2282 for (Retries = 0; Retries < IDE_MAX_WRITE_RETRIES; Retries++)
2284 BYTE Status = IDEReadStatus(DeviceExtension->CommandPortBase);
2285 if (!(Status & IDE_SR_BUSY) || (Status & IDE_SR_ERR))
2289 KeStallExecutionProcessor(10);
2291 if (Retries >= IDE_MAX_WRITE_RETRIES)
2293 DPRINT1("Drive is BUSY for too long after sending write command\n");
2294 return(SRB_STATUS_BUSY);
2297 /* Indicate expecting an interrupt. */
2298 DeviceExtension->ExpectingInterrupt = TRUE;
2300 DPRINT("AtapiFlushCache() done!\n");
2302 /* Wait for interrupt. */
2303 return(SRB_STATUS_PENDING);
2308 AtapiTestUnitReady(PATAPI_MINIPORT_EXTENSION DeviceExtension,
2309 PSCSI_REQUEST_BLOCK Srb)
2315 DPRINT1("AtapiTestUnitReady() called!\n");
2317 DPRINT1("SCSIOP_TEST_UNIT_READY: TargetId: %lu\n",
2320 /* Return success if media status is not supported */
2321 if (!(DeviceExtension->DeviceFlags[Srb->TargetId] & DEVICE_MEDIA_STATUS))
2323 Srb->SrbStatus = SRB_STATUS_SUCCESS;
2324 return(SRB_STATUS_SUCCESS);
2327 /* Wait for BUSY to clear */
2328 for (Retries = 0; Retries < IDE_MAX_BUSY_RETRIES; Retries++)
2330 Status = IDEReadStatus(DeviceExtension->CommandPortBase);
2331 if (!(Status & IDE_SR_BUSY))
2335 ScsiPortStallExecution(10);
2337 DPRINT1("Status=%02x\n", Status);
2338 DPRINT1("Waited %ld usecs for busy to clear\n", Retries * 10);
2339 if (Retries >= IDE_MAX_BUSY_RETRIES)
2341 DPRINT1("Drive is BUSY for too long\n");
2342 return(SRB_STATUS_BUSY);
2345 /* Select the desired drive */
2346 IDEWriteDriveHead(DeviceExtension->CommandPortBase,
2347 IDE_DH_FIXED | (Srb->TargetId ? IDE_DH_DRV1 : 0));
2348 ScsiPortStallExecution(10);
2350 /* Issue command to drive */
2351 IDEWriteCommand(DeviceExtension->CommandPortBase, IDE_CMD_GET_MEDIA_STATUS);
2353 /* Wait for controller ready */
2354 for (Retries = 0; Retries < IDE_MAX_WRITE_RETRIES; Retries++)
2356 Status = IDEReadStatus(DeviceExtension->CommandPortBase);
2357 if (!(Status & IDE_SR_BUSY) || (Status & IDE_SR_ERR))
2361 KeStallExecutionProcessor(10);
2363 if (Retries >= IDE_MAX_WRITE_RETRIES)
2365 DPRINT1("Drive is BUSY for too long after sending write command\n");
2366 return(SRB_STATUS_BUSY);
2369 if (Status & IDE_SR_ERR)
2371 Error = IDEReadError(DeviceExtension->CommandPortBase);
2372 if (Error == IDE_ER_UNC)
2375 /* Handle write protection 'error' */
2376 Srb->SrbStatus = SRB_STATUS_SUCCESS;
2377 return(SRB_STATUS_SUCCESS);
2382 /* Indicate expecting an interrupt. */
2383 DeviceExtension->ExpectingInterrupt = TRUE;
2384 return(SRB_STATUS_PENDING);
2388 DPRINT1("AtapiTestUnitReady() done!\n");
2390 Srb->SrbStatus = SRB_STATUS_SUCCESS;
2391 return(SRB_STATUS_SUCCESS);
2396 AtapiErrorToScsi(PVOID DeviceExtension,
2397 PSCSI_REQUEST_BLOCK Srb)
2399 PATAPI_MINIPORT_EXTENSION DevExt;
2400 ULONG CommandPortBase;
2401 ULONG ControlPortBase;
2406 DPRINT("AtapiErrorToScsi() called\n");
2408 DevExt = (PATAPI_MINIPORT_EXTENSION)DeviceExtension;
2410 CommandPortBase = DevExt->CommandPortBase;
2411 ControlPortBase = DevExt->ControlPortBase;
2413 ErrorReg = IDEReadError(CommandPortBase);
2415 if (DevExt->DeviceFlags[Srb->TargetId] & DEVICE_ATAPI)
2417 switch (ErrorReg >> 4)
2419 case SCSI_SENSE_NO_SENSE:
2420 DPRINT("ATAPI error: SCSI_SENSE_NO_SENSE\n");
2421 ScsiStatus = SCSISTAT_CHECK_CONDITION;
2422 SrbStatus = SRB_STATUS_ERROR;
2425 case SCSI_SENSE_RECOVERED_ERROR:
2426 DPRINT("ATAPI error: SCSI_SENSE_RECOVERED_SENSE\n");
2428 SrbStatus = SRB_STATUS_SUCCESS;
2431 case SCSI_SENSE_NOT_READY:
2432 DPRINT("ATAPI error: SCSI_SENSE_NOT_READY\n");
2433 ScsiStatus = SCSISTAT_CHECK_CONDITION;
2434 SrbStatus = SRB_STATUS_ERROR;
2437 case SCSI_SENSE_MEDIUM_ERROR:
2438 DPRINT("ATAPI error: SCSI_SENSE_MEDIUM_ERROR\n");
2439 ScsiStatus = SCSISTAT_CHECK_CONDITION;
2440 SrbStatus = SRB_STATUS_ERROR;
2443 case SCSI_SENSE_HARDWARE_ERROR:
2444 DPRINT("ATAPI error: SCSI_SENSE_HARDWARE_ERROR\n");
2445 ScsiStatus = SCSISTAT_CHECK_CONDITION;
2446 SrbStatus = SRB_STATUS_ERROR;
2449 case SCSI_SENSE_ILLEGAL_REQUEST:
2450 DPRINT("ATAPI error: SCSI_SENSE_ILLEGAL_REQUEST\n");
2451 ScsiStatus = SCSISTAT_CHECK_CONDITION;
2452 SrbStatus = SRB_STATUS_ERROR;
2455 case SCSI_SENSE_UNIT_ATTENTION:
2456 DPRINT("ATAPI error: SCSI_SENSE_UNIT_ATTENTION\n");
2457 ScsiStatus = SCSISTAT_CHECK_CONDITION;
2458 SrbStatus = SRB_STATUS_ERROR;
2461 case SCSI_SENSE_DATA_PROTECT:
2462 DPRINT("ATAPI error: SCSI_SENSE_DATA_PROTECT\n");
2463 ScsiStatus = SCSISTAT_CHECK_CONDITION;
2464 SrbStatus = SRB_STATUS_ERROR;
2467 case SCSI_SENSE_BLANK_CHECK:
2468 DPRINT("ATAPI error: SCSI_SENSE_BLANK_CHECK\n");
2469 ScsiStatus = SCSISTAT_CHECK_CONDITION;
2470 SrbStatus = SRB_STATUS_ERROR;
2473 case SCSI_SENSE_ABORTED_COMMAND:
2474 DPRINT("ATAPI error: SCSI_SENSE_ABORTED_COMMAND\n");
2475 ScsiStatus = SCSISTAT_CHECK_CONDITION;
2476 SrbStatus = SRB_STATUS_ERROR;
2480 DPRINT("ATAPI error: Invalid sense key\n");
2482 SrbStatus = SRB_STATUS_ERROR;
2488 DPRINT1("IDE error: %02x\n", ErrorReg);
2491 SrbStatus = SRB_STATUS_ERROR;
2494 UCHAR SectorCount, SectorNum, CylinderLow, CylinderHigh;
2497 CylinderLow = IDEReadCylinderLow(CommandPortBase);
2498 CylinderHigh = IDEReadCylinderHigh(CommandPortBase);
2499 DriveHead = IDEReadDriveHead(CommandPortBase);
2500 SectorCount = IDEReadSectorCount(CommandPortBase);
2501 SectorNum = IDEReadSectorNum(CommandPortBase);
2503 DPRINT1("IDE Error: ERR:%02x CYLLO:%02x CYLHI:%02x SCNT:%02x SNUM:%02x\n",
2514 Srb->ScsiStatus = ScsiStatus;
2516 DPRINT("AtapiErrorToScsi() done\n");
2523 AtapiScsiSrbToAtapi (PSCSI_REQUEST_BLOCK Srb)
2525 DPRINT("AtapiConvertScsiToAtapi() called\n");
2527 Srb->CdbLength = 12;
2529 switch (Srb->Cdb[0])
2531 case SCSIOP_FORMAT_UNIT:
2532 Srb->Cdb[0] = ATAPI_FORMAT_UNIT;
2535 case SCSIOP_MODE_SELECT:
2537 PATAPI_MODE_SELECT12 AtapiModeSelect;
2540 AtapiModeSelect = (PATAPI_MODE_SELECT12)Srb->Cdb;
2541 Length = ((PCDB)Srb->Cdb)->MODE_SELECT.ParameterListLength;
2543 RtlZeroMemory (Srb->Cdb,
2545 AtapiModeSelect->OperationCode = ATAPI_MODE_SELECT;
2546 AtapiModeSelect->PFBit = 1;
2547 AtapiModeSelect->ParameterListLengthMsb = 0;
2548 AtapiModeSelect->ParameterListLengthLsb = Length;
2552 case SCSIOP_MODE_SENSE:
2554 PATAPI_MODE_SENSE12 AtapiModeSense;
2558 AtapiModeSense = (PATAPI_MODE_SENSE12)Srb->Cdb;
2559 PageCode = ((PCDB)Srb->Cdb)->MODE_SENSE.PageCode;
2560 Length = ((PCDB)Srb->Cdb)->MODE_SENSE.AllocationLength;
2562 RtlZeroMemory (Srb->Cdb,
2564 AtapiModeSense->OperationCode = ATAPI_MODE_SENSE;
2565 AtapiModeSense->PageCode = PageCode;
2566 AtapiModeSense->ParameterListLengthMsb = 0;
2567 AtapiModeSense->ParameterListLengthLsb = Length;