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.
19 /* $Id: atapi.c,v 1.36 2003/01/28 17:34:20 hbirr Exp $
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];
77 BOOLEAN DevicePresent
[2];
78 BOOLEAN DeviceAtapi
[2];
79 ULONG TransferSize
[2];
80 BOOLEAN MultiSectorCommand
[2];
84 ULONG CommandPortBase
;
85 ULONG ControlPortBase
;
86 ULONG BusMasterRegisterBase
;
88 BOOLEAN ExpectingInterrupt
;
89 PSCSI_REQUEST_BLOCK CurrentSrb
;
93 ULONG DataTransferLength
;
94 } ATAPI_MINIPORT_EXTENSION
, *PATAPI_MINIPORT_EXTENSION
;
97 typedef struct _UNIT_EXTENSION
100 } UNIT_EXTENSION
, *PUNIT_EXTENSION
;
102 PCI_SLOT_NUMBER LastSlotNumber
;
104 #ifdef ENABLE_NATIVE_PCI
105 typedef struct _PCI_NATIVE_CONTROLLER
110 PCI_NATIVE_CONTROLLER
, *PPCI_NATIVE_CONTROLLER
;
112 PCI_NATIVE_CONTROLLER
const PciNativeController
[] =
116 0x4D68, // PDC20268, Ultra100TX2
120 0x4D30, // PDC20267, Ultra100
126 // ----------------------------------------------- Discardable Declarations
130 // make the initialization routines discardable, so that they
133 #pragma alloc_text(init, DriverEntry)
134 #pragma alloc_text(init, IDECreateController)
135 #pragma alloc_text(init, IDEPolledRead)
137 // make the PASSIVE_LEVEL routines pageable, so that they don't
138 // waste nonpaged memory
140 #pragma alloc_text(page, IDEShutdown)
141 #pragma alloc_text(page, IDEDispatchOpenClose)
142 #pragma alloc_text(page, IDEDispatchRead)
143 #pragma alloc_text(page, IDEDispatchWrite)
145 #endif /* ALLOC_PRAGMA */
147 // ---------------------------------------------------- Forward Declarations
150 AtapiFindCompatiblePciController(PVOID DeviceExtension
,
152 PVOID BusInformation
,
153 PCHAR ArgumentString
,
154 PPORT_CONFIGURATION_INFORMATION ConfigInfo
,
158 AtapiFindIsaBusController(PVOID DeviceExtension
,
160 PVOID BusInformation
,
161 PCHAR ArgumentString
,
162 PPORT_CONFIGURATION_INFORMATION ConfigInfo
,
166 AtapiFindNativePciController(PVOID DeviceExtension
,
168 PVOID BusInformation
,
169 PCHAR ArgumentString
,
170 PPORT_CONFIGURATION_INFORMATION ConfigInfo
,
173 static BOOLEAN STDCALL
174 AtapiInitialize(IN PVOID DeviceExtension
);
176 static BOOLEAN STDCALL
177 AtapiResetBus(IN PVOID DeviceExtension
,
180 static BOOLEAN STDCALL
181 AtapiStartIo(IN PVOID DeviceExtension
,
182 IN PSCSI_REQUEST_BLOCK Srb
);
184 static BOOLEAN STDCALL
185 AtapiInterrupt(IN PVOID DeviceExtension
);
188 AtapiFindDevices(PATAPI_MINIPORT_EXTENSION DeviceExtension
,
189 PPORT_CONFIGURATION_INFORMATION ConfigInfo
);
192 AtapiIdentifyDevice(IN ULONG CommandPort
,
193 IN ULONG ControlPort
,
196 OUT PIDE_DRIVE_IDENTIFY DrvParms
);
199 IDEResetController(IN ULONG CommandPort
,
200 IN ULONG ControlPort
);
203 AtapiPolledRead(IN ULONG CommandPort
,
204 IN ULONG ControlPort
,
209 IN BYTE CylinderHigh
,
217 AtapiSendAtapiCommand(IN PATAPI_MINIPORT_EXTENSION DeviceExtension
,
218 IN PSCSI_REQUEST_BLOCK Srb
);
221 AtapiSendIdeCommand(IN PATAPI_MINIPORT_EXTENSION DeviceExtension
,
222 IN PSCSI_REQUEST_BLOCK Srb
);
225 AtapiInquiry(IN PATAPI_MINIPORT_EXTENSION DeviceExtension
,
226 IN PSCSI_REQUEST_BLOCK Srb
);
229 AtapiReadCapacity(IN PATAPI_MINIPORT_EXTENSION DeviceExtension
,
230 IN PSCSI_REQUEST_BLOCK Srb
);
233 AtapiReadWrite(IN PATAPI_MINIPORT_EXTENSION DeviceExtension
,
234 IN PSCSI_REQUEST_BLOCK Srb
);
238 AtapiErrorToScsi(PVOID DeviceExtension
,
239 PSCSI_REQUEST_BLOCK Srb
);
241 // ---------------------------------------------------------------- Inlines
244 IDESwapBytePairs(char *Buf
,
250 for (i
= 0; i
< Cnt
; i
+= 2)
259 // ------------------------------------------------------- Public Interface
264 // This function initializes the driver, locates and claims
265 // hardware resources, and creates various NT objects needed
266 // to process I/O requests.
272 // IN PDRIVER_OBJECT DriverObject System allocated Driver Object
274 // IN PUNICODE_STRING RegistryPath Name of registry driver service
281 DriverEntry(IN PDRIVER_OBJECT DriverObject
,
282 IN PUNICODE_STRING RegistryPath
)
284 HW_INITIALIZATION_DATA InitData
;
287 DPRINT("ATAPI Driver %s\n", VERSION
);
288 DPRINT("RegistryPath: '%wZ'\n", RegistryPath
);
290 /* Initialize data structure */
291 RtlZeroMemory(&InitData
,
292 sizeof(HW_INITIALIZATION_DATA
));
293 InitData
.HwInitializationDataSize
= sizeof(HW_INITIALIZATION_DATA
);
294 InitData
.HwInitialize
= AtapiInitialize
;
295 InitData
.HwResetBus
= AtapiResetBus
;
296 InitData
.HwStartIo
= AtapiStartIo
;
297 InitData
.HwInterrupt
= AtapiInterrupt
;
299 InitData
.DeviceExtensionSize
= sizeof(ATAPI_MINIPORT_EXTENSION
);
300 InitData
.SpecificLuExtensionSize
= sizeof(UNIT_EXTENSION
);
302 InitData
.MapBuffers
= TRUE
;
305 /* Search the PCI bus for compatibility mode ide controllers */
307 InitData
.HwFindAdapter
= AtapiFindCompatiblePciController
;
308 InitData
.NumberOfAccessRanges
= 3;
309 InitData
.AdapterInterfaceType
= PCIBus
;
311 InitData
.VendorId
= NULL
;
312 InitData
.VendorIdLength
= 0;
313 InitData
.DeviceId
= NULL
;
314 InitData
.DeviceIdLength
= 0;
316 Status
= ScsiPortInitialize(DriverObject
,
320 // if (newStatus < statusToReturn)
321 // statusToReturn = newStatus;
324 /* Search the PCI bus for all ide controllers */
325 #ifdef ENABLE_NATIVE_PCI
327 InitData
.HwFindAdapter
= AtapiFindNativePciController
;
328 InitData
.NumberOfAccessRanges
= 3;
329 InitData
.AdapterInterfaceType
= PCIBus
;
331 InitData
.VendorId
= 0;
332 InitData
.VendorIdLength
= 0;
333 InitData
.DeviceId
= 0;
334 InitData
.DeviceIdLength
= 0;
336 LastSlotNumber
.u
.AsULONG
= 0xFFFFFFFF;
338 Status
= ScsiPortInitialize(DriverObject
,
342 // if (newStatus < statusToReturn)
343 // statusToReturn = newStatus;
346 /* Search the ISA bus for ide controllers */
348 InitData
.HwFindAdapter
= AtapiFindIsaBusController
;
349 InitData
.NumberOfAccessRanges
= 2;
350 InitData
.AdapterInterfaceType
= Isa
;
352 InitData
.VendorId
= NULL
;
353 InitData
.VendorIdLength
= 0;
354 InitData
.DeviceId
= NULL
;
355 InitData
.DeviceIdLength
= 0;
357 Status
= ScsiPortInitialize(DriverObject
,
361 // if (newStatus < statusToReturn)
362 // statusToReturn = newStatus;
365 DPRINT("Returning from DriverEntry\n");
372 AtapiClaimHwResources(PATAPI_MINIPORT_EXTENSION DevExt
,
373 PPORT_CONFIGURATION_INFORMATION ConfigInfo
,
374 INTERFACE_TYPE InterfaceType
,
375 ULONG CommandPortBase
,
376 ULONG ControlPortBase
,
377 ULONG BusMasterPortBase
,
378 ULONG InterruptVector
)
380 SCSI_PHYSICAL_ADDRESS IoAddress
;
383 IoAddress
= ScsiPortConvertUlongToPhysicalAddress(CommandPortBase
);
384 IoBase
= ScsiPortGetDeviceBase((PVOID
)DevExt
,
386 ConfigInfo
->SystemIoBusNumber
,
394 DevExt
->CommandPortBase
= (ULONG
)IoBase
;
395 ConfigInfo
->AccessRanges
[0].RangeStart
= IoAddress
;
396 ConfigInfo
->AccessRanges
[0].RangeLength
= 8;
397 ConfigInfo
->AccessRanges
[0].RangeInMemory
= FALSE
;
401 IoAddress
= ScsiPortConvertUlongToPhysicalAddress(ControlPortBase
+ 2);
402 IoBase
= ScsiPortGetDeviceBase((PVOID
)DevExt
,
404 ConfigInfo
->SystemIoBusNumber
,
410 ScsiPortFreeDeviceBase((PVOID
)DevExt
,
411 (PVOID
)DevExt
->CommandPortBase
);
414 DevExt
->ControlPortBase
= (ULONG
)IoBase
;
415 ConfigInfo
->AccessRanges
[1].RangeStart
= IoAddress
;
416 ConfigInfo
->AccessRanges
[1].RangeLength
= 1;
417 ConfigInfo
->AccessRanges
[1].RangeInMemory
= FALSE
;
419 if (BusMasterPortBase
)
421 IoAddress
= ScsiPortConvertUlongToPhysicalAddress(BusMasterPortBase
);
422 IoBase
= ScsiPortGetDeviceBase((PVOID
)DevExt
,
424 ConfigInfo
->SystemIoBusNumber
,
430 ScsiPortFreeDeviceBase((PVOID
)DevExt
, (PVOID
)DevExt
->CommandPortBase
);
431 ScsiPortFreeDeviceBase((PVOID
)DevExt
, (PVOID
)DevExt
->ControlPortBase
);
434 ConfigInfo
->AccessRanges
[2].RangeStart
= IoAddress
;
435 ConfigInfo
->AccessRanges
[2].RangeLength
= 8;
436 ConfigInfo
->AccessRanges
[2].RangeInMemory
= FALSE
;
438 ConfigInfo
->BusInterruptLevel
= InterruptVector
;
439 ConfigInfo
->BusInterruptVector
= InterruptVector
;
440 ConfigInfo
->InterruptMode
= (InterfaceType
== Isa
) ? Latched
: LevelSensitive
;
442 if ((CommandPortBase
== 0x1F0 || ControlPortBase
== 0x3F4) && !ConfigInfo
->AtdiskPrimaryClaimed
)
444 ConfigInfo
->AtdiskPrimaryClaimed
= TRUE
;
446 if ((CommandPortBase
== 0x170 || ControlPortBase
== 0x374) && !ConfigInfo
->AtdiskSecondaryClaimed
)
448 ConfigInfo
->AtdiskSecondaryClaimed
= TRUE
;
456 AtapiFindCompatiblePciController(PVOID DeviceExtension
,
458 PVOID BusInformation
,
459 PCHAR ArgumentString
,
460 PPORT_CONFIGURATION_INFORMATION ConfigInfo
,
463 PATAPI_MINIPORT_EXTENSION DevExt
= (PATAPI_MINIPORT_EXTENSION
)DeviceExtension
;
464 PCI_SLOT_NUMBER SlotNumber
;
465 PCI_COMMON_CONFIG PciConfig
;
467 ULONG StartDeviceNumber
;
469 ULONG StartFunctionNumber
;
470 ULONG FunctionNumber
;
471 BOOLEAN ChannelFound
;
473 ULONG BusMasterBasePort
= 0;
475 DPRINT("AtapiFindCompatiblePciController() Bus: %lu Slot: %lu\n",
476 ConfigInfo
->SystemIoBusNumber
,
477 ConfigInfo
->SlotNumber
);
481 /* both channels were claimed: exit */
482 if (ConfigInfo
->AtdiskPrimaryClaimed
== TRUE
&&
483 ConfigInfo
->AtdiskSecondaryClaimed
== TRUE
)
484 return(SP_RETURN_NOT_FOUND
);
486 SlotNumber
.u
.AsULONG
= ConfigInfo
->SlotNumber
;
487 StartDeviceNumber
= SlotNumber
.u
.bits
.DeviceNumber
;
488 StartFunctionNumber
= SlotNumber
.u
.bits
.FunctionNumber
;
489 for (DeviceNumber
= StartDeviceNumber
; DeviceNumber
< PCI_MAX_DEVICES
; DeviceNumber
++)
491 SlotNumber
.u
.bits
.DeviceNumber
= DeviceNumber
;
492 for (FunctionNumber
= StartFunctionNumber
; FunctionNumber
< PCI_MAX_FUNCTION
; FunctionNumber
++)
494 SlotNumber
.u
.bits
.FunctionNumber
= FunctionNumber
;
495 ChannelFound
= FALSE
;
498 DataSize
= ScsiPortGetBusData(DeviceExtension
,
500 ConfigInfo
->SystemIoBusNumber
,
501 SlotNumber
.u
.AsULONG
,
503 PCI_COMMON_HDR_LENGTH
);
504 if (DataSize
!= PCI_COMMON_HDR_LENGTH
)
506 if (FunctionNumber
== 0)
516 DPRINT("%x %x\n", PciConfig
.BaseClass
, PciConfig
.SubClass
);
517 if (PciConfig
.BaseClass
== 0x01 &&
518 PciConfig
.SubClass
== 0x01) // &&
519 // (PciConfig.ProgIf & 0x05) == 0)
521 /* both channels are in compatibility mode */
522 DPRINT("Bus %1lu Device %2lu Func %1lu VenID 0x%04hx DevID 0x%04hx\n",
523 ConfigInfo
->SystemIoBusNumber
,
524 SlotNumber
.u
.bits
.DeviceNumber
,
525 SlotNumber
.u
.bits
.FunctionNumber
,
528 DPRINT("ProgIF 0x%02hx\n", PciConfig
.ProgIf
);
530 DPRINT("Found IDE controller in compatibility mode!\n");
532 ConfigInfo
->NumberOfBuses
= 1;
533 ConfigInfo
->MaximumNumberOfTargets
= 2;
534 ConfigInfo
->MaximumTransferLength
= 0x10000; /* max 64Kbyte */
536 if (PciConfig
.ProgIf
& 0x80)
538 DPRINT("Found IDE Bus Master controller!\n");
539 if (PciConfig
.u
.type0
.BaseAddresses
[4] & PCI_ADDRESS_IO_SPACE
)
541 BusMasterBasePort
= PciConfig
.u
.type0
.BaseAddresses
[4] & PCI_ADDRESS_IO_ADDRESS_MASK
;
542 DPRINT(" IDE Bus Master Registers at IO %lx\n", BusMasterBasePort
);
545 if (ConfigInfo
->AtdiskPrimaryClaimed
== FALSE
)
547 /* Both channels unclaimed: Claim primary channel */
548 DPRINT("Primary channel!\n");
549 ChannelFound
= AtapiClaimHwResources(DevExt
,
558 else if (ConfigInfo
->AtdiskSecondaryClaimed
== FALSE
)
560 /* Primary channel already claimed: claim secondary channel */
561 DPRINT("Secondary channel!\n");
563 ChannelFound
= AtapiClaimHwResources(DevExt
,
568 BusMasterBasePort
? BusMasterBasePort
+ 8 : 0,
572 /* Find attached devices */
575 DeviceFound
= AtapiFindDevices(DevExt
, ConfigInfo
);
576 ConfigInfo
->SlotNumber
= SlotNumber
.u
.AsULONG
;
577 DPRINT("AtapiFindCompatiblePciController() returns: SP_RETURN_FOUND\n");
578 return(SP_RETURN_FOUND
);
581 if (FunctionNumber
== 0 && !(PciConfig
.HeaderType
& PCI_MULTIFUNCTION
))
586 StartFunctionNumber
= 0;
588 DPRINT("AtapiFindCompatiblePciController() returns: SP_RETURN_NOT_FOUND\n");
590 return(SP_RETURN_NOT_FOUND
);
597 AtapiFindIsaBusController(PVOID DeviceExtension
,
599 PVOID BusInformation
,
600 PCHAR ArgumentString
,
601 PPORT_CONFIGURATION_INFORMATION ConfigInfo
,
604 PATAPI_MINIPORT_EXTENSION DevExt
= (PATAPI_MINIPORT_EXTENSION
)DeviceExtension
;
605 BOOLEAN ChannelFound
= FALSE
;
606 BOOLEAN DeviceFound
= FALSE
;
608 DPRINT("AtapiFindIsaBusController() called!\n");
612 ConfigInfo
->NumberOfBuses
= 1;
613 ConfigInfo
->MaximumNumberOfTargets
= 2;
614 ConfigInfo
->MaximumTransferLength
= 0x10000; /* max 64Kbyte */
616 if (ConfigInfo
->AtdiskPrimaryClaimed
== FALSE
)
618 /* Both channels unclaimed: Claim primary channel */
619 DPRINT("Primary channel!\n");
621 ChannelFound
= AtapiClaimHwResources(DevExt
,
630 else if (ConfigInfo
->AtdiskSecondaryClaimed
== FALSE
)
632 /* Primary channel already claimed: claim secondary channel */
633 DPRINT("Secondary channel!\n");
635 ChannelFound
= AtapiClaimHwResources(DevExt
,
646 DPRINT("AtapiFindIsaBusController() both channels claimed. Returns: SP_RETURN_NOT_FOUND\n");
648 return(SP_RETURN_NOT_FOUND
);
651 /* Find attached devices */
654 DeviceFound
= AtapiFindDevices(DevExt
,
656 DPRINT("AtapiFindIsaBusController() returns: SP_RETURN_FOUND\n");
657 return(SP_RETURN_FOUND
);
660 return SP_RETURN_NOT_FOUND
;
665 #ifdef ENABLE_NATIVE_PCI
667 AtapiFindNativePciController(PVOID DeviceExtension
,
669 PVOID BusInformation
,
670 PCHAR ArgumentString
,
671 PPORT_CONFIGURATION_INFORMATION ConfigInfo
,
674 PATAPI_MINIPORT_EXTENSION DevExt
= (PATAPI_MINIPORT_EXTENSION
)DeviceExtension
;
675 PCI_COMMON_CONFIG PciConfig
;
676 PCI_SLOT_NUMBER SlotNumber
;
679 ULONG StartDeviceNumber
;
680 ULONG FunctionNumber
;
681 ULONG StartFunctionNumber
;
682 ULONG BusMasterBasePort
;
684 BOOLEAN ChannelFound
;
686 DPRINT("AtapiFindNativePciController() called!\n");
688 SlotNumber
.u
.AsULONG
= ConfigInfo
->SlotNumber
;
689 StartDeviceNumber
= SlotNumber
.u
.bits
.DeviceNumber
;
690 StartFunctionNumber
= SlotNumber
.u
.bits
.FunctionNumber
;
691 for (DeviceNumber
= StartDeviceNumber
; DeviceNumber
< PCI_MAX_DEVICES
; DeviceNumber
++)
693 SlotNumber
.u
.bits
.DeviceNumber
= DeviceNumber
;
694 for (FunctionNumber
= StartFunctionNumber
; FunctionNumber
< PCI_MAX_FUNCTION
; FunctionNumber
++)
696 SlotNumber
.u
.bits
.FunctionNumber
= FunctionNumber
;
697 DataSize
= ScsiPortGetBusData(DeviceExtension
,
699 ConfigInfo
->SystemIoBusNumber
,
700 SlotNumber
.u
.AsULONG
,
702 PCI_COMMON_HDR_LENGTH
);
703 if (DataSize
!= PCI_COMMON_HDR_LENGTH
)
707 for (Count
= 0; Count
< sizeof(PciNativeController
)/sizeof(PCI_NATIVE_CONTROLLER
); Count
++)
709 if (PciConfig
.VendorID
== PciNativeController
[Count
].VendorID
&&
710 PciConfig
.DeviceID
== PciNativeController
[Count
].DeviceID
)
715 if (Count
< sizeof(PciNativeController
)/sizeof(PCI_NATIVE_CONTROLLER
))
717 /* We have found a known native pci ide controller */
718 if ((PciConfig
.ProgIf
& 0x80) && (PciConfig
.u
.type0
.BaseAddresses
[4] & PCI_ADDRESS_IO_SPACE
))
720 DPRINT("Found IDE Bus Master controller!\n");
721 BusMasterBasePort
= PciConfig
.u
.type0
.BaseAddresses
[4] & PCI_ADDRESS_IO_ADDRESS_MASK
;
722 DPRINT(" IDE Bus Master Registers at IO %lx\n", BusMasterBasePort
);
726 BusMasterBasePort
= 0;
729 DPRINT("VendorID: %04x, DeviceID: %04x\n", PciConfig
.VendorID
, PciConfig
.DeviceID
);
730 ConfigInfo
->NumberOfBuses
= 1;
731 ConfigInfo
->MaximumNumberOfTargets
= 2;
732 ConfigInfo
->MaximumTransferLength
= 0x10000; /* max 64Kbyte */
735 We must not store and use the last tested slot number. If there is a recall
736 to the some device and we will claim the primary channel again than the call
737 to ScsiPortGetDeviceBase in AtapiClaimHwResource will fail and we can try to
738 claim the secondary channel.
740 ChannelFound
= FALSE
;
741 if (LastSlotNumber
.u
.AsULONG
!= SlotNumber
.u
.AsULONG
)
743 /* try to claim primary channel */
744 if ((PciConfig
.u
.type0
.BaseAddresses
[0] & PCI_ADDRESS_IO_SPACE
) &&
745 (PciConfig
.u
.type0
.BaseAddresses
[1] & PCI_ADDRESS_IO_SPACE
))
747 /* primary channel is enabled */
748 ChannelFound
= AtapiClaimHwResources(DevExt
,
751 PciConfig
.u
.type0
.BaseAddresses
[0] & PCI_ADDRESS_IO_ADDRESS_MASK
,
752 PciConfig
.u
.type0
.BaseAddresses
[1] & PCI_ADDRESS_IO_ADDRESS_MASK
,
754 PciConfig
.u
.type0
.InterruptLine
);
757 AtapiFindDevices(DevExt
, ConfigInfo
);
759 ConfigInfo
->SlotNumber
= LastSlotNumber
.u
.AsULONG
= SlotNumber
.u
.AsULONG
;
760 return SP_RETURN_FOUND
;
766 /* try to claim secondary channel */
767 if ((PciConfig
.u
.type0
.BaseAddresses
[2] & PCI_ADDRESS_IO_SPACE
) &&
768 (PciConfig
.u
.type0
.BaseAddresses
[3] & PCI_ADDRESS_IO_SPACE
))
770 /* secondary channel is enabled */
771 ChannelFound
= AtapiClaimHwResources(DevExt
,
774 PciConfig
.u
.type0
.BaseAddresses
[2] & PCI_ADDRESS_IO_ADDRESS_MASK
,
775 PciConfig
.u
.type0
.BaseAddresses
[3] & PCI_ADDRESS_IO_ADDRESS_MASK
,
776 BusMasterBasePort
? BusMasterBasePort
+ 8 : 0,
777 PciConfig
.u
.type0
.InterruptLine
);
780 AtapiFindDevices(DevExt
, ConfigInfo
);
782 LastSlotNumber
.u
.AsULONG
= 0xFFFFFFFF;
783 return SP_RETURN_FOUND
;
789 StartFunctionNumber
= 0;
792 LastSlotNumber
.u
.AsULONG
= 0xFFFFFFFF;
793 DPRINT("AtapiFindNativePciController() done!\n");
795 return(SP_RETURN_NOT_FOUND
);
800 static BOOLEAN STDCALL
801 AtapiInitialize(IN PVOID DeviceExtension
)
807 static BOOLEAN STDCALL
808 AtapiResetBus(IN PVOID DeviceExtension
,
815 static BOOLEAN STDCALL
816 AtapiStartIo(IN PVOID DeviceExtension
,
817 IN PSCSI_REQUEST_BLOCK Srb
)
819 PATAPI_MINIPORT_EXTENSION DevExt
;
822 DPRINT("AtapiStartIo() called\n");
824 DevExt
= (PATAPI_MINIPORT_EXTENSION
)DeviceExtension
;
826 switch (Srb
->Function
)
828 case SRB_FUNCTION_EXECUTE_SCSI
:
829 DevExt
->CurrentSrb
= Srb
;
830 if (DevExt
->DeviceAtapi
[Srb
->TargetId
] == TRUE
)
832 Result
= AtapiSendAtapiCommand(DevExt
,
837 Result
= AtapiSendIdeCommand(DevExt
,
844 Srb
->SrbStatus
= Result
;
847 if (Result
!= SRB_STATUS_PENDING
)
849 DevExt
->CurrentSrb
= NULL
;
850 Srb
->SrbStatus
= (UCHAR
)Result
;
852 ScsiPortNotification(RequestComplete
,
855 ScsiPortNotification(NextRequest
,
861 DPRINT("SrbStatus = SRB_STATUS_PENDING\n");
864 DPRINT("AtapiStartIo() done\n");
870 static BOOLEAN STDCALL
871 AtapiInterrupt(IN PVOID DeviceExtension
)
873 PATAPI_MINIPORT_EXTENSION DevExt
;
874 PSCSI_REQUEST_BLOCK Srb
;
875 ULONG CommandPortBase
;
876 ULONG ControlPortBase
;
882 PUCHAR TargetAddress
;
885 DPRINT("AtapiInterrupt() called!\n");
887 DevExt
= (PATAPI_MINIPORT_EXTENSION
)DeviceExtension
;
889 CommandPortBase
= DevExt
->CommandPortBase
;
890 ControlPortBase
= DevExt
->ControlPortBase
;
892 if (DevExt
->ExpectingInterrupt
== FALSE
)
894 DeviceStatus
= IDEReadStatus(CommandPortBase
);
895 DPRINT("AtapiInterrupt(): Unexpected interrupt (port=%x)\n", CommandPortBase
);
899 /* check if it was our irq */
900 if ((DeviceStatus
= IDEReadAltStatus(ControlPortBase
)) & IDE_SR_BUSY
)
902 ScsiPortStallExecution(1);
903 if ((DeviceStatus
= IDEReadAltStatus(ControlPortBase
) & IDE_SR_BUSY
))
905 DPRINT("AtapiInterrupt(): Unexpected interrupt (port=%x)\n", CommandPortBase
);
910 Srb
= DevExt
->CurrentSrb
;
911 DPRINT("Srb: %p\n", Srb
);
913 DPRINT("CommandPortBase: %lx ControlPortBase: %lx\n", CommandPortBase
, ControlPortBase
);
915 IsAtapi
= DevExt
->DeviceAtapi
[Srb
->TargetId
];
916 DPRINT("IsAtapi == %s\n", (IsAtapi
) ? "TRUE" : "FALSE");
920 DeviceStatus
= IDEReadStatus(CommandPortBase
);
921 DPRINT("DeviceStatus: %x\n", DeviceStatus
);
923 if ((DeviceStatus
& IDE_SR_ERR
) &&
924 (Srb
->Cdb
[0] != SCSIOP_REQUEST_SENSE
))
926 /* Report error condition */
927 Srb
->SrbStatus
= SRB_STATUS_ERROR
;
932 if (Srb
->SrbFlags
& SRB_FLAGS_DATA_IN
)
934 DPRINT("Read data\n");
936 /* Update controller/device state variables */
937 TargetAddress
= DevExt
->DataBuffer
;
941 TransferSize
= IDEReadCylinderLow(CommandPortBase
);
942 TransferSize
+= IDEReadCylinderHigh(CommandPortBase
) << 8;
946 TransferSize
= DevExt
->TransferSize
[Srb
->TargetId
];
949 DPRINT("TransferLength: %lu\n", Srb
->DataTransferLength
);
950 DPRINT("TransferSize: %lu\n", TransferSize
);
952 if (DevExt
->DataTransferLength
<= TransferSize
)
956 TransferSize
= DevExt
->DataTransferLength
;
958 DevExt
->DataTransferLength
= 0;
963 DevExt
->DataTransferLength
-= TransferSize
;
966 DevExt
->DataBuffer
+= TransferSize
;
967 DPRINT("IsLastBlock == %s\n", (IsLastBlock
) ? "TRUE" : "FALSE");
969 /* Wait for DRQ assertion */
970 for (Retries
= 0; Retries
< IDE_MAX_DRQ_RETRIES
&&
971 !(IDEReadStatus(CommandPortBase
) & IDE_SR_DRQ
);
974 KeStallExecutionProcessor(10);
977 /* Copy the block of data */
978 if (DevExt
->DWordIo
[Srb
->TargetId
])
980 IDEReadBlock32(CommandPortBase
,
986 IDEReadBlock(CommandPortBase
,
993 for (Retries
= 0; Retries
< IDE_MAX_BUSY_RETRIES
&&
994 (IDEReadStatus(CommandPortBase
) & IDE_SR_BUSY
);
997 KeStallExecutionProcessor(10);
1000 /* Check for data overrun */
1001 while (IDEReadStatus(CommandPortBase
) & IDE_SR_DRQ
)
1003 DPRINT1("AtapiInterrupt(): reading overrun data!\n");
1004 IDEReadWord(CommandPortBase
);
1008 Srb
->SrbStatus
= SRB_STATUS_SUCCESS
;
1010 else if (Srb
->SrbFlags
& SRB_FLAGS_DATA_OUT
)
1012 DPRINT("Write data\n");
1014 if (DevExt
->DataTransferLength
== 0)
1016 /* Check for data overrun */
1017 if (DeviceStatus
& IDE_SR_DRQ
)
1019 /* FIXME: Handle error! */
1020 /* This can occure if the irq is shared with an other and if the
1021 ide controller has a write buffer. We have write the last sectors
1022 and the other device has a irq before ours. The isr is called but
1023 we haven't a interrupt. The controller writes the sector buffer
1024 and the status register shows DRQ because the write is not ended. */
1025 DPRINT("AtapiInterrupt(): data overrun error!\n");
1031 /* Update DevExt data */
1032 TransferSize
= DevExt
->TransferSize
[Srb
->TargetId
];
1033 if (DevExt
->DataTransferLength
< TransferSize
)
1035 TransferSize
= DevExt
->DataTransferLength
;
1038 TargetAddress
= DevExt
->DataBuffer
;
1039 DevExt
->DataBuffer
+= TransferSize
;
1040 DevExt
->DataTransferLength
-= TransferSize
;
1042 /* Write the sector */
1043 if (DevExt
->DWordIo
[Srb
->TargetId
])
1045 IDEWriteBlock32(CommandPortBase
,
1051 IDEWriteBlock(CommandPortBase
,
1057 Srb
->SrbStatus
= SRB_STATUS_SUCCESS
;
1061 DPRINT1("Unspecified transfer direction!\n");
1062 Srb
->SrbStatus
= SRB_STATUS_SUCCESS
; // SRB_STATUS_ERROR;
1068 if (Srb
->SrbStatus
== SRB_STATUS_ERROR
)
1070 Srb
->SrbStatus
= AtapiErrorToScsi(DeviceExtension
,
1075 /* complete this packet */
1078 DevExt
->ExpectingInterrupt
= FALSE
;
1080 ScsiPortNotification(RequestComplete
,
1084 ScsiPortNotification(NextRequest
,
1089 DPRINT("AtapiInterrupt() done!\n");
1094 // ---------------------------------------------------- Discardable statics
1097 /**********************************************************************
1102 * Searches for devices on the given port.
1109 * Port device specific information.
1112 * Port configuration information.
1115 * TRUE: At least one device is attached to the port.
1116 * FALSE: No device is attached to the port.
1120 AtapiFindDevices(PATAPI_MINIPORT_EXTENSION DeviceExtension
,
1121 PPORT_CONFIGURATION_INFORMATION ConfigInfo
)
1123 BOOLEAN DeviceFound
= FALSE
;
1124 ULONG CommandPortBase
;
1125 ULONG ControlPortBase
;
1130 DPRINT("AtapiFindDevices() called\n");
1132 CommandPortBase
= ScsiPortConvertPhysicalAddressToUlong(ConfigInfo
->AccessRanges
[0].RangeStart
);
1133 DPRINT(" CommandPortBase: %x\n", CommandPortBase
);
1135 ControlPortBase
= ScsiPortConvertPhysicalAddressToUlong(ConfigInfo
->AccessRanges
[1].RangeStart
);
1136 DPRINT(" ControlPortBase: %x\n", ControlPortBase
);
1138 for (UnitNumber
= 0; UnitNumber
< 2; UnitNumber
++)
1141 IDEWriteDriveHead(CommandPortBase
,
1142 IDE_DH_FIXED
| (UnitNumber
? IDE_DH_DRV1
: 0));
1143 ScsiPortStallExecution(500);
1145 /* Disable interrupts */
1146 IDEWriteDriveControl(ControlPortBase
,
1148 ScsiPortStallExecution(500);
1150 /* Check if a device is attached to the interface */
1151 IDEWriteCylinderHigh(CommandPortBase
, 0xaa);
1152 IDEWriteCylinderLow(CommandPortBase
, 0x55);
1154 High
= IDEReadCylinderHigh(CommandPortBase
);
1155 Low
= IDEReadCylinderLow(CommandPortBase
);
1157 IDEWriteCylinderHigh(CommandPortBase
, 0);
1158 IDEWriteCylinderLow(CommandPortBase
, 0);
1160 if (Low
!= 0x55 || High
!= 0xaa)
1162 DPRINT("No Drive found. UnitNumber %d CommandPortBase %x\n", UnitNumber
, CommandPortBase
);
1166 IDEWriteCommand(CommandPortBase
, IDE_CMD_RESET
);
1168 for (Retries
= 0; Retries
< 20000; Retries
++)
1170 if (!(IDEReadStatus(CommandPortBase
) & IDE_SR_BUSY
))
1174 ScsiPortStallExecution(150);
1176 if (Retries
>= 20000)
1178 DPRINT("Timeout on drive %lu\n", UnitNumber
);
1179 DeviceExtension
->DevicePresent
[UnitNumber
] = FALSE
;
1183 High
= IDEReadCylinderHigh(CommandPortBase
);
1184 Low
= IDEReadCylinderLow(CommandPortBase
);
1186 DPRINT(" Check drive %lu: High 0x%x Low 0x%x\n",
1191 if (High
== 0xEB && Low
== 0x14)
1193 if (AtapiIdentifyDevice(CommandPortBase
,
1197 &DeviceExtension
->DeviceParams
[UnitNumber
]))
1199 DPRINT(" ATAPI drive found!\n");
1200 DeviceExtension
->DevicePresent
[UnitNumber
] = TRUE
;
1201 DeviceExtension
->DeviceAtapi
[UnitNumber
] = TRUE
;
1202 DeviceExtension
->TransferSize
[UnitNumber
] = DeviceExtension
->DeviceParams
[UnitNumber
].BytesPerSector
;
1203 DeviceExtension
->MultiSectorCommand
[UnitNumber
] = FALSE
;
1204 DeviceExtension
->DWordIo
[UnitNumber
] = FALSE
;
1209 DPRINT(" No ATAPI drive found!\n");
1214 if (AtapiIdentifyDevice(CommandPortBase
,
1218 &DeviceExtension
->DeviceParams
[UnitNumber
]))
1220 DPRINT(" IDE drive found!\n");
1221 DeviceExtension
->DevicePresent
[UnitNumber
] = TRUE
;
1222 DeviceExtension
->DeviceAtapi
[UnitNumber
] = FALSE
;
1223 DeviceExtension
->TransferSize
[UnitNumber
] = DeviceExtension
->DeviceParams
[UnitNumber
].BytesPerSector
;
1224 if ((DeviceExtension
->DeviceParams
[UnitNumber
].RWMultImplemented
& 0x8000) &&
1225 (DeviceExtension
->DeviceParams
[UnitNumber
].RWMultImplemented
& 0xff) &&
1226 (DeviceExtension
->DeviceParams
[UnitNumber
].RWMultCurrent
& 0x100) &&
1227 (DeviceExtension
->DeviceParams
[UnitNumber
].RWMultCurrent
& 0xff))
1229 DeviceExtension
->TransferSize
[UnitNumber
] *= (DeviceExtension
->DeviceParams
[UnitNumber
].RWMultCurrent
& 0xff);
1230 DeviceExtension
->MultiSectorCommand
[UnitNumber
] = TRUE
;
1234 DeviceExtension
->MultiSectorCommand
[UnitNumber
] = FALSE
;
1236 DeviceExtension
->DWordIo
[UnitNumber
] = DeviceExtension
->DeviceParams
[UnitNumber
].DWordIo
? TRUE
: FALSE
;
1241 DPRINT(" No IDE drive found!\n");
1246 /* Reset pending interrupts */
1247 IDEReadStatus(CommandPortBase
);
1248 /* Reenable interrupts */
1249 IDEWriteDriveControl(ControlPortBase
, 0);
1250 ScsiPortStallExecution(500);
1251 /* Return with drive 0 selected */
1252 IDEWriteDriveHead(CommandPortBase
, IDE_DH_FIXED
);
1253 ScsiPortStallExecution(500);
1255 DPRINT("AtapiFindDrives() done (DeviceFound %s)\n", (DeviceFound
) ? "TRUE" : "FALSE");
1257 return(DeviceFound
);
1261 // AtapiResetController
1264 // Reset the controller and report completion status
1270 // IN WORD CommandPort The address of the command port
1271 // IN WORD ControlPort The address of the control port
1277 AtapiResetController(IN ULONG CommandPort
,
1278 IN ULONG ControlPort
)
1282 /* Assert drive reset line */
1283 IDEWriteDriveControl(ControlPort
, IDE_DC_SRST
);
1285 /* Wait for min. 25 microseconds */
1286 ScsiPortStallExecution(IDE_RESET_PULSE_LENGTH
);
1288 /* Negate drive reset line */
1289 IDEWriteDriveControl(ControlPort
, 0);
1291 /* Wait for BUSY negation */
1292 for (Retries
= 0; Retries
< IDE_RESET_BUSY_TIMEOUT
* 1000; Retries
++)
1294 if (!(IDEReadStatus(CommandPort
) & IDE_SR_BUSY
))
1298 ScsiPortStallExecution(10);
1301 if (Retries
>= IDE_RESET_BUSY_TIMEOUT
* 1000)
1306 // return TRUE if controller came back to life. and
1307 // the registers are initialized correctly
1308 return(IDEReadError(CommandPort
) == 1);
1312 * AtapiIdentifyDevice
1315 * Get the identification block from the drive
1322 * Address of the command port
1324 * Address of the control port
1326 * The drive index (0,1)
1328 * Send an ATA(FALSE) or an ATAPI(TRUE) identify comand
1330 * Address to write drive ident block
1333 * TRUE: The drive identification block was retrieved successfully
1334 * FALSE: an error ocurred
1338 AtapiIdentifyDevice(IN ULONG CommandPort
,
1339 IN ULONG ControlPort
,
1342 OUT PIDE_DRIVE_IDENTIFY DrvParms
)
1346 /* Get the Drive Identify block from drive or die */
1347 if (AtapiPolledRead(CommandPort
,
1354 (DriveNum
? IDE_DH_DRV1
: 0),
1355 (Atapi
? IDE_CMD_IDENT_ATAPI_DRV
: IDE_CMD_IDENT_ATA_DRV
),
1356 (BYTE
*)DrvParms
) != 0)
1358 DPRINT("IDEPolledRead() failed\n");
1362 /* Report on drive parameters if debug mode */
1363 IDESwapBytePairs(DrvParms
->SerialNumber
, 20);
1364 IDESwapBytePairs(DrvParms
->FirmwareRev
, 8);
1365 IDESwapBytePairs(DrvParms
->ModelNumber
, 40);
1366 DPRINT("Config:%04x Cyls:%5d Heads:%2d Sectors/Track:%3d Gaps:%02d %02d\n",
1367 DrvParms
->ConfigBits
,
1368 DrvParms
->LogicalCyls
,
1369 DrvParms
->LogicalHeads
,
1370 DrvParms
->SectorsPerTrack
,
1371 DrvParms
->InterSectorGap
,
1372 DrvParms
->InterSectorGapSize
);
1373 DPRINT("Bytes/PLO:%3d Vendor Cnt:%2d Serial number:[%.20s]\n",
1374 DrvParms
->BytesInPLO
,
1375 DrvParms
->VendorUniqueCnt
,
1376 DrvParms
->SerialNumber
);
1377 DPRINT("Cntlr type:%2d BufSiz:%5d ECC bytes:%3d Firmware Rev:[%.8s]\n",
1378 DrvParms
->ControllerType
,
1379 DrvParms
->BufferSize
* IDE_SECTOR_BUF_SZ
,
1380 DrvParms
->ECCByteCnt
,
1381 DrvParms
->FirmwareRev
);
1382 DPRINT("Model:[%.40s]\n", DrvParms
->ModelNumber
);
1383 DPRINT("RWMultMax?:%04x RWMult?:%02x LBA:%d DMA:%d MinPIO:%d ns MinDMA:%d ns\n",
1384 (DrvParms
->RWMultImplemented
),
1385 (DrvParms
->RWMultCurrent
) & 0xff,
1386 (DrvParms
->Capabilities
& IDE_DRID_LBA_SUPPORTED
) ? 1 : 0,
1387 (DrvParms
->Capabilities
& IDE_DRID_DMA_SUPPORTED
) ? 1 : 0,
1388 DrvParms
->MinPIOTransTime
,
1389 DrvParms
->MinDMATransTime
);
1390 DPRINT("TM:Cyls:%d Heads:%d Sectors/Trk:%d Capacity:%ld\n",
1391 DrvParms
->TMCylinders
,
1393 DrvParms
->TMSectorsPerTrk
,
1394 (ULONG
)(DrvParms
->TMCapacityLo
+ (DrvParms
->TMCapacityHi
<< 16)));
1395 DPRINT("TM:SectorCount: 0x%04x%04x = %lu\n",
1396 DrvParms
->TMSectorCountHi
,
1397 DrvParms
->TMSectorCountLo
,
1398 (ULONG
)((DrvParms
->TMSectorCountHi
<< 16) + DrvParms
->TMSectorCountLo
));
1400 if (! Atapi
&& 0 != (DrvParms
->Capabilities
& IDE_DRID_LBA_SUPPORTED
))
1402 /* LBA ATA drives always have a sector size of 512 */
1403 DrvParms
->BytesPerSector
= 512;
1407 DPRINT("BytesPerSector %d\n", DrvParms
->BytesPerSector
);
1408 if (DrvParms
->BytesPerSector
== 0)
1410 DrvParms
->BytesPerSector
= 512;
1414 for (i
= 15; i
>= 0; i
--)
1416 if (DrvParms
->BytesPerSector
& (1 << i
))
1418 DrvParms
->BytesPerSector
= 1 << i
;
1424 DPRINT("BytesPerSector %d\n", DrvParms
->BytesPerSector
);
1433 // Read a sector of data from the drive in a polled fashion.
1439 // IN WORD Address Address of command port for drive
1440 // IN BYTE PreComp Value to write to precomp register
1441 // IN BYTE SectorCnt Value to write to sectorCnt register
1442 // IN BYTE SectorNum Value to write to sectorNum register
1443 // IN BYTE CylinderLow Value to write to CylinderLow register
1444 // IN BYTE CylinderHigh Value to write to CylinderHigh register
1445 // IN BYTE DrvHead Value to write to Drive/Head register
1446 // IN BYTE Command Value to write to Command register
1447 // OUT BYTE *Buffer Buffer for output data
1450 // int 0 is success, non 0 is an error code
1454 AtapiPolledRead(IN ULONG CommandPort
,
1455 IN ULONG ControlPort
,
1459 IN BYTE CylinderLow
,
1460 IN BYTE CylinderHigh
,
1465 ULONG SectorCount
= 0;
1467 BOOLEAN Junk
= FALSE
;
1471 /* Wait for BUSY to clear */
1472 for (RetryCount
= 0; RetryCount
< IDE_MAX_BUSY_RETRIES
; RetryCount
++)
1474 Status
= IDEReadStatus(CommandPort
);
1475 if (!(Status
& IDE_SR_BUSY
))
1479 ScsiPortStallExecution(10);
1481 DPRINT("status=%02x\n", Status
);
1482 DPRINT("waited %ld usecs for busy to clear\n", RetryCount
* 10);
1483 if (RetryCount
>= IDE_MAX_BUSY_RETRIES
)
1485 DPRINT("Drive is BUSY for too long\n");
1486 return(IDE_ER_ABRT
);
1490 /* Write Drive/Head to select drive */
1491 IDEWriteDriveHead(CommandPort
, IDE_DH_FIXED
| DrvHead
);
1492 ScsiPortStallExecution(500);
1494 /* Disable interrupts */
1495 IDEWriteDriveControl(ControlPort
, IDE_DC_nIEN
);
1496 ScsiPortStallExecution(500);
1499 /* Wait for STATUS.BUSY and STATUS.DRQ to clear */
1500 for (RetryCount
= 0; RetryCount
< IDE_MAX_BUSY_RETRIES
; RetryCount
++)
1502 Status
= IDEReadStatus(CommandPort
);
1503 if (!(Status
& IDE_SR_BUSY
) && !(Status
& IDE_SR_DRQ
))
1507 ScsiPortStallExecution(10);
1509 if (RetryCount
>= IDE_MAX_BUSY_RETRIES
)
1515 /* Issue command to drive */
1516 if (DrvHead
& IDE_DH_LBA
)
1518 DPRINT("READ:DRV=%d:LBA=1:BLK=%08d:SC=%02x:CM=%02x\n",
1519 DrvHead
& IDE_DH_DRV1
? 1 : 0,
1520 ((DrvHead
& 0x0f) << 24) + (CylinderHigh
<< 16) + (CylinderLow
<< 8) + SectorNum
,
1526 DPRINT("READ:DRV=%d:LBA=0:CH=%02x:CL=%02x:HD=%01x:SN=%02x:SC=%02x:CM=%02x\n",
1527 DrvHead
& IDE_DH_DRV1
? 1 : 0,
1536 /* Setup command parameters */
1537 IDEWritePrecomp(CommandPort
, PreComp
);
1538 IDEWriteSectorCount(CommandPort
, SectorCnt
);
1539 IDEWriteSectorNum(CommandPort
, SectorNum
);
1540 IDEWriteCylinderHigh(CommandPort
, CylinderHigh
);
1541 IDEWriteCylinderLow(CommandPort
, CylinderLow
);
1542 IDEWriteDriveHead(CommandPort
, IDE_DH_FIXED
| DrvHead
);
1544 /* Issue the command */
1545 IDEWriteCommand(CommandPort
, Command
);
1546 ScsiPortStallExecution(50);
1548 /* wait for DRQ or error */
1549 for (RetryCount
= 0; RetryCount
< IDE_MAX_POLL_RETRIES
; RetryCount
++)
1551 Status
= IDEReadStatus(CommandPort
);
1552 if (!(Status
& IDE_SR_BUSY
))
1554 if (Status
& IDE_SR_ERR
)
1556 IDEWriteDriveControl(ControlPort
, 0);
1557 ScsiPortStallExecution(50);
1558 IDEReadStatus(CommandPort
);
1560 return(IDE_ER_ABRT
);
1562 if (Status
& IDE_SR_DRQ
)
1568 IDEWriteDriveControl(ControlPort
, 0);
1569 ScsiPortStallExecution(50);
1570 IDEReadStatus(CommandPort
);
1572 return(IDE_ER_ABRT
);
1575 ScsiPortStallExecution(10);
1579 if (RetryCount
>= IDE_MAX_POLL_RETRIES
)
1581 IDEWriteDriveControl(ControlPort
, 0);
1582 ScsiPortStallExecution(50);
1583 IDEReadStatus(CommandPort
);
1585 return(IDE_ER_ABRT
);
1590 /* Read data into buffer */
1593 IDEReadBlock(CommandPort
, Buffer
, IDE_SECTOR_BUF_SZ
);
1594 Buffer
+= IDE_SECTOR_BUF_SZ
;
1598 UCHAR JunkBuffer
[IDE_SECTOR_BUF_SZ
];
1599 IDEReadBlock(CommandPort
, JunkBuffer
, IDE_SECTOR_BUF_SZ
);
1603 /* Check for error or more sectors to read */
1604 for (RetryCount
= 0; RetryCount
< IDE_MAX_BUSY_RETRIES
; RetryCount
++)
1606 Status
= IDEReadStatus(CommandPort
);
1607 if (!(Status
& IDE_SR_BUSY
))
1609 if (Status
& IDE_SR_ERR
)
1611 IDEWriteDriveControl(ControlPort
, 0);
1612 ScsiPortStallExecution(50);
1613 IDEReadStatus(CommandPort
);
1615 return(IDE_ER_ABRT
);
1617 if (Status
& IDE_SR_DRQ
)
1619 if (SectorCount
>= SectorCnt
)
1621 DPRINT("Buffer size exceeded!\n");
1628 if (SectorCount
> SectorCnt
)
1630 DPRINT("Read %lu sectors of junk!\n",
1631 SectorCount
- SectorCnt
);
1633 IDEWriteDriveControl(ControlPort
, 0);
1634 ScsiPortStallExecution(50);
1635 IDEReadStatus(CommandPort
);
1645 // ------------------------------------------- Nondiscardable statics
1648 AtapiSendAtapiCommand(IN PATAPI_MINIPORT_EXTENSION DeviceExtension
,
1649 IN PSCSI_REQUEST_BLOCK Srb
)
1651 UCHAR ByteCountHigh
;
1657 DPRINT("AtapiSendAtapiCommand() called!\n");
1659 if (Srb
->PathId
!= 0)
1661 Srb
->SrbStatus
= SRB_STATUS_INVALID_PATH_ID
;
1662 return(SRB_STATUS_INVALID_PATH_ID
);
1665 if (Srb
->TargetId
> 1)
1667 Srb
->SrbStatus
= SRB_STATUS_INVALID_TARGET_ID
;
1668 return(SRB_STATUS_INVALID_TARGET_ID
);
1673 Srb
->SrbStatus
= SRB_STATUS_INVALID_LUN
;
1674 return(SRB_STATUS_INVALID_LUN
);
1677 if (DeviceExtension
->DevicePresent
[Srb
->TargetId
] == FALSE
)
1679 Srb
->SrbStatus
= SRB_STATUS_NO_DEVICE
;
1680 return(SRB_STATUS_NO_DEVICE
);
1683 DPRINT("AtapiSendAtapiCommand(): TargetId: %lu\n",
1686 if (Srb
->Cdb
[0] == SCSIOP_INQUIRY
)
1687 return(AtapiInquiry(DeviceExtension
,
1690 /* Set pointer to data buffer. */
1691 DeviceExtension
->DataBuffer
= (PUCHAR
)Srb
->DataBuffer
;
1692 DeviceExtension
->DataTransferLength
= Srb
->DataTransferLength
;
1693 DeviceExtension
->CurrentSrb
= Srb
;
1695 /* Wait for BUSY to clear */
1696 for (Retries
= 0; Retries
< IDE_MAX_BUSY_RETRIES
; Retries
++)
1698 Status
= IDEReadStatus(DeviceExtension
->CommandPortBase
);
1699 if (!(Status
& IDE_SR_BUSY
))
1703 ScsiPortStallExecution(10);
1705 DPRINT("status=%02x\n", Status
);
1706 DPRINT("waited %ld usecs for busy to clear\n", Retries
* 10);
1707 if (Retries
>= IDE_MAX_BUSY_RETRIES
)
1709 DPRINT("Drive is BUSY for too long\n");
1710 return(SRB_STATUS_BUSY
);
1713 /* Select the desired drive */
1714 IDEWriteDriveHead(DeviceExtension
->CommandPortBase
,
1715 IDE_DH_FIXED
| (Srb
->TargetId
? IDE_DH_DRV1
: 0));
1717 /* Wait a little while */
1718 ScsiPortStallExecution(50);
1721 /* Wait for BUSY to clear and DRDY to assert */
1722 for (Retries
= 0; Retries
< IDE_MAX_BUSY_RETRIES
; Retries
++)
1724 Status
= IDEReadStatus(DeviceExtension
->CommandPortBase
);
1725 if (!(Status
& IDE_SR_BUSY
) && (Status
& IDE_SR_DRDY
))
1729 ScsiPortStallExecution(10);
1731 DPRINT("waited %ld usecs for busy to clear after drive select\n", Retries
* 10);
1732 if (Retries
>= IDE_MAX_BUSY_RETRIES
)
1734 DPRINT("Drive is BUSY for too long after drive select\n");
1735 return(SRB_STATUS_BUSY
);
1739 if (DeviceExtension
->DataTransferLength
< 0x10000)
1741 ByteCountLow
= (UCHAR
)(DeviceExtension
->DataTransferLength
& 0xFF);
1742 ByteCountHigh
= (UCHAR
)(DeviceExtension
->DataTransferLength
>> 8);
1746 ByteCountLow
= 0xFF;
1747 ByteCountHigh
= 0xFF;
1750 /* Set feature register */
1751 IDEWritePrecomp(DeviceExtension
->CommandPortBase
, 0);
1753 /* Set command packet length */
1754 IDEWriteCylinderHigh(DeviceExtension
->CommandPortBase
, ByteCountHigh
);
1755 IDEWriteCylinderLow(DeviceExtension
->CommandPortBase
, ByteCountLow
);
1757 /* Issue command to drive */
1758 IDEWriteCommand(DeviceExtension
->CommandPortBase
, 0xA0); /* Packet command */
1760 /* Wait for DRQ to assert */
1761 for (Retries
= 0; Retries
< IDE_MAX_BUSY_RETRIES
; Retries
++)
1763 Status
= IDEReadStatus(DeviceExtension
->CommandPortBase
);
1764 if ((Status
& IDE_SR_DRQ
))
1768 ScsiPortStallExecution(10);
1771 CdbSize
= (DeviceExtension
->DeviceParams
[Srb
->TargetId
].ConfigBits
& 0x3 == 1) ? 16 : 12;
1772 DPRINT("CdbSize: %lu\n", CdbSize
);
1774 /* Write command packet */
1775 IDEWriteBlock(DeviceExtension
->CommandPortBase
,
1779 DeviceExtension
->ExpectingInterrupt
= TRUE
;
1781 DPRINT("AtapiSendAtapiCommand() done\n");
1783 return(SRB_STATUS_PENDING
);
1788 AtapiSendIdeCommand(IN PATAPI_MINIPORT_EXTENSION DeviceExtension
,
1789 IN PSCSI_REQUEST_BLOCK Srb
)
1791 ULONG SrbStatus
= SRB_STATUS_SUCCESS
;
1793 DPRINT("AtapiSendIdeCommand() called!\n");
1795 DPRINT("PathId: %lu TargetId: %lu Lun: %lu\n",
1800 switch (Srb
->Cdb
[0])
1802 case SCSIOP_INQUIRY
:
1803 SrbStatus
= AtapiInquiry(DeviceExtension
,
1807 case SCSIOP_READ_CAPACITY
:
1808 SrbStatus
= AtapiReadCapacity(DeviceExtension
,
1814 SrbStatus
= AtapiReadWrite(DeviceExtension
,
1818 case SCSIOP_MODE_SENSE
:
1819 case SCSIOP_TEST_UNIT_READY
:
1821 case SCSIOP_START_STOP_UNIT
:
1822 case SCSIOP_REQUEST_SENSE
:
1826 DbgPrint("AtapiSendIdeCommand():unknown command %x\n",
1828 SrbStatus
= SRB_STATUS_INVALID_REQUEST
;
1832 DPRINT("AtapiSendIdeCommand() done!\n");
1839 AtapiInquiry(PATAPI_MINIPORT_EXTENSION DeviceExtension
,
1840 PSCSI_REQUEST_BLOCK Srb
)
1842 PIDE_DRIVE_IDENTIFY DeviceParams
;
1843 PINQUIRYDATA InquiryData
;
1846 DPRINT("SCSIOP_INQUIRY: DeviceExtension %p TargetId: %lu\n",
1847 DeviceExtension
, Srb
->TargetId
);
1849 if (Srb
->PathId
!= 0)
1851 Srb
->SrbStatus
= SRB_STATUS_INVALID_PATH_ID
;
1852 return(SRB_STATUS_INVALID_PATH_ID
);
1855 if (Srb
->TargetId
> 1)
1857 Srb
->SrbStatus
= SRB_STATUS_INVALID_TARGET_ID
;
1858 return(SRB_STATUS_INVALID_TARGET_ID
);
1863 Srb
->SrbStatus
= SRB_STATUS_INVALID_LUN
;
1864 return(SRB_STATUS_INVALID_LUN
);
1867 if (DeviceExtension
->DevicePresent
[Srb
->TargetId
] == FALSE
)
1869 Srb
->SrbStatus
= SRB_STATUS_NO_DEVICE
;
1870 return(SRB_STATUS_NO_DEVICE
);
1873 InquiryData
= Srb
->DataBuffer
;
1874 DeviceParams
= &DeviceExtension
->DeviceParams
[Srb
->TargetId
];
1877 for (i
= 0; i
< Srb
->DataTransferLength
; i
++)
1879 ((PUCHAR
)Srb
->DataBuffer
)[i
] = 0;
1882 /* set device class */
1883 if (DeviceExtension
->DeviceAtapi
[Srb
->TargetId
] == FALSE
)
1886 InquiryData
->DeviceType
= DIRECT_ACCESS_DEVICE
;
1890 /* get it from the ATAPI configuration word */
1891 InquiryData
->DeviceType
= (DeviceParams
->ConfigBits
>> 8) & 0x1F;
1892 DPRINT("Device class: %u\n", InquiryData
->DeviceType
);
1895 DPRINT("ConfigBits: 0x%x\n", DeviceParams
->ConfigBits
);
1896 if (DeviceParams
->ConfigBits
& 0x80)
1898 DPRINT("Removable media!\n");
1899 InquiryData
->RemovableMedia
= 1;
1902 for (i
= 0; i
< 20; i
+= 2)
1904 InquiryData
->VendorId
[i
] =
1905 ((PUCHAR
)DeviceParams
->ModelNumber
)[i
];
1906 InquiryData
->VendorId
[i
+1] =
1907 ((PUCHAR
)DeviceParams
->ModelNumber
)[i
+1];
1910 for (i
= 0; i
< 4; i
++)
1912 InquiryData
->ProductId
[12+i
] = ' ';
1915 for (i
= 0; i
< 4; i
+= 2)
1917 InquiryData
->ProductRevisionLevel
[i
] =
1918 ((PUCHAR
)DeviceParams
->FirmwareRev
)[i
];
1919 InquiryData
->ProductRevisionLevel
[i
+1] =
1920 ((PUCHAR
)DeviceParams
->FirmwareRev
)[i
+1];
1923 DPRINT("VendorId: '%.20s'\n", InquiryData
->VendorId
);
1925 Srb
->SrbStatus
= SRB_STATUS_SUCCESS
;
1926 return(SRB_STATUS_SUCCESS
);
1931 AtapiReadCapacity(PATAPI_MINIPORT_EXTENSION DeviceExtension
,
1932 PSCSI_REQUEST_BLOCK Srb
)
1934 PREAD_CAPACITY_DATA CapacityData
;
1935 PIDE_DRIVE_IDENTIFY DeviceParams
;
1938 DPRINT("SCSIOP_READ_CAPACITY: TargetId: %lu\n", Srb
->TargetId
);
1940 if (Srb
->PathId
!= 0)
1942 Srb
->SrbStatus
= SRB_STATUS_INVALID_PATH_ID
;
1943 return(SRB_STATUS_INVALID_PATH_ID
);
1946 if (Srb
->TargetId
> 1)
1948 Srb
->SrbStatus
= SRB_STATUS_INVALID_TARGET_ID
;
1949 return(SRB_STATUS_INVALID_TARGET_ID
);
1954 Srb
->SrbStatus
= SRB_STATUS_INVALID_LUN
;
1955 return(SRB_STATUS_INVALID_LUN
);
1958 if (DeviceExtension
->DevicePresent
[Srb
->TargetId
] == FALSE
)
1960 Srb
->SrbStatus
= SRB_STATUS_NO_DEVICE
;
1961 return(SRB_STATUS_NO_DEVICE
);
1964 CapacityData
= (PREAD_CAPACITY_DATA
)Srb
->DataBuffer
;
1965 DeviceParams
= &DeviceExtension
->DeviceParams
[Srb
->TargetId
];
1967 /* Set sector (block) size to 512 bytes (big-endian). */
1968 CapacityData
->BytesPerBlock
= 0x20000;
1970 /* Calculate last sector (big-endian). */
1971 if (DeviceParams
->Capabilities
& IDE_DRID_LBA_SUPPORTED
)
1973 LastSector
= (ULONG
)((DeviceParams
->TMSectorCountHi
<< 16) +
1974 DeviceParams
->TMSectorCountLo
) - 1;
1978 LastSector
= (ULONG
)(DeviceParams
->LogicalCyls
*
1979 DeviceParams
->LogicalHeads
*
1980 DeviceParams
->SectorsPerTrack
)-1;
1983 CapacityData
->LogicalBlockAddress
= (((PUCHAR
)&LastSector
)[0] << 24) |
1984 (((PUCHAR
)&LastSector
)[1] << 16) |
1985 (((PUCHAR
)&LastSector
)[2] << 8) |
1986 ((PUCHAR
)&LastSector
)[3];
1988 DPRINT("LastCount: %lu (%08lx / %08lx)\n",
1991 CapacityData
->LogicalBlockAddress
);
1993 Srb
->SrbStatus
= SRB_STATUS_SUCCESS
;
1994 return(SRB_STATUS_SUCCESS
);
1999 AtapiReadWrite(PATAPI_MINIPORT_EXTENSION DeviceExtension
,
2000 PSCSI_REQUEST_BLOCK Srb
)
2002 PIDE_DRIVE_IDENTIFY DeviceParams
;
2003 ULONG StartingSector
;
2013 DPRINT("AtapiReadWrite() called!\n");
2015 if (Srb
->PathId
!= 0)
2017 Srb
->SrbStatus
= SRB_STATUS_INVALID_PATH_ID
;
2018 return(SRB_STATUS_INVALID_PATH_ID
);
2021 if (Srb
->TargetId
> 1)
2023 Srb
->SrbStatus
= SRB_STATUS_INVALID_TARGET_ID
;
2024 return(SRB_STATUS_INVALID_TARGET_ID
);
2029 Srb
->SrbStatus
= SRB_STATUS_INVALID_LUN
;
2030 return(SRB_STATUS_INVALID_LUN
);
2033 if (DeviceExtension
->DevicePresent
[Srb
->TargetId
] == FALSE
)
2035 Srb
->SrbStatus
= SRB_STATUS_NO_DEVICE
;
2036 return(SRB_STATUS_NO_DEVICE
);
2039 DPRINT("SCSIOP_WRITE: TargetId: %lu\n",
2042 DeviceParams
= &DeviceExtension
->DeviceParams
[Srb
->TargetId
];
2044 /* Get starting sector number from CDB. */
2045 StartingSector
= ((PCDB
)Srb
->Cdb
)->CDB10
.LogicalBlockByte3
|
2046 ((PCDB
)Srb
->Cdb
)->CDB10
.LogicalBlockByte2
<< 8 |
2047 ((PCDB
)Srb
->Cdb
)->CDB10
.LogicalBlockByte1
<< 16 |
2048 ((PCDB
)Srb
->Cdb
)->CDB10
.LogicalBlockByte0
<< 24;
2050 SectorCount
= (Srb
->DataTransferLength
+ DeviceParams
->BytesPerSector
- 1) /
2051 DeviceParams
->BytesPerSector
;
2053 DPRINT("Starting sector %lu Number of bytes %lu Sectors %lu\n",
2055 Srb
->DataTransferLength
,
2058 if (DeviceParams
->Capabilities
& IDE_DRID_LBA_SUPPORTED
)
2060 SectorNumber
= StartingSector
& 0xff;
2061 CylinderLow
= (StartingSector
>> 8) & 0xff;
2062 CylinderHigh
= (StartingSector
>> 16) & 0xff;
2063 DrvHead
= ((StartingSector
>> 24) & 0x0f) |
2064 (Srb
->TargetId
? IDE_DH_DRV1
: 0) |
2069 SectorNumber
= (StartingSector
% DeviceParams
->SectorsPerTrack
) + 1;
2070 StartingSector
/= DeviceParams
->SectorsPerTrack
;
2071 DrvHead
= (StartingSector
% DeviceParams
->LogicalHeads
) |
2072 (Srb
->TargetId
? IDE_DH_DRV1
: 0);
2073 StartingSector
/= DeviceParams
->LogicalHeads
;
2074 CylinderLow
= StartingSector
& 0xff;
2075 CylinderHigh
= StartingSector
>> 8;
2079 if (Srb
->SrbFlags
& SRB_FLAGS_DATA_IN
)
2081 Command
= DeviceExtension
->MultiSectorCommand
[Srb
->TargetId
] ? IDE_CMD_READ_MULTIPLE
: IDE_CMD_READ
;
2085 Command
= DeviceExtension
->MultiSectorCommand
[Srb
->TargetId
] ? IDE_CMD_WRITE_MULTIPLE
: IDE_CMD_WRITE
;
2088 if (DrvHead
& IDE_DH_LBA
)
2090 DPRINT("%s:BUS=%04x:DRV=%d:LBA=1:BLK=%08d:SC=%02x:CM=%02x\n",
2091 (Srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) ? "READ" : "WRITE",
2092 DeviceExtension
->CommandPortBase
,
2093 DrvHead
& IDE_DH_DRV1
? 1 : 0,
2094 ((DrvHead
& 0x0f) << 24) +
2095 (CylinderHigh
<< 16) + (CylinderLow
<< 8) + SectorNumber
,
2101 DPRINT("%s:BUS=%04x:DRV=%d:LBA=0:CH=%02x:CL=%02x:HD=%01x:SN=%02x:SC=%02x:CM=%02x\n",
2102 (Srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) ? "READ" : "WRITE",
2103 DeviceExtension
->CommandPortBase
,
2104 DrvHead
& IDE_DH_DRV1
? 1 : 0,
2113 /* Set pointer to data buffer. */
2114 DeviceExtension
->DataBuffer
= (PUCHAR
)Srb
->DataBuffer
;
2115 DeviceExtension
->DataTransferLength
= Srb
->DataTransferLength
;
2117 DeviceExtension
->CurrentSrb
= Srb
;
2119 /* wait for BUSY to clear */
2120 for (Retries
= 0; Retries
< IDE_MAX_BUSY_RETRIES
; Retries
++)
2122 Status
= IDEReadStatus(DeviceExtension
->CommandPortBase
);
2123 if (!(Status
& IDE_SR_BUSY
))
2127 ScsiPortStallExecution(10);
2129 DPRINT("status=%02x\n", Status
);
2130 DPRINT("waited %ld usecs for busy to clear\n", Retries
* 10);
2131 if (Retries
>= IDE_MAX_BUSY_RETRIES
)
2133 DPRINT ("Drive is BUSY for too long\n");
2134 return(SRB_STATUS_BUSY
);
2136 if (++ControllerExtension
->Retries
> IDE_MAX_CMD_RETRIES
)
2138 DbgPrint ("Max Retries on Drive reset reached, returning failure\n");
2139 Irp
= ControllerExtension
->CurrentIrp
;
2140 Irp
->IoStatus
.Status
= STATUS_DISK_OPERATION_FAILED
;
2141 Irp
->IoStatus
.Information
= 0;
2147 DPRINT ("Beginning drive reset sequence\n");
2148 IDEBeginControllerReset(ControllerExtension
);
2155 /* Select the desired drive */
2156 IDEWriteDriveHead(DeviceExtension
->CommandPortBase
,
2157 IDE_DH_FIXED
| DrvHead
);
2159 ScsiPortStallExecution(10);
2161 /* wait for BUSY to clear and DRDY to assert */
2162 for (Retries
= 0; Retries
< IDE_MAX_BUSY_RETRIES
; Retries
++)
2164 Status
= IDEReadStatus(DeviceExtension
->CommandPortBase
);
2165 if (!(Status
& IDE_SR_BUSY
) && (Status
& IDE_SR_DRDY
))
2169 ScsiPortStallExecution(10);
2171 DPRINT("waited %ld usecs for busy to clear after drive select\n", Retries
* 10);
2172 if (Retries
>= IDE_MAX_BUSY_RETRIES
)
2174 DPRINT("Drive is BUSY for too long after drive select\n");
2175 return(SRB_STATUS_BUSY
);
2177 if (ControllerExtension
->Retries
++ > IDE_MAX_CMD_RETRIES
)
2179 DbgPrint ("Max Retries on Drive reset reached, returning failure\n");
2180 Irp
= ControllerExtension
->CurrentIrp
;
2181 Irp
->IoStatus
.Status
= STATUS_DISK_OPERATION_FAILED
;
2182 Irp
->IoStatus
.Information
= 0;
2188 DPRINT("Beginning drive reset sequence\n");
2189 IDEBeginControllerReset(ControllerExtension
);
2197 /* Setup command parameters */
2198 IDEWritePrecomp(DeviceExtension
->CommandPortBase
, 0);
2199 IDEWriteSectorCount(DeviceExtension
->CommandPortBase
, SectorCount
);
2200 IDEWriteSectorNum(DeviceExtension
->CommandPortBase
, SectorNumber
);
2201 IDEWriteCylinderHigh(DeviceExtension
->CommandPortBase
, CylinderHigh
);
2202 IDEWriteCylinderLow(DeviceExtension
->CommandPortBase
, CylinderLow
);
2203 IDEWriteDriveHead(DeviceExtension
->CommandPortBase
, IDE_DH_FIXED
| DrvHead
);
2205 /* Issue command to drive */
2206 IDEWriteCommand(DeviceExtension
->CommandPortBase
, Command
);
2208 /* Write data block */
2209 if (Srb
->SrbFlags
& SRB_FLAGS_DATA_OUT
)
2211 PUCHAR TargetAddress
;
2214 /* Wait for controller ready */
2215 for (Retries
= 0; Retries
< IDE_MAX_WRITE_RETRIES
; Retries
++)
2217 BYTE Status
= IDEReadStatus(DeviceExtension
->CommandPortBase
);
2218 if (!(Status
& IDE_SR_BUSY
) || (Status
& IDE_SR_ERR
))
2222 KeStallExecutionProcessor(10);
2224 if (Retries
>= IDE_MAX_WRITE_RETRIES
)
2226 DPRINT1("Drive is BUSY for too long after sending write command\n");
2227 return(SRB_STATUS_BUSY
);
2229 if (DeviceExtension
->Retries
++ > IDE_MAX_CMD_RETRIES
)
2231 Irp
= ControllerExtension
->CurrentIrp
;
2232 Irp
->IoStatus
.Status
= STATUS_DISK_OPERATION_FAILED
;
2233 Irp
->IoStatus
.Information
= 0;
2239 IDEBeginControllerReset(ControllerExtension
);
2246 /* Update DeviceExtension data */
2247 TransferSize
= DeviceExtension
->TransferSize
[Srb
->TargetId
];
2248 if (DeviceExtension
->DataTransferLength
< TransferSize
)
2250 TransferSize
= DeviceExtension
->DataTransferLength
;
2253 TargetAddress
= DeviceExtension
->DataBuffer
;
2254 DeviceExtension
->DataBuffer
+= TransferSize
;
2255 DeviceExtension
->DataTransferLength
-= TransferSize
;
2257 /* Write data block */
2258 if (DeviceExtension
->DWordIo
[Srb
->TargetId
])
2260 IDEWriteBlock32(DeviceExtension
->CommandPortBase
,
2266 IDEWriteBlock(DeviceExtension
->CommandPortBase
,
2271 /* Indicate expecting an interrupt. */
2272 DeviceExtension
->ExpectingInterrupt
= TRUE
;
2274 DPRINT("AtapiReadWrite() done!\n");
2276 /* Wait for interrupt. */
2277 return(SRB_STATUS_PENDING
);
2282 AtapiErrorToScsi(PVOID DeviceExtension
,
2283 PSCSI_REQUEST_BLOCK Srb
)
2285 PATAPI_MINIPORT_EXTENSION DevExt
;
2286 ULONG CommandPortBase
;
2287 ULONG ControlPortBase
;
2292 DPRINT("AtapiErrorToScsi() called\n");
2294 DevExt
= (PATAPI_MINIPORT_EXTENSION
)DeviceExtension
;
2296 CommandPortBase
= DevExt
->CommandPortBase
;
2297 ControlPortBase
= DevExt
->ControlPortBase
;
2299 ErrorReg
= IDEReadError(CommandPortBase
);
2301 if (DevExt
->DeviceAtapi
[Srb
->TargetId
])
2303 switch (ErrorReg
>> 4)
2305 case SCSI_SENSE_NO_SENSE
:
2306 DPRINT("ATAPI error: SCSI_SENSE_NO_SENSE\n");
2307 ScsiStatus
= SCSISTAT_CHECK_CONDITION
;
2308 SrbStatus
= SRB_STATUS_ERROR
;
2311 case SCSI_SENSE_RECOVERED_ERROR
:
2312 DPRINT("ATAPI error: SCSI_SENSE_RECOVERED_SENSE\n");
2314 SrbStatus
= SRB_STATUS_SUCCESS
;
2317 case SCSI_SENSE_NOT_READY
:
2318 DPRINT("ATAPI error: SCSI_SENSE_NOT_READY\n");
2319 ScsiStatus
= SCSISTAT_CHECK_CONDITION
;
2320 SrbStatus
= SRB_STATUS_ERROR
;
2323 case SCSI_SENSE_MEDIUM_ERROR
:
2324 DPRINT("ATAPI error: SCSI_SENSE_MEDIUM_ERROR\n");
2325 ScsiStatus
= SCSISTAT_CHECK_CONDITION
;
2326 SrbStatus
= SRB_STATUS_ERROR
;
2329 case SCSI_SENSE_HARDWARE_ERROR
:
2330 DPRINT("ATAPI error: SCSI_SENSE_HARDWARE_ERROR\n");
2331 ScsiStatus
= SCSISTAT_CHECK_CONDITION
;
2332 SrbStatus
= SRB_STATUS_ERROR
;
2335 case SCSI_SENSE_ILLEGAL_REQUEST
:
2336 DPRINT("ATAPI error: SCSI_SENSE_ILLEGAL_REQUEST\n");
2337 ScsiStatus
= SCSISTAT_CHECK_CONDITION
;
2338 SrbStatus
= SRB_STATUS_ERROR
;
2341 case SCSI_SENSE_UNIT_ATTENTION
:
2342 DPRINT("ATAPI error: SCSI_SENSE_UNIT_ATTENTION\n");
2343 ScsiStatus
= SCSISTAT_CHECK_CONDITION
;
2344 SrbStatus
= SRB_STATUS_ERROR
;
2347 case SCSI_SENSE_DATA_PROTECT
:
2348 DPRINT("ATAPI error: SCSI_SENSE_DATA_PROTECT\n");
2349 ScsiStatus
= SCSISTAT_CHECK_CONDITION
;
2350 SrbStatus
= SRB_STATUS_ERROR
;
2353 case SCSI_SENSE_BLANK_CHECK
:
2354 DPRINT("ATAPI error: SCSI_SENSE_BLANK_CHECK\n");
2355 ScsiStatus
= SCSISTAT_CHECK_CONDITION
;
2356 SrbStatus
= SRB_STATUS_ERROR
;
2359 case SCSI_SENSE_ABORTED_COMMAND
:
2360 DPRINT("ATAPI error: SCSI_SENSE_ABORTED_COMMAND\n");
2361 ScsiStatus
= SCSISTAT_CHECK_CONDITION
;
2362 SrbStatus
= SRB_STATUS_ERROR
;
2366 DPRINT("ATAPI error: Invalid sense key\n");
2368 SrbStatus
= SRB_STATUS_ERROR
;
2374 DPRINT1("IDE error: %02x\n", ErrorReg
);
2377 SrbStatus
= SRB_STATUS_ERROR
;
2380 UCHAR SectorCount
, SectorNum
, CylinderLow
, CylinderHigh
;
2383 CylinderLow
= IDEReadCylinderLow(CommandPortBase
);
2384 CylinderHigh
= IDEReadCylinderHigh(CommandPortBase
);
2385 DriveHead
= IDEReadDriveHead(CommandPortBase
);
2386 SectorCount
= IDEReadSectorCount(CommandPortBase
);
2387 SectorNum
= IDEReadSectorNum(CommandPortBase
);
2389 DPRINT1("IDE Error: ERR:%02x CYLLO:%02x CYLHI:%02x SCNT:%02x SNUM:%02x\n",
2400 Srb
->ScsiStatus
= ScsiStatus
;
2402 DPRINT("AtapiErrorToScsi() done\n");