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.34 2002/12/15 00:23:31 sedwards 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 } ATAPI_MINIPORT_EXTENSION
, *PATAPI_MINIPORT_EXTENSION
;
96 typedef struct _UNIT_EXTENSION
99 } UNIT_EXTENSION
, *PUNIT_EXTENSION
;
101 PCI_SLOT_NUMBER LastSlotNumber
;
103 #ifdef ENABLE_NATIVE_PCI
104 typedef struct _PCI_NATIVE_CONTROLLER
109 PCI_NATIVE_CONTROLLER
, *PPCI_NATIVE_CONTROLLER
;
111 PCI_NATIVE_CONTROLLER
const PciNativeController
[] =
115 0x4D68, // PDC20268, Ultra100TX2
119 0x4D30, // PDC20267, Ultra100
125 // ----------------------------------------------- Discardable Declarations
129 // make the initialization routines discardable, so that they
132 #pragma alloc_text(init, DriverEntry)
133 #pragma alloc_text(init, IDECreateController)
134 #pragma alloc_text(init, IDEPolledRead)
136 // make the PASSIVE_LEVEL routines pageable, so that they don't
137 // waste nonpaged memory
139 #pragma alloc_text(page, IDEShutdown)
140 #pragma alloc_text(page, IDEDispatchOpenClose)
141 #pragma alloc_text(page, IDEDispatchRead)
142 #pragma alloc_text(page, IDEDispatchWrite)
144 #endif /* ALLOC_PRAGMA */
146 // ---------------------------------------------------- Forward Declarations
149 AtapiFindCompatiblePciController(PVOID DeviceExtension
,
151 PVOID BusInformation
,
152 PCHAR ArgumentString
,
153 PPORT_CONFIGURATION_INFORMATION ConfigInfo
,
157 AtapiFindIsaBusController(PVOID DeviceExtension
,
159 PVOID BusInformation
,
160 PCHAR ArgumentString
,
161 PPORT_CONFIGURATION_INFORMATION ConfigInfo
,
165 AtapiFindNativePciController(PVOID DeviceExtension
,
167 PVOID BusInformation
,
168 PCHAR ArgumentString
,
169 PPORT_CONFIGURATION_INFORMATION ConfigInfo
,
172 static BOOLEAN STDCALL
173 AtapiInitialize(IN PVOID DeviceExtension
);
175 static BOOLEAN STDCALL
176 AtapiResetBus(IN PVOID DeviceExtension
,
179 static BOOLEAN STDCALL
180 AtapiStartIo(IN PVOID DeviceExtension
,
181 IN PSCSI_REQUEST_BLOCK Srb
);
183 static BOOLEAN STDCALL
184 AtapiInterrupt(IN PVOID DeviceExtension
);
187 AtapiFindDevices(PATAPI_MINIPORT_EXTENSION DeviceExtension
,
188 PPORT_CONFIGURATION_INFORMATION ConfigInfo
);
191 AtapiIdentifyDevice(IN ULONG CommandPort
,
192 IN ULONG ControlPort
,
195 OUT PIDE_DRIVE_IDENTIFY DrvParms
);
198 IDEResetController(IN ULONG CommandPort
,
199 IN ULONG ControlPort
);
202 AtapiPolledRead(IN ULONG CommandPort
,
203 IN ULONG ControlPort
,
208 IN BYTE CylinderHigh
,
216 AtapiSendAtapiCommand(IN PATAPI_MINIPORT_EXTENSION DeviceExtension
,
217 IN PSCSI_REQUEST_BLOCK Srb
);
220 AtapiSendIdeCommand(IN PATAPI_MINIPORT_EXTENSION DeviceExtension
,
221 IN PSCSI_REQUEST_BLOCK Srb
);
224 AtapiInquiry(IN PATAPI_MINIPORT_EXTENSION DeviceExtension
,
225 IN PSCSI_REQUEST_BLOCK Srb
);
228 AtapiReadCapacity(IN PATAPI_MINIPORT_EXTENSION DeviceExtension
,
229 IN PSCSI_REQUEST_BLOCK Srb
);
232 AtapiReadWrite(IN PATAPI_MINIPORT_EXTENSION DeviceExtension
,
233 IN PSCSI_REQUEST_BLOCK Srb
);
237 AtapiErrorToScsi(PVOID DeviceExtension
,
238 PSCSI_REQUEST_BLOCK Srb
);
240 // ---------------------------------------------------------------- Inlines
243 IDESwapBytePairs(char *Buf
,
249 for (i
= 0; i
< Cnt
; i
+= 2)
258 // ------------------------------------------------------- Public Interface
263 // This function initializes the driver, locates and claims
264 // hardware resources, and creates various NT objects needed
265 // to process I/O requests.
271 // IN PDRIVER_OBJECT DriverObject System allocated Driver Object
273 // IN PUNICODE_STRING RegistryPath Name of registry driver service
280 DriverEntry(IN PDRIVER_OBJECT DriverObject
,
281 IN PUNICODE_STRING RegistryPath
)
283 HW_INITIALIZATION_DATA InitData
;
286 DPRINT("ATAPI Driver %s\n", VERSION
);
287 DPRINT("RegistryPath: '%wZ'\n", RegistryPath
);
289 /* Initialize data structure */
290 RtlZeroMemory(&InitData
,
291 sizeof(HW_INITIALIZATION_DATA
));
292 InitData
.HwInitializationDataSize
= sizeof(HW_INITIALIZATION_DATA
);
293 InitData
.HwInitialize
= AtapiInitialize
;
294 InitData
.HwResetBus
= AtapiResetBus
;
295 InitData
.HwStartIo
= AtapiStartIo
;
296 InitData
.HwInterrupt
= AtapiInterrupt
;
298 InitData
.DeviceExtensionSize
= sizeof(ATAPI_MINIPORT_EXTENSION
);
299 InitData
.SpecificLuExtensionSize
= sizeof(UNIT_EXTENSION
);
301 InitData
.MapBuffers
= TRUE
;
304 /* Search the PCI bus for compatibility mode ide controllers */
306 InitData
.HwFindAdapter
= AtapiFindCompatiblePciController
;
307 InitData
.NumberOfAccessRanges
= 3;
308 InitData
.AdapterInterfaceType
= PCIBus
;
310 InitData
.VendorId
= NULL
;
311 InitData
.VendorIdLength
= 0;
312 InitData
.DeviceId
= NULL
;
313 InitData
.DeviceIdLength
= 0;
315 Status
= ScsiPortInitialize(DriverObject
,
319 // if (newStatus < statusToReturn)
320 // statusToReturn = newStatus;
323 /* Search the PCI bus for all ide controllers */
324 #ifdef ENABLE_NATIVE_PCI
326 InitData
.HwFindAdapter
= AtapiFindNativePciController
;
327 InitData
.NumberOfAccessRanges
= 3;
328 InitData
.AdapterInterfaceType
= PCIBus
;
330 InitData
.VendorId
= 0;
331 InitData
.VendorIdLength
= 0;
332 InitData
.DeviceId
= 0;
333 InitData
.DeviceIdLength
= 0;
335 LastSlotNumber
.u
.AsULONG
= 0xFFFFFFFF;
337 Status
= ScsiPortInitialize(DriverObject
,
341 // if (newStatus < statusToReturn)
342 // statusToReturn = newStatus;
345 /* Search the ISA bus for ide controllers */
347 InitData
.HwFindAdapter
= AtapiFindIsaBusController
;
348 InitData
.NumberOfAccessRanges
= 2;
349 InitData
.AdapterInterfaceType
= Isa
;
351 InitData
.VendorId
= NULL
;
352 InitData
.VendorIdLength
= 0;
353 InitData
.DeviceId
= NULL
;
354 InitData
.DeviceIdLength
= 0;
356 Status
= ScsiPortInitialize(DriverObject
,
360 // if (newStatus < statusToReturn)
361 // statusToReturn = newStatus;
364 DPRINT("Returning from DriverEntry\n");
371 AtapiClaimHwResources(PATAPI_MINIPORT_EXTENSION DevExt
,
372 PPORT_CONFIGURATION_INFORMATION ConfigInfo
,
373 INTERFACE_TYPE InterfaceType
,
374 ULONG CommandPortBase
,
375 ULONG ControlPortBase
,
376 ULONG BusMasterPortBase
,
377 ULONG InterruptVector
)
379 SCSI_PHYSICAL_ADDRESS IoAddress
;
382 IoAddress
= ScsiPortConvertUlongToPhysicalAddress(CommandPortBase
);
383 IoBase
= ScsiPortGetDeviceBase((PVOID
)DevExt
,
385 ConfigInfo
->SystemIoBusNumber
,
393 DevExt
->CommandPortBase
= (ULONG
)IoBase
;
394 ConfigInfo
->AccessRanges
[0].RangeStart
= IoAddress
;
395 ConfigInfo
->AccessRanges
[0].RangeLength
= 8;
396 ConfigInfo
->AccessRanges
[0].RangeInMemory
= FALSE
;
400 IoAddress
= ScsiPortConvertUlongToPhysicalAddress(ControlPortBase
+ 2);
401 IoBase
= ScsiPortGetDeviceBase((PVOID
)DevExt
,
403 ConfigInfo
->SystemIoBusNumber
,
409 ScsiPortFreeDeviceBase((PVOID
)DevExt
,
410 (PVOID
)DevExt
->CommandPortBase
);
413 DevExt
->ControlPortBase
= (ULONG
)IoBase
;
414 ConfigInfo
->AccessRanges
[1].RangeStart
= IoAddress
;
415 ConfigInfo
->AccessRanges
[1].RangeLength
= 1;
416 ConfigInfo
->AccessRanges
[1].RangeInMemory
= FALSE
;
418 if (BusMasterPortBase
)
420 IoAddress
= ScsiPortConvertUlongToPhysicalAddress(BusMasterPortBase
);
421 IoBase
= ScsiPortGetDeviceBase((PVOID
)DevExt
,
423 ConfigInfo
->SystemIoBusNumber
,
429 ScsiPortFreeDeviceBase((PVOID
)DevExt
, (PVOID
)DevExt
->CommandPortBase
);
430 ScsiPortFreeDeviceBase((PVOID
)DevExt
, (PVOID
)DevExt
->ControlPortBase
);
433 ConfigInfo
->AccessRanges
[2].RangeStart
= IoAddress
;
434 ConfigInfo
->AccessRanges
[2].RangeLength
= 8;
435 ConfigInfo
->AccessRanges
[2].RangeInMemory
= FALSE
;
437 ConfigInfo
->BusInterruptLevel
= InterruptVector
;
438 ConfigInfo
->BusInterruptVector
= InterruptVector
;
439 ConfigInfo
->InterruptMode
= (InterfaceType
== Isa
) ? Latched
: LevelSensitive
;
441 if ((CommandPortBase
== 0x1F0 || ControlPortBase
== 0x3F4) && !ConfigInfo
->AtdiskPrimaryClaimed
)
443 ConfigInfo
->AtdiskPrimaryClaimed
= TRUE
;
445 if ((CommandPortBase
== 0x170 || ControlPortBase
== 0x374) && !ConfigInfo
->AtdiskSecondaryClaimed
)
447 ConfigInfo
->AtdiskSecondaryClaimed
= TRUE
;
455 AtapiFindCompatiblePciController(PVOID DeviceExtension
,
457 PVOID BusInformation
,
458 PCHAR ArgumentString
,
459 PPORT_CONFIGURATION_INFORMATION ConfigInfo
,
462 PATAPI_MINIPORT_EXTENSION DevExt
= (PATAPI_MINIPORT_EXTENSION
)DeviceExtension
;
463 PCI_SLOT_NUMBER SlotNumber
;
464 PCI_COMMON_CONFIG PciConfig
;
466 ULONG StartDeviceNumber
;
468 ULONG StartFunctionNumber
;
469 ULONG FunctionNumber
;
470 BOOLEAN ChannelFound
;
472 ULONG BusMasterBasePort
= 0;
474 DPRINT("AtapiFindCompatiblePciController() Bus: %lu Slot: %lu\n",
475 ConfigInfo
->SystemIoBusNumber
,
476 ConfigInfo
->SlotNumber
);
480 /* both channels were claimed: exit */
481 if (ConfigInfo
->AtdiskPrimaryClaimed
== TRUE
&&
482 ConfigInfo
->AtdiskSecondaryClaimed
== TRUE
)
483 return(SP_RETURN_NOT_FOUND
);
485 SlotNumber
.u
.AsULONG
= ConfigInfo
->SlotNumber
;
486 StartDeviceNumber
= SlotNumber
.u
.bits
.DeviceNumber
;
487 StartFunctionNumber
= SlotNumber
.u
.bits
.FunctionNumber
;
488 for (DeviceNumber
= StartDeviceNumber
; DeviceNumber
< PCI_MAX_DEVICES
; DeviceNumber
++)
490 SlotNumber
.u
.bits
.DeviceNumber
= DeviceNumber
;
491 for (FunctionNumber
= StartFunctionNumber
; FunctionNumber
< PCI_MAX_FUNCTION
; FunctionNumber
++)
493 SlotNumber
.u
.bits
.FunctionNumber
= FunctionNumber
;
494 ChannelFound
= FALSE
;
497 DataSize
= ScsiPortGetBusData(DeviceExtension
,
499 ConfigInfo
->SystemIoBusNumber
,
500 SlotNumber
.u
.AsULONG
,
502 PCI_COMMON_HDR_LENGTH
);
503 if (DataSize
!= PCI_COMMON_HDR_LENGTH
)
505 if (FunctionNumber
== 0)
515 DPRINT("%x %x\n", PciConfig
.BaseClass
, PciConfig
.SubClass
);
516 if (PciConfig
.BaseClass
== 0x01 &&
517 PciConfig
.SubClass
== 0x01) // &&
518 // (PciConfig.ProgIf & 0x05) == 0)
520 /* both channels are in compatibility mode */
521 DPRINT("Bus %1lu Device %2lu Func %1lu VenID 0x%04hx DevID 0x%04hx\n",
522 ConfigInfo
->SystemIoBusNumber
,
523 SlotNumber
.u
.bits
.DeviceNumber
,
524 SlotNumber
.u
.bits
.FunctionNumber
,
527 DPRINT("ProgIF 0x%02hx\n", PciConfig
.ProgIf
);
529 DPRINT("Found IDE controller in compatibility mode!\n");
531 ConfigInfo
->NumberOfBuses
= 1;
532 ConfigInfo
->MaximumNumberOfTargets
= 2;
533 ConfigInfo
->MaximumTransferLength
= 0x10000; /* max 64Kbyte */
535 if (PciConfig
.ProgIf
& 0x80)
537 DPRINT("Found IDE Bus Master controller!\n");
538 if (PciConfig
.u
.type0
.BaseAddresses
[4] & PCI_ADDRESS_IO_SPACE
)
540 BusMasterBasePort
= PciConfig
.u
.type0
.BaseAddresses
[4] & PCI_ADDRESS_IO_ADDRESS_MASK
;
541 DPRINT(" IDE Bus Master Registers at IO %lx\n", BusMasterBasePort
);
544 if (ConfigInfo
->AtdiskPrimaryClaimed
== FALSE
)
546 /* Both channels unclaimed: Claim primary channel */
547 DPRINT("Primary channel!\n");
548 ChannelFound
= AtapiClaimHwResources(DevExt
,
557 else if (ConfigInfo
->AtdiskSecondaryClaimed
== FALSE
)
559 /* Primary channel already claimed: claim secondary channel */
560 DPRINT("Secondary channel!\n");
562 ChannelFound
= AtapiClaimHwResources(DevExt
,
567 BusMasterBasePort
? BusMasterBasePort
+ 8 : 0,
571 /* Find attached devices */
574 DeviceFound
= AtapiFindDevices(DevExt
, ConfigInfo
);
575 ConfigInfo
->SlotNumber
= SlotNumber
.u
.AsULONG
;
576 DPRINT("AtapiFindCompatiblePciController() returns: SP_RETURN_FOUND\n");
577 return(SP_RETURN_FOUND
);
580 if (FunctionNumber
== 0 && !(PciConfig
.HeaderType
& PCI_MULTIFUNCTION
))
585 StartFunctionNumber
= 0;
587 DPRINT("AtapiFindCompatiblePciController() returns: SP_RETURN_NOT_FOUND\n");
589 return(SP_RETURN_NOT_FOUND
);
596 AtapiFindIsaBusController(PVOID DeviceExtension
,
598 PVOID BusInformation
,
599 PCHAR ArgumentString
,
600 PPORT_CONFIGURATION_INFORMATION ConfigInfo
,
603 PATAPI_MINIPORT_EXTENSION DevExt
= (PATAPI_MINIPORT_EXTENSION
)DeviceExtension
;
604 BOOLEAN ChannelFound
= FALSE
;
605 BOOLEAN DeviceFound
= FALSE
;
607 DPRINT("AtapiFindIsaBusController() called!\n");
611 ConfigInfo
->NumberOfBuses
= 1;
612 ConfigInfo
->MaximumNumberOfTargets
= 2;
613 ConfigInfo
->MaximumTransferLength
= 0x10000; /* max 64Kbyte */
615 if (ConfigInfo
->AtdiskPrimaryClaimed
== FALSE
)
617 /* Both channels unclaimed: Claim primary channel */
618 DPRINT("Primary channel!\n");
620 ChannelFound
= AtapiClaimHwResources(DevExt
,
629 else if (ConfigInfo
->AtdiskSecondaryClaimed
== FALSE
)
631 /* Primary channel already claimed: claim secondary channel */
632 DPRINT("Secondary channel!\n");
634 ChannelFound
= AtapiClaimHwResources(DevExt
,
645 DPRINT("AtapiFindIsaBusController() both channels claimed. Returns: SP_RETURN_NOT_FOUND\n");
647 return(SP_RETURN_NOT_FOUND
);
650 /* Find attached devices */
653 DeviceFound
= AtapiFindDevices(DevExt
,
655 DPRINT("AtapiFindIsaBusController() returns: SP_RETURN_FOUND\n");
656 return(SP_RETURN_FOUND
);
659 return SP_RETURN_NOT_FOUND
;
664 #ifdef ENABLE_NATIVE_PCI
666 AtapiFindNativePciController(PVOID DeviceExtension
,
668 PVOID BusInformation
,
669 PCHAR ArgumentString
,
670 PPORT_CONFIGURATION_INFORMATION ConfigInfo
,
673 PATAPI_MINIPORT_EXTENSION DevExt
= (PATAPI_MINIPORT_EXTENSION
)DeviceExtension
;
674 PCI_COMMON_CONFIG PciConfig
;
675 PCI_SLOT_NUMBER SlotNumber
;
678 ULONG StartDeviceNumber
;
679 ULONG FunctionNumber
;
680 ULONG StartFunctionNumber
;
681 ULONG BusMasterBasePort
;
683 BOOLEAN ChannelFound
;
685 DPRINT("AtapiFindNativePciController() called!\n");
687 SlotNumber
.u
.AsULONG
= ConfigInfo
->SlotNumber
;
688 StartDeviceNumber
= SlotNumber
.u
.bits
.DeviceNumber
;
689 StartFunctionNumber
= SlotNumber
.u
.bits
.FunctionNumber
;
690 for (DeviceNumber
= StartDeviceNumber
; DeviceNumber
< PCI_MAX_DEVICES
; DeviceNumber
++)
692 SlotNumber
.u
.bits
.DeviceNumber
= DeviceNumber
;
693 for (FunctionNumber
= StartFunctionNumber
; FunctionNumber
< PCI_MAX_FUNCTION
; FunctionNumber
++)
695 SlotNumber
.u
.bits
.FunctionNumber
= FunctionNumber
;
696 DataSize
= ScsiPortGetBusData(DeviceExtension
,
698 ConfigInfo
->SystemIoBusNumber
,
699 SlotNumber
.u
.AsULONG
,
701 PCI_COMMON_HDR_LENGTH
);
702 if (DataSize
!= PCI_COMMON_HDR_LENGTH
)
706 for (Count
= 0; Count
< sizeof(PciNativeController
)/sizeof(PCI_NATIVE_CONTROLLER
); Count
++)
708 if (PciConfig
.VendorID
== PciNativeController
[Count
].VendorID
&&
709 PciConfig
.DeviceID
== PciNativeController
[Count
].DeviceID
)
714 if (Count
< sizeof(PciNativeController
)/sizeof(PCI_NATIVE_CONTROLLER
))
716 /* We have found a known native pci ide controller */
717 if ((PciConfig
.ProgIf
& 0x80) && (PciConfig
.u
.type0
.BaseAddresses
[4] & PCI_ADDRESS_IO_SPACE
))
719 DPRINT("Found IDE Bus Master controller!\n");
720 BusMasterBasePort
= PciConfig
.u
.type0
.BaseAddresses
[4] & PCI_ADDRESS_IO_ADDRESS_MASK
;
721 DPRINT(" IDE Bus Master Registers at IO %lx\n", BusMasterBasePort
);
725 BusMasterBasePort
= 0;
728 DPRINT("VendorID: %04x, DeviceID: %04x\n", PciConfig
.VendorID
, PciConfig
.DeviceID
);
729 ConfigInfo
->NumberOfBuses
= 1;
730 ConfigInfo
->MaximumNumberOfTargets
= 2;
731 ConfigInfo
->MaximumTransferLength
= 0x10000; /* max 64Kbyte */
734 We must not store and use the last tested slot number. If there is a recall
735 to the some device and we will claim the primary channel again than the call
736 to ScsiPortGetDeviceBase in AtapiClaimHwResource will fail and we can try to
737 claim the secondary channel.
739 ChannelFound
= FALSE
;
740 if (LastSlotNumber
.u
.AsULONG
!= SlotNumber
.u
.AsULONG
)
742 /* try to claim primary channel */
743 if ((PciConfig
.u
.type0
.BaseAddresses
[0] & PCI_ADDRESS_IO_SPACE
) &&
744 (PciConfig
.u
.type0
.BaseAddresses
[1] & PCI_ADDRESS_IO_SPACE
))
746 /* primary channel is enabled */
747 ChannelFound
= AtapiClaimHwResources(DevExt
,
750 PciConfig
.u
.type0
.BaseAddresses
[0] & PCI_ADDRESS_IO_ADDRESS_MASK
,
751 PciConfig
.u
.type0
.BaseAddresses
[1] & PCI_ADDRESS_IO_ADDRESS_MASK
,
753 PciConfig
.u
.type0
.InterruptLine
);
756 AtapiFindDevices(DevExt
, ConfigInfo
);
758 ConfigInfo
->SlotNumber
= LastSlotNumber
.u
.AsULONG
= SlotNumber
.u
.AsULONG
;
759 return SP_RETURN_FOUND
;
765 /* try to claim secondary channel */
766 if ((PciConfig
.u
.type0
.BaseAddresses
[2] & PCI_ADDRESS_IO_SPACE
) &&
767 (PciConfig
.u
.type0
.BaseAddresses
[3] & PCI_ADDRESS_IO_SPACE
))
769 /* secondary channel is enabled */
770 ChannelFound
= AtapiClaimHwResources(DevExt
,
773 PciConfig
.u
.type0
.BaseAddresses
[2] & PCI_ADDRESS_IO_ADDRESS_MASK
,
774 PciConfig
.u
.type0
.BaseAddresses
[3] & PCI_ADDRESS_IO_ADDRESS_MASK
,
775 BusMasterBasePort
? BusMasterBasePort
+ 8 : 0,
776 PciConfig
.u
.type0
.InterruptLine
);
779 AtapiFindDevices(DevExt
, ConfigInfo
);
781 LastSlotNumber
.u
.AsULONG
= 0xFFFFFFFF;
782 return SP_RETURN_FOUND
;
788 StartFunctionNumber
= 0;
791 LastSlotNumber
.u
.AsULONG
= 0xFFFFFFFF;
792 DPRINT("AtapiFindNativePciController() done!\n");
794 return(SP_RETURN_NOT_FOUND
);
799 static BOOLEAN STDCALL
800 AtapiInitialize(IN PVOID DeviceExtension
)
806 static BOOLEAN STDCALL
807 AtapiResetBus(IN PVOID DeviceExtension
,
814 static BOOLEAN STDCALL
815 AtapiStartIo(IN PVOID DeviceExtension
,
816 IN PSCSI_REQUEST_BLOCK Srb
)
818 PATAPI_MINIPORT_EXTENSION DevExt
;
821 DPRINT("AtapiStartIo() called\n");
823 DevExt
= (PATAPI_MINIPORT_EXTENSION
)DeviceExtension
;
825 switch (Srb
->Function
)
827 case SRB_FUNCTION_EXECUTE_SCSI
:
828 DevExt
->CurrentSrb
= Srb
;
829 if (DevExt
->DeviceAtapi
[Srb
->TargetId
] == TRUE
)
831 Result
= AtapiSendAtapiCommand(DevExt
,
836 Result
= AtapiSendIdeCommand(DevExt
,
843 Srb
->SrbStatus
= Result
;
846 if (Result
!= SRB_STATUS_PENDING
)
848 DevExt
->CurrentSrb
= NULL
;
849 Srb
->SrbStatus
= (UCHAR
)Result
;
851 ScsiPortNotification(RequestComplete
,
854 ScsiPortNotification(NextRequest
,
860 DPRINT("SrbStatus = SRB_STATUS_PENDING\n");
863 DPRINT("AtapiStartIo() done\n");
869 static BOOLEAN STDCALL
870 AtapiInterrupt(IN PVOID DeviceExtension
)
872 PATAPI_MINIPORT_EXTENSION DevExt
;
873 PSCSI_REQUEST_BLOCK Srb
;
874 ULONG CommandPortBase
;
875 ULONG ControlPortBase
;
881 PUCHAR TargetAddress
;
884 DPRINT("AtapiInterrupt() called!\n");
886 DevExt
= (PATAPI_MINIPORT_EXTENSION
)DeviceExtension
;
888 CommandPortBase
= DevExt
->CommandPortBase
;
889 ControlPortBase
= DevExt
->ControlPortBase
;
891 if (DevExt
->ExpectingInterrupt
== FALSE
)
893 DeviceStatus
= IDEReadStatus(CommandPortBase
);
894 DPRINT("AtapiInterrupt(): Unexpected interrupt (port=%x)\n", CommandPortBase
);
898 /* check if it was our irq */
899 if ((DeviceStatus
= IDEReadAltStatus(ControlPortBase
)) & IDE_SR_BUSY
)
901 ScsiPortStallExecution(1);
902 if ((DeviceStatus
= IDEReadAltStatus(ControlPortBase
) & IDE_SR_BUSY
))
904 DPRINT("AtapiInterrupt(): Unexpected interrupt (port=%x)\n", CommandPortBase
);
909 Srb
= DevExt
->CurrentSrb
;
910 DPRINT("Srb: %p\n", Srb
);
912 DPRINT("CommandPortBase: %lx ControlPortBase: %lx\n", CommandPortBase
, ControlPortBase
);
914 IsAtapi
= DevExt
->DeviceAtapi
[Srb
->TargetId
];
915 DPRINT("IsAtapi == %s\n", (IsAtapi
) ? "TRUE" : "FALSE");
919 DeviceStatus
= IDEReadStatus(CommandPortBase
);
920 DPRINT("DeviceStatus: %x\n", DeviceStatus
);
922 if ((DeviceStatus
& IDE_SR_ERR
) &&
923 (Srb
->Cdb
[0] != SCSIOP_REQUEST_SENSE
))
925 /* Report error condition */
926 Srb
->SrbStatus
= SRB_STATUS_ERROR
;
931 if (Srb
->SrbFlags
& SRB_FLAGS_DATA_IN
)
933 DPRINT("Read data\n");
935 /* Update controller/device state variables */
936 TargetAddress
= Srb
->DataBuffer
;
940 TransferSize
= IDEReadCylinderLow(CommandPortBase
);
941 TransferSize
+= IDEReadCylinderHigh(CommandPortBase
) << 8;
945 TransferSize
= DevExt
->TransferSize
[Srb
->TargetId
];
948 DPRINT("TransferLength: %lu\n", Srb
->DataTransferLength
);
949 DPRINT("TransferSize: %lu\n", TransferSize
);
951 if (Srb
->DataTransferLength
<= TransferSize
)
955 TransferSize
= Srb
->DataTransferLength
;
957 Srb
->DataTransferLength
= 0;
962 Srb
->DataTransferLength
-= TransferSize
;
965 Srb
->DataBuffer
+= TransferSize
;
966 DPRINT("IsLastBlock == %s\n", (IsLastBlock
) ? "TRUE" : "FALSE");
968 /* Wait for DRQ assertion */
969 for (Retries
= 0; Retries
< IDE_MAX_DRQ_RETRIES
&&
970 !(IDEReadStatus(CommandPortBase
) & IDE_SR_DRQ
);
973 KeStallExecutionProcessor(10);
976 /* Copy the block of data */
977 if (DevExt
->DWordIo
[Srb
->TargetId
])
979 IDEReadBlock32(CommandPortBase
,
985 IDEReadBlock(CommandPortBase
,
992 for (Retries
= 0; Retries
< IDE_MAX_BUSY_RETRIES
&&
993 (IDEReadStatus(CommandPortBase
) & IDE_SR_BUSY
);
996 KeStallExecutionProcessor(10);
999 /* Check for data overrun */
1000 while (IDEReadStatus(CommandPortBase
) & IDE_SR_DRQ
)
1002 DPRINT1("AtapiInterrupt(): reading overrun data!\n");
1003 IDEReadWord(CommandPortBase
);
1007 Srb
->SrbStatus
= SRB_STATUS_SUCCESS
;
1009 else if (Srb
->SrbFlags
& SRB_FLAGS_DATA_OUT
)
1011 DPRINT("Write data\n");
1013 if (Srb
->DataTransferLength
== 0)
1015 /* Check for data overrun */
1016 if (DeviceStatus
& IDE_SR_DRQ
)
1018 /* FIXME: Handle error! */
1019 /* This can occure if the irq is shared with an other and if the
1020 ide controller has a write buffer. We have write the last sectors
1021 and the other device has a irq before ours. The isr is called but
1022 we haven't a interrupt. The controller writes the sector buffer
1023 and the status register shows DRQ because the write is not ended. */
1024 DPRINT("AtapiInterrupt(): data overrun error!\n");
1030 /* Update SRB data */
1031 TransferSize
= DevExt
->TransferSize
[Srb
->TargetId
];
1032 if (Srb
->DataTransferLength
< TransferSize
)
1034 TransferSize
= Srb
->DataTransferLength
;
1037 TargetAddress
= Srb
->DataBuffer
;
1038 Srb
->DataBuffer
+= TransferSize
;
1039 Srb
->DataTransferLength
-= TransferSize
;
1041 /* Write the sector */
1042 if (DevExt
->DWordIo
[Srb
->TargetId
])
1044 IDEWriteBlock32(CommandPortBase
,
1050 IDEWriteBlock(CommandPortBase
,
1056 Srb
->SrbStatus
= SRB_STATUS_SUCCESS
;
1060 DPRINT1("Unspecified transfer direction!\n");
1061 Srb
->SrbStatus
= SRB_STATUS_SUCCESS
; // SRB_STATUS_ERROR;
1067 if (Srb
->SrbStatus
== SRB_STATUS_ERROR
)
1069 Srb
->SrbStatus
= AtapiErrorToScsi(DeviceExtension
,
1074 /* complete this packet */
1077 DevExt
->ExpectingInterrupt
= FALSE
;
1079 ScsiPortNotification(RequestComplete
,
1083 ScsiPortNotification(NextRequest
,
1088 DPRINT("AtapiInterrupt() done!\n");
1093 // ---------------------------------------------------- Discardable statics
1096 /**********************************************************************
1101 * Searches for devices on the given port.
1108 * Port device specific information.
1111 * Port configuration information.
1114 * TRUE: At least one device is attached to the port.
1115 * FALSE: No device is attached to the port.
1119 AtapiFindDevices(PATAPI_MINIPORT_EXTENSION DeviceExtension
,
1120 PPORT_CONFIGURATION_INFORMATION ConfigInfo
)
1122 BOOLEAN DeviceFound
= FALSE
;
1123 ULONG CommandPortBase
;
1124 ULONG ControlPortBase
;
1129 DPRINT("AtapiFindDevices() called\n");
1131 CommandPortBase
= ScsiPortConvertPhysicalAddressToUlong(ConfigInfo
->AccessRanges
[0].RangeStart
);
1132 DPRINT(" CommandPortBase: %x\n", CommandPortBase
);
1134 ControlPortBase
= ScsiPortConvertPhysicalAddressToUlong(ConfigInfo
->AccessRanges
[1].RangeStart
);
1135 DPRINT(" ControlPortBase: %x\n", ControlPortBase
);
1137 for (UnitNumber
= 0; UnitNumber
< 2; UnitNumber
++)
1140 IDEWriteDriveHead(CommandPortBase
,
1141 IDE_DH_FIXED
| (UnitNumber
? IDE_DH_DRV1
: 0));
1142 ScsiPortStallExecution(500);
1144 /* Disable interrupts */
1145 IDEWriteDriveControl(ControlPortBase
,
1147 ScsiPortStallExecution(500);
1149 IDEWriteCylinderHigh(CommandPortBase
, 0);
1150 IDEWriteCylinderLow(CommandPortBase
, 0);
1151 IDEWriteCommand(CommandPortBase
, IDE_CMD_RESET
);
1153 for (Retries
= 0; Retries
< 20000; Retries
++)
1155 if (!(IDEReadStatus(CommandPortBase
) & IDE_SR_BUSY
))
1159 ScsiPortStallExecution(150);
1161 if (Retries
>= 20000)
1163 DPRINT("Timeout on drive %lu\n", UnitNumber
);
1164 DeviceExtension
->DevicePresent
[UnitNumber
] = FALSE
;
1168 High
= IDEReadCylinderHigh(CommandPortBase
);
1169 Low
= IDEReadCylinderLow(CommandPortBase
);
1171 DPRINT(" Check drive %lu: High 0x%x Low 0x%x\n",
1176 if (High
== 0xEB && Low
== 0x14)
1178 if (AtapiIdentifyDevice(CommandPortBase
,
1182 &DeviceExtension
->DeviceParams
[UnitNumber
]))
1184 DPRINT(" ATAPI drive found!\n");
1185 DeviceExtension
->DevicePresent
[UnitNumber
] = TRUE
;
1186 DeviceExtension
->DeviceAtapi
[UnitNumber
] = TRUE
;
1187 DeviceExtension
->TransferSize
[UnitNumber
] = DeviceExtension
->DeviceParams
[UnitNumber
].BytesPerSector
;
1188 DeviceExtension
->MultiSectorCommand
[UnitNumber
] = FALSE
;
1189 DeviceExtension
->DWordIo
[UnitNumber
] = FALSE
;
1194 DPRINT(" No ATAPI drive found!\n");
1199 if (AtapiIdentifyDevice(CommandPortBase
,
1203 &DeviceExtension
->DeviceParams
[UnitNumber
]))
1205 DPRINT(" IDE drive found!\n");
1206 DeviceExtension
->DevicePresent
[UnitNumber
] = TRUE
;
1207 DeviceExtension
->DeviceAtapi
[UnitNumber
] = FALSE
;
1208 DeviceExtension
->TransferSize
[UnitNumber
] = DeviceExtension
->DeviceParams
[UnitNumber
].BytesPerSector
;
1209 if (DeviceExtension
->DeviceParams
[UnitNumber
].RWMultImplemented
& 0x8000 &&
1210 DeviceExtension
->DeviceParams
[UnitNumber
].RWMultImplemented
& 0xff)
1212 DeviceExtension
->TransferSize
[UnitNumber
] *= (DeviceExtension
->DeviceParams
[UnitNumber
].RWMultCurrent
& 0xff);
1213 DeviceExtension
->MultiSectorCommand
[UnitNumber
] = TRUE
;
1217 DeviceExtension
->MultiSectorCommand
[UnitNumber
] = FALSE
;
1219 DeviceExtension
->DWordIo
[UnitNumber
] = DeviceExtension
->DeviceParams
[UnitNumber
].DWordIo
? TRUE
: FALSE
;
1224 DPRINT(" No IDE drive found!\n");
1230 DPRINT("AtapiFindDrives() done (DeviceFound %s)\n", (DeviceFound
) ? "TRUE" : "FALSE");
1232 return(DeviceFound
);
1236 // AtapiResetController
1239 // Reset the controller and report completion status
1245 // IN WORD CommandPort The address of the command port
1246 // IN WORD ControlPort The address of the control port
1252 AtapiResetController(IN ULONG CommandPort
,
1253 IN ULONG ControlPort
)
1257 /* Assert drive reset line */
1258 IDEWriteDriveControl(ControlPort
, IDE_DC_SRST
);
1260 /* Wait for min. 25 microseconds */
1261 ScsiPortStallExecution(IDE_RESET_PULSE_LENGTH
);
1263 /* Negate drive reset line */
1264 IDEWriteDriveControl(ControlPort
, 0);
1266 /* Wait for BUSY negation */
1267 for (Retries
= 0; Retries
< IDE_RESET_BUSY_TIMEOUT
* 1000; Retries
++)
1269 if (!(IDEReadStatus(CommandPort
) & IDE_SR_BUSY
))
1273 ScsiPortStallExecution(10);
1276 if (Retries
>= IDE_RESET_BUSY_TIMEOUT
* 1000)
1281 // return TRUE if controller came back to life. and
1282 // the registers are initialized correctly
1283 return(IDEReadError(CommandPort
) == 1);
1287 * AtapiIdentifyDevice
1290 * Get the identification block from the drive
1297 * Address of the command port
1299 * Address of the control port
1301 * The drive index (0,1)
1303 * Send an ATA(FALSE) or an ATAPI(TRUE) identify comand
1305 * Address to write drive ident block
1308 * TRUE: The drive identification block was retrieved successfully
1309 * FALSE: an error ocurred
1313 AtapiIdentifyDevice(IN ULONG CommandPort
,
1314 IN ULONG ControlPort
,
1317 OUT PIDE_DRIVE_IDENTIFY DrvParms
)
1321 /* Get the Drive Identify block from drive or die */
1322 if (AtapiPolledRead(CommandPort
,
1329 (DriveNum
? IDE_DH_DRV1
: 0),
1330 (Atapi
? IDE_CMD_IDENT_ATAPI_DRV
: IDE_CMD_IDENT_ATA_DRV
),
1331 (BYTE
*)DrvParms
) != 0)
1333 DPRINT("IDEPolledRead() failed\n");
1337 /* Report on drive parameters if debug mode */
1338 IDESwapBytePairs(DrvParms
->SerialNumber
, 20);
1339 IDESwapBytePairs(DrvParms
->FirmwareRev
, 8);
1340 IDESwapBytePairs(DrvParms
->ModelNumber
, 40);
1341 DPRINT("Config:%04x Cyls:%5d Heads:%2d Sectors/Track:%3d Gaps:%02d %02d\n",
1342 DrvParms
->ConfigBits
,
1343 DrvParms
->LogicalCyls
,
1344 DrvParms
->LogicalHeads
,
1345 DrvParms
->SectorsPerTrack
,
1346 DrvParms
->InterSectorGap
,
1347 DrvParms
->InterSectorGapSize
);
1348 DPRINT("Bytes/PLO:%3d Vendor Cnt:%2d Serial number:[%.20s]\n",
1349 DrvParms
->BytesInPLO
,
1350 DrvParms
->VendorUniqueCnt
,
1351 DrvParms
->SerialNumber
);
1352 DPRINT("Cntlr type:%2d BufSiz:%5d ECC bytes:%3d Firmware Rev:[%.8s]\n",
1353 DrvParms
->ControllerType
,
1354 DrvParms
->BufferSize
* IDE_SECTOR_BUF_SZ
,
1355 DrvParms
->ECCByteCnt
,
1356 DrvParms
->FirmwareRev
);
1357 DPRINT("Model:[%.40s]\n", DrvParms
->ModelNumber
);
1358 DPRINT("RWMultMax?:%04x RWMult?:%02x LBA:%d DMA:%d MinPIO:%d ns MinDMA:%d ns\n",
1359 (DrvParms
->RWMultImplemented
),
1360 (DrvParms
->RWMultCurrent
) & 0xff,
1361 (DrvParms
->Capabilities
& IDE_DRID_LBA_SUPPORTED
) ? 1 : 0,
1362 (DrvParms
->Capabilities
& IDE_DRID_DMA_SUPPORTED
) ? 1 : 0,
1363 DrvParms
->MinPIOTransTime
,
1364 DrvParms
->MinDMATransTime
);
1365 DPRINT("TM:Cyls:%d Heads:%d Sectors/Trk:%d Capacity:%ld\n",
1366 DrvParms
->TMCylinders
,
1368 DrvParms
->TMSectorsPerTrk
,
1369 (ULONG
)(DrvParms
->TMCapacityLo
+ (DrvParms
->TMCapacityHi
<< 16)));
1370 DPRINT("TM:SectorCount: 0x%04x%04x = %lu\n",
1371 DrvParms
->TMSectorCountHi
,
1372 DrvParms
->TMSectorCountLo
,
1373 (ULONG
)((DrvParms
->TMSectorCountHi
<< 16) + DrvParms
->TMSectorCountLo
));
1375 DPRINT("BytesPerSector %d\n", DrvParms
->BytesPerSector
);
1376 if (DrvParms
->BytesPerSector
== 0)
1378 DrvParms
->BytesPerSector
= 512;
1382 for (i
= 15; i
>= 0; i
--)
1384 if (DrvParms
->BytesPerSector
& (1 << i
))
1386 DrvParms
->BytesPerSector
= 1 << i
;
1391 DPRINT("BytesPerSector %d\n", DrvParms
->BytesPerSector
);
1400 // Read a sector of data from the drive in a polled fashion.
1406 // IN WORD Address Address of command port for drive
1407 // IN BYTE PreComp Value to write to precomp register
1408 // IN BYTE SectorCnt Value to write to sectorCnt register
1409 // IN BYTE SectorNum Value to write to sectorNum register
1410 // IN BYTE CylinderLow Value to write to CylinderLow register
1411 // IN BYTE CylinderHigh Value to write to CylinderHigh register
1412 // IN BYTE DrvHead Value to write to Drive/Head register
1413 // IN BYTE Command Value to write to Command register
1414 // OUT BYTE *Buffer Buffer for output data
1417 // int 0 is success, non 0 is an error code
1421 AtapiPolledRead(IN ULONG CommandPort
,
1422 IN ULONG ControlPort
,
1426 IN BYTE CylinderLow
,
1427 IN BYTE CylinderHigh
,
1432 ULONG SectorCount
= 0;
1434 BOOLEAN Junk
= FALSE
;
1438 /* Wait for BUSY to clear */
1439 for (RetryCount
= 0; RetryCount
< IDE_MAX_BUSY_RETRIES
; RetryCount
++)
1441 Status
= IDEReadStatus(CommandPort
);
1442 if (!(Status
& IDE_SR_BUSY
))
1446 ScsiPortStallExecution(10);
1448 DPRINT("status=%02x\n", Status
);
1449 DPRINT("waited %ld usecs for busy to clear\n", RetryCount
* 10);
1450 if (RetryCount
>= IDE_MAX_BUSY_RETRIES
)
1452 DPRINT("Drive is BUSY for too long\n");
1453 return(IDE_ER_ABRT
);
1457 /* Write Drive/Head to select drive */
1458 IDEWriteDriveHead(CommandPort
, IDE_DH_FIXED
| DrvHead
);
1459 ScsiPortStallExecution(500);
1461 /* Disable interrupts */
1462 IDEWriteDriveControl(ControlPort
, IDE_DC_nIEN
);
1463 ScsiPortStallExecution(500);
1466 /* Wait for STATUS.BUSY and STATUS.DRQ to clear */
1467 for (RetryCount
= 0; RetryCount
< IDE_MAX_BUSY_RETRIES
; RetryCount
++)
1469 Status
= IDEReadStatus(CommandPort
);
1470 if (!(Status
& IDE_SR_BUSY
) && !(Status
& IDE_SR_DRQ
))
1474 ScsiPortStallExecution(10);
1476 if (RetryCount
>= IDE_MAX_BUSY_RETRIES
)
1482 /* Issue command to drive */
1483 if (DrvHead
& IDE_DH_LBA
)
1485 DPRINT("READ:DRV=%d:LBA=1:BLK=%08d:SC=%02x:CM=%02x\n",
1486 DrvHead
& IDE_DH_DRV1
? 1 : 0,
1487 ((DrvHead
& 0x0f) << 24) + (CylinderHigh
<< 16) + (CylinderLow
<< 8) + SectorNum
,
1493 DPRINT("READ:DRV=%d:LBA=0:CH=%02x:CL=%02x:HD=%01x:SN=%02x:SC=%02x:CM=%02x\n",
1494 DrvHead
& IDE_DH_DRV1
? 1 : 0,
1503 /* Setup command parameters */
1504 IDEWritePrecomp(CommandPort
, PreComp
);
1505 IDEWriteSectorCount(CommandPort
, SectorCnt
);
1506 IDEWriteSectorNum(CommandPort
, SectorNum
);
1507 IDEWriteCylinderHigh(CommandPort
, CylinderHigh
);
1508 IDEWriteCylinderLow(CommandPort
, CylinderLow
);
1509 IDEWriteDriveHead(CommandPort
, IDE_DH_FIXED
| DrvHead
);
1511 /* Issue the command */
1512 IDEWriteCommand(CommandPort
, Command
);
1513 ScsiPortStallExecution(50);
1515 /* wait for DRQ or error */
1516 for (RetryCount
= 0; RetryCount
< IDE_MAX_POLL_RETRIES
; RetryCount
++)
1518 Status
= IDEReadStatus(CommandPort
);
1519 if (!(Status
& IDE_SR_BUSY
))
1521 if (Status
& IDE_SR_ERR
)
1523 IDEWriteDriveControl(ControlPort
, 0);
1524 ScsiPortStallExecution(50);
1525 IDEReadStatus(CommandPort
);
1527 return(IDE_ER_ABRT
);
1529 if (Status
& IDE_SR_DRQ
)
1535 IDEWriteDriveControl(ControlPort
, 0);
1536 ScsiPortStallExecution(50);
1537 IDEReadStatus(CommandPort
);
1539 return(IDE_ER_ABRT
);
1542 ScsiPortStallExecution(10);
1546 if (RetryCount
>= IDE_MAX_POLL_RETRIES
)
1548 IDEWriteDriveControl(ControlPort
, 0);
1549 ScsiPortStallExecution(50);
1550 IDEReadStatus(CommandPort
);
1552 return(IDE_ER_ABRT
);
1557 /* Read data into buffer */
1560 IDEReadBlock(CommandPort
, Buffer
, IDE_SECTOR_BUF_SZ
);
1561 Buffer
+= IDE_SECTOR_BUF_SZ
;
1565 UCHAR JunkBuffer
[IDE_SECTOR_BUF_SZ
];
1566 IDEReadBlock(CommandPort
, JunkBuffer
, IDE_SECTOR_BUF_SZ
);
1570 /* Check for error or more sectors to read */
1571 for (RetryCount
= 0; RetryCount
< IDE_MAX_BUSY_RETRIES
; RetryCount
++)
1573 Status
= IDEReadStatus(CommandPort
);
1574 if (!(Status
& IDE_SR_BUSY
))
1576 if (Status
& IDE_SR_ERR
)
1578 IDEWriteDriveControl(ControlPort
, 0);
1579 ScsiPortStallExecution(50);
1580 IDEReadStatus(CommandPort
);
1582 return(IDE_ER_ABRT
);
1584 if (Status
& IDE_SR_DRQ
)
1586 if (SectorCount
>= SectorCnt
)
1588 DPRINT("Buffer size exceeded!\n");
1595 if (SectorCount
> SectorCnt
)
1597 DPRINT("Read %lu sectors of junk!\n",
1598 SectorCount
- SectorCnt
);
1600 IDEWriteDriveControl(ControlPort
, 0);
1601 ScsiPortStallExecution(50);
1602 IDEReadStatus(CommandPort
);
1612 // ------------------------------------------- Nondiscardable statics
1615 AtapiSendAtapiCommand(IN PATAPI_MINIPORT_EXTENSION DeviceExtension
,
1616 IN PSCSI_REQUEST_BLOCK Srb
)
1618 UCHAR ByteCountHigh
;
1624 DPRINT("AtapiSendAtapiCommand() called!\n");
1626 if (Srb
->PathId
!= 0)
1628 Srb
->SrbStatus
= SRB_STATUS_INVALID_PATH_ID
;
1629 return(SRB_STATUS_INVALID_PATH_ID
);
1632 if (Srb
->TargetId
> 1)
1634 Srb
->SrbStatus
= SRB_STATUS_INVALID_TARGET_ID
;
1635 return(SRB_STATUS_INVALID_TARGET_ID
);
1640 Srb
->SrbStatus
= SRB_STATUS_INVALID_LUN
;
1641 return(SRB_STATUS_INVALID_LUN
);
1644 if (DeviceExtension
->DevicePresent
[Srb
->TargetId
] == FALSE
)
1646 Srb
->SrbStatus
= SRB_STATUS_NO_DEVICE
;
1647 return(SRB_STATUS_NO_DEVICE
);
1650 DPRINT("AtapiSendAtapiCommand(): TargetId: %lu\n",
1653 if (Srb
->Cdb
[0] == SCSIOP_INQUIRY
)
1654 return(AtapiInquiry(DeviceExtension
,
1657 /* Set pointer to data buffer. */
1658 DeviceExtension
->DataBuffer
= (PUSHORT
)Srb
->DataBuffer
;
1659 DeviceExtension
->CurrentSrb
= Srb
;
1661 /* Wait for BUSY to clear */
1662 for (Retries
= 0; Retries
< IDE_MAX_BUSY_RETRIES
; Retries
++)
1664 Status
= IDEReadStatus(DeviceExtension
->CommandPortBase
);
1665 if (!(Status
& IDE_SR_BUSY
))
1669 ScsiPortStallExecution(10);
1671 DPRINT("status=%02x\n", Status
);
1672 DPRINT("waited %ld usecs for busy to clear\n", Retries
* 10);
1673 if (Retries
>= IDE_MAX_BUSY_RETRIES
)
1675 DPRINT("Drive is BUSY for too long\n");
1676 return(SRB_STATUS_BUSY
);
1679 /* Select the desired drive */
1680 IDEWriteDriveHead(DeviceExtension
->CommandPortBase
,
1681 IDE_DH_FIXED
| (Srb
->TargetId
? IDE_DH_DRV1
: 0));
1683 /* Wait a little while */
1684 ScsiPortStallExecution(50);
1687 /* Wait for BUSY to clear and DRDY to assert */
1688 for (Retries
= 0; Retries
< IDE_MAX_BUSY_RETRIES
; Retries
++)
1690 Status
= IDEReadStatus(DeviceExtension
->CommandPortBase
);
1691 if (!(Status
& IDE_SR_BUSY
) && (Status
& IDE_SR_DRDY
))
1695 ScsiPortStallExecution(10);
1697 DPRINT("waited %ld usecs for busy to clear after drive select\n", Retries
* 10);
1698 if (Retries
>= IDE_MAX_BUSY_RETRIES
)
1700 DPRINT("Drive is BUSY for too long after drive select\n");
1701 return(SRB_STATUS_BUSY
);
1705 if (Srb
->DataTransferLength
< 0x10000)
1707 ByteCountLow
= (UCHAR
)(Srb
->DataTransferLength
& 0xFF);
1708 ByteCountHigh
= (UCHAR
)(Srb
->DataTransferLength
>> 8);
1712 ByteCountLow
= 0xFF;
1713 ByteCountHigh
= 0xFF;
1716 /* Set feature register */
1717 IDEWritePrecomp(DeviceExtension
->CommandPortBase
, 0);
1719 /* Set command packet length */
1720 IDEWriteCylinderHigh(DeviceExtension
->CommandPortBase
, ByteCountHigh
);
1721 IDEWriteCylinderLow(DeviceExtension
->CommandPortBase
, ByteCountLow
);
1723 /* Issue command to drive */
1724 IDEWriteCommand(DeviceExtension
->CommandPortBase
, 0xA0); /* Packet command */
1726 /* Wait for DRQ to assert */
1727 for (Retries
= 0; Retries
< IDE_MAX_BUSY_RETRIES
; Retries
++)
1729 Status
= IDEReadStatus(DeviceExtension
->CommandPortBase
);
1730 if ((Status
& IDE_SR_DRQ
))
1734 ScsiPortStallExecution(10);
1737 CdbSize
= (DeviceExtension
->DeviceParams
[Srb
->TargetId
].ConfigBits
& 0x3 == 1) ? 16 : 12;
1738 DPRINT("CdbSize: %lu\n", CdbSize
);
1740 /* Write command packet */
1741 IDEWriteBlock(DeviceExtension
->CommandPortBase
,
1745 DeviceExtension
->ExpectingInterrupt
= TRUE
;
1747 DPRINT("AtapiSendAtapiCommand() done\n");
1749 return(SRB_STATUS_PENDING
);
1754 AtapiSendIdeCommand(IN PATAPI_MINIPORT_EXTENSION DeviceExtension
,
1755 IN PSCSI_REQUEST_BLOCK Srb
)
1757 ULONG SrbStatus
= SRB_STATUS_SUCCESS
;
1759 DPRINT("AtapiSendIdeCommand() called!\n");
1761 DPRINT("PathId: %lu TargetId: %lu Lun: %lu\n",
1766 switch (Srb
->Cdb
[0])
1768 case SCSIOP_INQUIRY
:
1769 SrbStatus
= AtapiInquiry(DeviceExtension
,
1773 case SCSIOP_READ_CAPACITY
:
1774 SrbStatus
= AtapiReadCapacity(DeviceExtension
,
1780 SrbStatus
= AtapiReadWrite(DeviceExtension
,
1784 case SCSIOP_MODE_SENSE
:
1785 case SCSIOP_TEST_UNIT_READY
:
1787 case SCSIOP_START_STOP_UNIT
:
1788 case SCSIOP_REQUEST_SENSE
:
1792 DbgPrint("AtapiSendIdeCommand():unknown command %x\n",
1794 SrbStatus
= SRB_STATUS_INVALID_REQUEST
;
1798 DPRINT("AtapiSendIdeCommand() done!\n");
1805 AtapiInquiry(PATAPI_MINIPORT_EXTENSION DeviceExtension
,
1806 PSCSI_REQUEST_BLOCK Srb
)
1808 PIDE_DRIVE_IDENTIFY DeviceParams
;
1809 PINQUIRYDATA InquiryData
;
1812 DPRINT("SCSIOP_INQUIRY: DeviceExtension %p TargetId: %lu\n",
1813 DeviceExtension
, Srb
->TargetId
);
1815 if (Srb
->PathId
!= 0)
1817 Srb
->SrbStatus
= SRB_STATUS_INVALID_PATH_ID
;
1818 return(SRB_STATUS_INVALID_PATH_ID
);
1821 if (Srb
->TargetId
> 1)
1823 Srb
->SrbStatus
= SRB_STATUS_INVALID_TARGET_ID
;
1824 return(SRB_STATUS_INVALID_TARGET_ID
);
1829 Srb
->SrbStatus
= SRB_STATUS_INVALID_LUN
;
1830 return(SRB_STATUS_INVALID_LUN
);
1833 if (DeviceExtension
->DevicePresent
[Srb
->TargetId
] == FALSE
)
1835 Srb
->SrbStatus
= SRB_STATUS_NO_DEVICE
;
1836 return(SRB_STATUS_NO_DEVICE
);
1839 InquiryData
= Srb
->DataBuffer
;
1840 DeviceParams
= &DeviceExtension
->DeviceParams
[Srb
->TargetId
];
1843 for (i
= 0; i
< Srb
->DataTransferLength
; i
++)
1845 ((PUCHAR
)Srb
->DataBuffer
)[i
] = 0;
1848 /* set device class */
1849 if (DeviceExtension
->DeviceAtapi
[Srb
->TargetId
] == FALSE
)
1852 InquiryData
->DeviceType
= DIRECT_ACCESS_DEVICE
;
1856 /* get it from the ATAPI configuration word */
1857 InquiryData
->DeviceType
= (DeviceParams
->ConfigBits
>> 8) & 0x1F;
1858 DPRINT("Device class: %u\n", InquiryData
->DeviceType
);
1861 DPRINT("ConfigBits: 0x%x\n", DeviceParams
->ConfigBits
);
1862 if (DeviceParams
->ConfigBits
& 0x80)
1864 DPRINT("Removable media!\n");
1865 InquiryData
->RemovableMedia
= 1;
1868 for (i
= 0; i
< 20; i
+= 2)
1870 InquiryData
->VendorId
[i
] =
1871 ((PUCHAR
)DeviceParams
->ModelNumber
)[i
];
1872 InquiryData
->VendorId
[i
+1] =
1873 ((PUCHAR
)DeviceParams
->ModelNumber
)[i
+1];
1876 for (i
= 0; i
< 4; i
++)
1878 InquiryData
->ProductId
[12+i
] = ' ';
1881 for (i
= 0; i
< 4; i
+= 2)
1883 InquiryData
->ProductRevisionLevel
[i
] =
1884 ((PUCHAR
)DeviceParams
->FirmwareRev
)[i
];
1885 InquiryData
->ProductRevisionLevel
[i
+1] =
1886 ((PUCHAR
)DeviceParams
->FirmwareRev
)[i
+1];
1889 DPRINT("VendorId: '%.20s'\n", InquiryData
->VendorId
);
1891 Srb
->SrbStatus
= SRB_STATUS_SUCCESS
;
1892 return(SRB_STATUS_SUCCESS
);
1897 AtapiReadCapacity(PATAPI_MINIPORT_EXTENSION DeviceExtension
,
1898 PSCSI_REQUEST_BLOCK Srb
)
1900 PREAD_CAPACITY_DATA CapacityData
;
1901 PIDE_DRIVE_IDENTIFY DeviceParams
;
1904 DPRINT("SCSIOP_READ_CAPACITY: TargetId: %lu\n", Srb
->TargetId
);
1906 if (Srb
->PathId
!= 0)
1908 Srb
->SrbStatus
= SRB_STATUS_INVALID_PATH_ID
;
1909 return(SRB_STATUS_INVALID_PATH_ID
);
1912 if (Srb
->TargetId
> 1)
1914 Srb
->SrbStatus
= SRB_STATUS_INVALID_TARGET_ID
;
1915 return(SRB_STATUS_INVALID_TARGET_ID
);
1920 Srb
->SrbStatus
= SRB_STATUS_INVALID_LUN
;
1921 return(SRB_STATUS_INVALID_LUN
);
1924 if (DeviceExtension
->DevicePresent
[Srb
->TargetId
] == FALSE
)
1926 Srb
->SrbStatus
= SRB_STATUS_NO_DEVICE
;
1927 return(SRB_STATUS_NO_DEVICE
);
1930 CapacityData
= (PREAD_CAPACITY_DATA
)Srb
->DataBuffer
;
1931 DeviceParams
= &DeviceExtension
->DeviceParams
[Srb
->TargetId
];
1933 /* Set sector (block) size to 512 bytes (big-endian). */
1934 CapacityData
->BytesPerBlock
= 0x20000;
1936 /* Calculate last sector (big-endian). */
1937 if (DeviceParams
->Capabilities
& IDE_DRID_LBA_SUPPORTED
)
1939 LastSector
= (ULONG
)((DeviceParams
->TMSectorCountHi
<< 16) +
1940 DeviceParams
->TMSectorCountLo
) - 1;
1944 LastSector
= (ULONG
)(DeviceParams
->LogicalCyls
*
1945 DeviceParams
->LogicalHeads
*
1946 DeviceParams
->SectorsPerTrack
)-1;
1949 CapacityData
->LogicalBlockAddress
= (((PUCHAR
)&LastSector
)[0] << 24) |
1950 (((PUCHAR
)&LastSector
)[1] << 16) |
1951 (((PUCHAR
)&LastSector
)[2] << 8) |
1952 ((PUCHAR
)&LastSector
)[3];
1954 DPRINT("LastCount: %lu (%08lx / %08lx)\n",
1957 CapacityData
->LogicalBlockAddress
);
1959 Srb
->SrbStatus
= SRB_STATUS_SUCCESS
;
1960 return(SRB_STATUS_SUCCESS
);
1965 AtapiReadWrite(PATAPI_MINIPORT_EXTENSION DeviceExtension
,
1966 PSCSI_REQUEST_BLOCK Srb
)
1968 PIDE_DRIVE_IDENTIFY DeviceParams
;
1969 ULONG StartingSector
;
1979 DPRINT("AtapiReadWrite() called!\n");
1981 if (Srb
->PathId
!= 0)
1983 Srb
->SrbStatus
= SRB_STATUS_INVALID_PATH_ID
;
1984 return(SRB_STATUS_INVALID_PATH_ID
);
1987 if (Srb
->TargetId
> 1)
1989 Srb
->SrbStatus
= SRB_STATUS_INVALID_TARGET_ID
;
1990 return(SRB_STATUS_INVALID_TARGET_ID
);
1995 Srb
->SrbStatus
= SRB_STATUS_INVALID_LUN
;
1996 return(SRB_STATUS_INVALID_LUN
);
1999 if (DeviceExtension
->DevicePresent
[Srb
->TargetId
] == FALSE
)
2001 Srb
->SrbStatus
= SRB_STATUS_NO_DEVICE
;
2002 return(SRB_STATUS_NO_DEVICE
);
2005 DPRINT("SCSIOP_WRITE: TargetId: %lu\n",
2008 DeviceParams
= &DeviceExtension
->DeviceParams
[Srb
->TargetId
];
2010 /* Get starting sector number from CDB. */
2011 StartingSector
= ((PCDB
)Srb
->Cdb
)->CDB10
.LogicalBlockByte3
|
2012 ((PCDB
)Srb
->Cdb
)->CDB10
.LogicalBlockByte2
<< 8 |
2013 ((PCDB
)Srb
->Cdb
)->CDB10
.LogicalBlockByte1
<< 16 |
2014 ((PCDB
)Srb
->Cdb
)->CDB10
.LogicalBlockByte0
<< 24;
2016 SectorCount
= (Srb
->DataTransferLength
+ DeviceParams
->BytesPerSector
- 1) /
2017 DeviceParams
->BytesPerSector
;
2019 DPRINT("Starting sector %lu Number of bytes %lu Sectors %lu\n",
2021 Srb
->DataTransferLength
,
2024 if (DeviceParams
->Capabilities
& IDE_DRID_LBA_SUPPORTED
)
2026 SectorNumber
= StartingSector
& 0xff;
2027 CylinderLow
= (StartingSector
>> 8) & 0xff;
2028 CylinderHigh
= (StartingSector
>> 16) & 0xff;
2029 DrvHead
= ((StartingSector
>> 24) & 0x0f) |
2030 (Srb
->TargetId
? IDE_DH_DRV1
: 0) |
2035 SectorNumber
= (StartingSector
% DeviceParams
->SectorsPerTrack
) + 1;
2036 StartingSector
/= DeviceParams
->SectorsPerTrack
;
2037 DrvHead
= (StartingSector
% DeviceParams
->LogicalHeads
) |
2038 (Srb
->TargetId
? IDE_DH_DRV1
: 0);
2039 StartingSector
/= DeviceParams
->LogicalHeads
;
2040 CylinderLow
= StartingSector
& 0xff;
2041 CylinderHigh
= StartingSector
>> 8;
2045 if (Srb
->SrbFlags
& SRB_FLAGS_DATA_IN
)
2047 Command
= DeviceExtension
->MultiSectorCommand
[Srb
->TargetId
] ? IDE_CMD_READ_MULTIPLE
: IDE_CMD_READ
;
2051 Command
= DeviceExtension
->MultiSectorCommand
[Srb
->TargetId
] ? IDE_CMD_WRITE_MULTIPLE
: IDE_CMD_WRITE
;
2054 if (DrvHead
& IDE_DH_LBA
)
2056 DPRINT("%s:BUS=%04x:DRV=%d:LBA=1:BLK=%08d:SC=%02x:CM=%02x\n",
2057 (Srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) ? "READ" : "WRITE",
2058 DeviceExtension
->CommandPortBase
,
2059 DrvHead
& IDE_DH_DRV1
? 1 : 0,
2060 ((DrvHead
& 0x0f) << 24) +
2061 (CylinderHigh
<< 16) + (CylinderLow
<< 8) + SectorNumber
,
2067 DPRINT("%s:BUS=%04x:DRV=%d:LBA=0:CH=%02x:CL=%02x:HD=%01x:SN=%02x:SC=%02x:CM=%02x\n",
2068 (Srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) ? "READ" : "WRITE",
2069 DeviceExtension
->CommandPortBase
,
2070 DrvHead
& IDE_DH_DRV1
? 1 : 0,
2079 /* Set pointer to data buffer. */
2080 DeviceExtension
->DataBuffer
= (PUSHORT
)Srb
->DataBuffer
;
2082 DeviceExtension
->CurrentSrb
= Srb
;
2084 /* wait for BUSY to clear */
2085 for (Retries
= 0; Retries
< IDE_MAX_BUSY_RETRIES
; Retries
++)
2087 Status
= IDEReadStatus(DeviceExtension
->CommandPortBase
);
2088 if (!(Status
& IDE_SR_BUSY
))
2092 ScsiPortStallExecution(10);
2094 DPRINT("status=%02x\n", Status
);
2095 DPRINT("waited %ld usecs for busy to clear\n", Retries
* 10);
2096 if (Retries
>= IDE_MAX_BUSY_RETRIES
)
2098 DPRINT ("Drive is BUSY for too long\n");
2099 return(SRB_STATUS_BUSY
);
2101 if (++ControllerExtension
->Retries
> IDE_MAX_CMD_RETRIES
)
2103 DbgPrint ("Max Retries on Drive reset reached, returning failure\n");
2104 Irp
= ControllerExtension
->CurrentIrp
;
2105 Irp
->IoStatus
.Status
= STATUS_DISK_OPERATION_FAILED
;
2106 Irp
->IoStatus
.Information
= 0;
2112 DPRINT ("Beginning drive reset sequence\n");
2113 IDEBeginControllerReset(ControllerExtension
);
2120 /* Select the desired drive */
2121 IDEWriteDriveHead(DeviceExtension
->CommandPortBase
,
2122 IDE_DH_FIXED
| DrvHead
);
2124 ScsiPortStallExecution(10);
2126 /* wait for BUSY to clear and DRDY to assert */
2127 for (Retries
= 0; Retries
< IDE_MAX_BUSY_RETRIES
; Retries
++)
2129 Status
= IDEReadStatus(DeviceExtension
->CommandPortBase
);
2130 if (!(Status
& IDE_SR_BUSY
) && (Status
& IDE_SR_DRDY
))
2134 ScsiPortStallExecution(10);
2136 DPRINT("waited %ld usecs for busy to clear after drive select\n", Retries
* 10);
2137 if (Retries
>= IDE_MAX_BUSY_RETRIES
)
2139 DPRINT("Drive is BUSY for too long after drive select\n");
2140 return(SRB_STATUS_BUSY
);
2142 if (ControllerExtension
->Retries
++ > IDE_MAX_CMD_RETRIES
)
2144 DbgPrint ("Max Retries on Drive reset reached, returning failure\n");
2145 Irp
= ControllerExtension
->CurrentIrp
;
2146 Irp
->IoStatus
.Status
= STATUS_DISK_OPERATION_FAILED
;
2147 Irp
->IoStatus
.Information
= 0;
2153 DPRINT("Beginning drive reset sequence\n");
2154 IDEBeginControllerReset(ControllerExtension
);
2162 /* Setup command parameters */
2163 IDEWritePrecomp(DeviceExtension
->CommandPortBase
, 0);
2164 IDEWriteSectorCount(DeviceExtension
->CommandPortBase
, SectorCount
);
2165 IDEWriteSectorNum(DeviceExtension
->CommandPortBase
, SectorNumber
);
2166 IDEWriteCylinderHigh(DeviceExtension
->CommandPortBase
, CylinderHigh
);
2167 IDEWriteCylinderLow(DeviceExtension
->CommandPortBase
, CylinderLow
);
2168 IDEWriteDriveHead(DeviceExtension
->CommandPortBase
, IDE_DH_FIXED
| DrvHead
);
2170 /* Issue command to drive */
2171 IDEWriteCommand(DeviceExtension
->CommandPortBase
, Command
);
2173 /* Write data block */
2174 if (Srb
->SrbFlags
& SRB_FLAGS_DATA_OUT
)
2176 PUCHAR TargetAddress
;
2179 /* Wait for controller ready */
2180 for (Retries
= 0; Retries
< IDE_MAX_WRITE_RETRIES
; Retries
++)
2182 BYTE Status
= IDEReadStatus(DeviceExtension
->CommandPortBase
);
2183 if (!(Status
& IDE_SR_BUSY
) || (Status
& IDE_SR_ERR
))
2187 KeStallExecutionProcessor(10);
2189 if (Retries
>= IDE_MAX_WRITE_RETRIES
)
2191 DPRINT1("Drive is BUSY for too long after sending write command\n");
2192 return(SRB_STATUS_BUSY
);
2194 if (DeviceExtension
->Retries
++ > IDE_MAX_CMD_RETRIES
)
2196 Irp
= ControllerExtension
->CurrentIrp
;
2197 Irp
->IoStatus
.Status
= STATUS_DISK_OPERATION_FAILED
;
2198 Irp
->IoStatus
.Information
= 0;
2204 IDEBeginControllerReset(ControllerExtension
);
2211 /* Update SRB data */
2212 TransferSize
= DeviceExtension
->TransferSize
[Srb
->TargetId
];
2213 if (Srb
->DataTransferLength
< TransferSize
)
2215 TransferSize
= Srb
->DataTransferLength
;
2218 TargetAddress
= Srb
->DataBuffer
;
2219 Srb
->DataBuffer
+= TransferSize
;
2220 Srb
->DataTransferLength
-= TransferSize
;
2222 /* Write data block */
2223 if (DeviceExtension
->DWordIo
[Srb
->TargetId
])
2225 IDEWriteBlock32(DeviceExtension
->CommandPortBase
,
2231 IDEWriteBlock(DeviceExtension
->CommandPortBase
,
2236 /* Indicate expecting an interrupt. */
2237 DeviceExtension
->ExpectingInterrupt
= TRUE
;
2239 DPRINT("AtapiReadWrite() done!\n");
2241 /* Wait for interrupt. */
2242 return(SRB_STATUS_PENDING
);
2247 AtapiErrorToScsi(PVOID DeviceExtension
,
2248 PSCSI_REQUEST_BLOCK Srb
)
2250 PATAPI_MINIPORT_EXTENSION DevExt
;
2251 ULONG CommandPortBase
;
2252 ULONG ControlPortBase
;
2257 DPRINT("AtapiErrorToScsi() called\n");
2259 DevExt
= (PATAPI_MINIPORT_EXTENSION
)DeviceExtension
;
2261 CommandPortBase
= DevExt
->CommandPortBase
;
2262 ControlPortBase
= DevExt
->ControlPortBase
;
2264 ErrorReg
= IDEReadError(CommandPortBase
);
2266 if (DevExt
->DeviceAtapi
[Srb
->TargetId
])
2268 switch (ErrorReg
>> 4)
2270 case SCSI_SENSE_NO_SENSE
:
2271 DPRINT("ATAPI error: SCSI_SENSE_NO_SENSE\n");
2272 ScsiStatus
= SCSISTAT_CHECK_CONDITION
;
2273 SrbStatus
= SRB_STATUS_ERROR
;
2276 case SCSI_SENSE_RECOVERED_ERROR
:
2277 DPRINT("ATAPI error: SCSI_SENSE_RECOVERED_SENSE\n");
2279 SrbStatus
= SRB_STATUS_SUCCESS
;
2282 case SCSI_SENSE_NOT_READY
:
2283 DPRINT("ATAPI error: SCSI_SENSE_NOT_READY\n");
2284 ScsiStatus
= SCSISTAT_CHECK_CONDITION
;
2285 SrbStatus
= SRB_STATUS_ERROR
;
2288 case SCSI_SENSE_MEDIUM_ERROR
:
2289 DPRINT("ATAPI error: SCSI_SENSE_MEDIUM_ERROR\n");
2290 ScsiStatus
= SCSISTAT_CHECK_CONDITION
;
2291 SrbStatus
= SRB_STATUS_ERROR
;
2294 case SCSI_SENSE_HARDWARE_ERROR
:
2295 DPRINT("ATAPI error: SCSI_SENSE_HARDWARE_ERROR\n");
2296 ScsiStatus
= SCSISTAT_CHECK_CONDITION
;
2297 SrbStatus
= SRB_STATUS_ERROR
;
2300 case SCSI_SENSE_ILLEGAL_REQUEST
:
2301 DPRINT("ATAPI error: SCSI_SENSE_ILLEGAL_REQUEST\n");
2302 ScsiStatus
= SCSISTAT_CHECK_CONDITION
;
2303 SrbStatus
= SRB_STATUS_ERROR
;
2306 case SCSI_SENSE_UNIT_ATTENTION
:
2307 DPRINT("ATAPI error: SCSI_SENSE_UNIT_ATTENTION\n");
2308 ScsiStatus
= SCSISTAT_CHECK_CONDITION
;
2309 SrbStatus
= SRB_STATUS_ERROR
;
2312 case SCSI_SENSE_DATA_PROTECT
:
2313 DPRINT("ATAPI error: SCSI_SENSE_DATA_PROTECT\n");
2314 ScsiStatus
= SCSISTAT_CHECK_CONDITION
;
2315 SrbStatus
= SRB_STATUS_ERROR
;
2318 case SCSI_SENSE_BLANK_CHECK
:
2319 DPRINT("ATAPI error: SCSI_SENSE_BLANK_CHECK\n");
2320 ScsiStatus
= SCSISTAT_CHECK_CONDITION
;
2321 SrbStatus
= SRB_STATUS_ERROR
;
2324 case SCSI_SENSE_ABORTED_COMMAND
:
2325 DPRINT("ATAPI error: SCSI_SENSE_ABORTED_COMMAND\n");
2326 ScsiStatus
= SCSISTAT_CHECK_CONDITION
;
2327 SrbStatus
= SRB_STATUS_ERROR
;
2331 DPRINT("ATAPI error: Invalid sense key\n");
2333 SrbStatus
= SRB_STATUS_ERROR
;
2339 DPRINT1("IDE error: %02x\n", ErrorReg
);
2342 SrbStatus
= SRB_STATUS_ERROR
;
2345 UCHAR SectorCount
, SectorNum
, CylinderLow
, CylinderHigh
;
2348 CylinderLow
= IDEReadCylinderLow(CommandPortBase
);
2349 CylinderHigh
= IDEReadCylinderHigh(CommandPortBase
);
2350 DriveHead
= IDEReadDriveHead(CommandPortBase
);
2351 SectorCount
= IDEReadSectorCount(CommandPortBase
);
2352 SectorNum
= IDEReadSectorNum(CommandPortBase
);
2354 DPRINT1("IDE Error: ERR:%02x CYLLO:%02x CYLHI:%02x SCNT:%02x SNUM:%02x\n",
2365 Srb
->ScsiStatus
= ScsiStatus
;
2367 DPRINT("AtapiErrorToScsi() done\n");