* Sync with UniATA v0.42e2.
* Hello AHCI support, you've been missed ! (that's WIP but still)
svn path=/trunk/; revision=57018
/*++
-Copyright (c) 2002-2011 Alexandr A. Telyatnikov (Alter)
+Copyright (c) 2002-2012 Alexandr A. Telyatnikov (Alter)
Module Name:
atapi.h
#define PRINT_PREFIX
// Note, that using DbgPrint on raised IRQL will crash w2k
-// tis will not happen immediately, so we shall see some logs
+// ttis will not happen immediately, so we shall see some logs
//#define LOG_ON_RAISED_IRQL_W2K TRUE
//#define LOG_ON_RAISED_IRQL_W2K FALSE
#define DFLAGS_REINIT_DMA 0x4000 //
#define DFLAGS_HIDDEN 0x8000 // Hidden device, available only with special IOCTLs
// via communication virtual device
+#define DFLAGS_MANUAL_CHS 0x10000 // For devices those have no IDENTIFY commands
//#define DFLAGS_ 0x10000 //
//
// Used to disable 'advanced' features.
// IDE command definitions
//
+#define IDE_COMMAND_DATA_SET_MGMT 0x06 // TRIM
#define IDE_COMMAND_ATAPI_RESET 0x08
#define IDE_COMMAND_RECALIBRATE 0x10
#define IDE_COMMAND_READ 0x20
#define IDE_STATUS_IDLE 0x50
#define IDE_STATUS_BUSY 0x80
+#define IDE_STATUS_WRONG 0xff
+#define IDE_STATUS_MASK 0xff
+
//
// IDE drive select/head definitions
USHORT CurrentMultiSector:8; // 59
USHORT CurrentMultiSectorValid:1;
- USHORT Reserved59_9:7;
+ USHORT Reserved59_9_11:3;
+ USHORT SanitizeSupported:1;
+ USHORT CryptoScrambleExtSupported:1;
+ USHORT OverwriteExtSupported:1;
+ USHORT BlockEraseExtSupported:1;
ULONG UserAddressableSectors; // 60-61
USHORT MinimumPIOCycleTime; // 67
USHORT MinimumPIOCycleTimeIORDY; // 68
- USHORT Reserved69_70[2]; // 69-70
+ USHORT Reserved69_0_4:5; // 69
+ USHORT ReadZeroAfterTrim:1;
+ USHORT Lba28Support:1;
+ USHORT Reserved69_7_IEEE1667:1;
+ USHORT MicrocodeDownloadDMA:1;
+ USHORT MaxPwdDMA:1;
+ USHORT WriteBufferDMA:1;
+ USHORT ReadBufferDMA:1;
+ USHORT DevConfigDMA:1;
+ USHORT LongSectorErrorReporting:1;
+ USHORT DeterministicReadAfterTrim:1;
+ USHORT CFastSupport:1;
+
+ USHORT Reserved70; // 70
USHORT ReleaseTimeOverlapped; // 71
USHORT ReleaseTimeServiceCommand; // 72
USHORT Reserved73_74[2]; // 73-74
#define ATA_SATA_GEN3 0x0008
#define ATA_SUPPORT_NCQ 0x0100
#define ATA_SUPPORT_IFPWRMNGTRCV 0x0200
+#define ATA_SUPPORT_PHY_EVENT_COUNTER 0x0400
+#define ATA_SUPPORT_NCQ_UNLOAD 0x0800
+#define ATA_SUPPORT_NCQ_PRI_INFO 0x1000
USHORT Reserved77; // 77
USHORT MajorRevision; // 80
USHORT MinorRevision; // 81
+#define ATA_VER_MJ_ATA4 0x0010
+#define ATA_VER_MJ_ATA5 0x0020
+#define ATA_VER_MJ_ATA6 0x0040
+#define ATA_VER_MJ_ATA7 0x0080
+#define ATA_VER_MJ_ATA8_ASC 0x0100
+
struct {
USHORT Smart:1; // 82/85
USHORT Security:1;
ULONGLONG UserAddressableSectors48; // 100-103
- USHORT Reserved104[2]; // 104-105
+ USHORT StreamingTransferTimePIO; // 104
+ USHORT MaxLBARangeDescBlockCount; // 105 // in 512b blocks
union {
USHORT PhysLogSectorSize; // 106
struct {
USHORT PLSS_Signature:2; // = 0x01 = 01b
};
};
- USHORT Reserved107[10]; // 107-116
+ USHORT InterSeekDelay; // 107
+ USHORT WorldWideName[4]; // 108-111
+ USHORT Reserved112[5]; // 112-116
ULONG LargeSectorSize; // 117-118
- USHORT Reserved117[8]; // 119-126
+ USHORT Reserved119[8]; // 119-126
USHORT RemovableStatus; // 127
USHORT SecurityStatus; // 128
- USHORT FeaturesSupport4; // 129
- USHORT Reserved130[30]; // 130-159
+ USHORT Reserved129[31]; // 129-159
USHORT CfAdvPowerMode; // 160
- USHORT Reserved161[14]; // 161-175
+ USHORT Reserved161[7]; // 161-167
+ USHORT DeviceNominalFormFactor:4; // 168
+ USHORT Reserved168_4_15:12;
+ USHORT DataSetManagementSupported:1; // 169
+ USHORT Reserved169_1_15:15;
+ USHORT AdditionalProdNum[4]; // 170-173
+ USHORT Reserved174[2]; // 174-175
USHORT MediaSerial[30]; // 176-205
- USHORT Reserved206[49]; // 205-254
- USHORT Integrity; // 255
+ union {
+ USHORT SCT; // 206
+ struct {
+ USHORT SCT_Supported:1;
+ USHORT Reserved:1;
+ USHORT SCT_WriteSame:1;
+ USHORT SCT_ErrorRecovery:1;
+ USHORT SCT_Feature:1;
+ USHORT SCT_DataTables:1;
+ USHORT Reserved_6_15:10;
+ };
+ };
+ USHORT Reserved_CE_ATA[2]; // 207-208
+ USHORT LogicalSectorOffset:14; // 209
+ USHORT Reserved209_14_One:1;
+ USHORT Reserved209_15_Zero:1;
+
+ USHORT WriteReadVerify_CountMode2[2]; // 210-211
+ USHORT WriteReadVerify_CountMode3[2]; // 212-213
+
+ USHORT NVCache_PM_Supported:1; // 214
+ USHORT NVCache_PM_Enabled:1;
+ USHORT NVCache_Reserved_2_3:2;
+ USHORT NVCache_Enabled:1;
+ USHORT NVCache_Reserved_5_7:3;
+ USHORT NVCache_PM_Version:4;
+ USHORT NVCache_Version:4;
+
+ USHORT NVCache_Size_LogicalBlocks[2]; // 215-216
+ USHORT NominalMediaRotationRate; // 217
+ USHORT Reserved218; // 218
+ USHORT NVCache_DeviceSpinUpTime:8; // 219
+ USHORT NVCache_Reserved219_8_15:8;
+
+ USHORT WriteReadVerify_CurrentMode:8; // 220
+ USHORT WriteReadVerify_Reserved220_8_15:8;
+
+ USHORT Reserved221; // 221
+ union {
+ struct {
+ USHORT VersionFlags:12;
+ USHORT TransportType:4;
+ };
+ struct {
+ USHORT ATA8_APT:1;
+ USHORT ATA_ATAPI7:1;
+ USHORT Reserved:14;
+ } PATA;
+ struct {
+ USHORT ATA8_AST:1;
+ USHORT v10a:1;
+ USHORT II_Ext:1;
+ USHORT v25:1;
+ USHORT v26:1;
+ USHORT v30:1;
+ USHORT Reserved:10;
+ } SATA;
+ } TransportMajor;
+ USHORT TransportMinor; // 223
+
+ USHORT Reserved224[10]; // 224-233
+
+ USHORT MinBlocks_MicrocodeDownload_Mode3; // 234
+ USHORT MaxBlocks_MicrocodeDownload_Mode3; // 235
+
+ USHORT Reserved236[19]; // 236-254
+
+ union {
+ USHORT Integrity; // 255
+ struct {
+ USHORT ChecksumValid:8;
+ USHORT Checksum:8;
+ };
+ };
} IDENTIFY_DATA, *PIDENTIFY_DATA;
//
#define IDENTIFY_DATA_SIZE sizeof(IDENTIFY_DATA)
+
// IDENTIFY DMA timing cycle modes.
#define IDENTIFY_DMA_CYCLES_MODE_0 0x00
#define IDENTIFY_DMA_CYCLES_MODE_1 0x01
#define IDENTIFY_DMA_CYCLES_MODE_2 0x02
+
+// for IDE_COMMAND_DATA_SET_MGMT
+typedef struct _TRIM_DATA {
+ ULONGLONG Lba:48;
+ ULONGLONG BlockCount:16;
+} TRIM_DATA, *PTRIM_DATA;
+
/*
#define PCI_DEV_HW_SPEC(idhi, idlo) \
{ #idlo, 4, #idhi, 4}
IN ULONG c
);
+extern VOID
+UniataExpectChannelInterrupt(
+ IN struct _HW_CHANNEL* chan,
+ IN BOOLEAN Expecting
+ );
+
#define CHAN_NOT_SPECIFIED (0xffffffffL)
#define CHAN_NOT_SPECIFIED_CHECK_CABLE (0xfffffffeL)
#define DEVNUM_NOT_SPECIFIED (0xffffffffL)
ULONGLONG lba
);
-BOOLEAN
+ULONG
NTAPI
UniataAnybodyHome(
IN PVOID HwDeviceExtension,
IN ULONG deviceNumber
);
+#define ATA_AT_HOME_HDD 0x01
+#define ATA_AT_HOME_ATAPI 0x02
+#define ATA_AT_HOME_XXX 0x04
+#define ATA_AT_HOME_NOBODY 0x00
+
#define ATA_CMD_FLAG_LBAIOsupp 0x01
#define ATA_CMD_FLAG_48supp 0x02
#define ATA_CMD_FLAG_48 0x04
#define ATA_CMD_FLAG_DMA 0x08
+#define ATA_CMD_FLAG_FUA 0x10
+#define ATA_CMD_FLAG_In 0x40
+#define ATA_CMD_FLAG_Out 0x80
extern UCHAR AtaCommands48[256];
extern UCHAR AtaCommandFlags[256];
( ((AtaCommandFlags[command] & ATA_CMD_FLAG_LBAIOsupp) && (supp48) && (((lba+count) >= ATA_MAX_IOLBA28) || (count > 256)) ) || \
(lba > ATA_MAX_LBA28) || (count > 255) )
+#define UniAtaClearAtaReq(AtaReq) \
+{ \
+ RtlZeroMemory((PCHAR)(AtaReq), FIELD_OFFSET(ATA_REQ, ata)); \
+}
+
+
+//#define ATAPI_DEVICE(de, ldev) (de->lun[ldev].DeviceFlags & DFLAGS_ATAPI_DEVICE)
+#define ATAPI_DEVICE(chan, dev) ((chan->lun[dev]->DeviceFlags & DFLAGS_ATAPI_DEVICE) ? TRUE : FALSE)
+
#ifdef _DEBUG
#define PrintNtConsole _PrintNtConsole
#else //_DEBUG
/*++
-Copyright (c) 2002-2011 Alexandr A. Telyatnikov (Alter)
+Copyright (c) 2002-2012 Alexandr A. Telyatnikov (Alter)
Module Name:
bm_devs.h
#ifndef __IDE_BUSMASTER_DEVICES_H__
#define __IDE_BUSMASTER_DEVICES_H__
+#ifdef USER_MODE
+#define PVEN_STR PCSTR
+#else // USER_MODE
+#define PVEN_STR PCHAR
+#endif // USER_MODE
+
typedef struct _BUSMASTER_CONTROLLER_INFORMATION {
- PCHAR VendorId;
+ PVEN_STR VendorId;
ULONG VendorIdLength;
ULONG nVendorId;
- PCHAR DeviceId;
+ PVEN_STR DeviceId;
ULONG DeviceIdLength;
ULONG nDeviceId;
ULONG nRevId;
#ifdef USER_MODE
#define PCI_DEV_HW_SPEC_BM(idhi, idlo, rev, mode, name, flags) \
- { #idlo, 4, 0x##idlo, #idhi, 4, 0x##idhi, rev, mode, name, flags}
+ { (PVEN_STR) #idlo, 4, 0x##idlo, (PVEN_STR) #idhi, 4, 0x##idhi, rev, mode, name, flags}
#else
#define PCI_DEV_HW_SPEC_BM(idhi, idlo, rev, mode, name, flags) \
- { (PCHAR) #idlo, 4, 0x##idlo, (PCHAR) #idhi, 4, 0x##idhi, rev, mode, NULL, flags}
+ { (PVEN_STR) #idlo, 4, 0x##idlo, (PVEN_STR) #idhi, 4, 0x##idhi, rev, mode, NULL, flags}
#endif
#define BMLIST_TERMINATOR (0xffffffffL)
/*++
-Copyright (c) 2002-2011 Alexandr A. Telyatnikov (Alter)
+Copyright (c) 2002-2012 Alexandr A. Telyatnikov (Alter)
Module Name:
bsmaster.h
// HBA Capabilities
struct {
ULONG NOP:5; // number of ports
- ULONG Reserved5_7:1;
+ ULONG SXS:1; // Supports External SATA
+ ULONG EMS:1; // Enclosure Management Supported
+ ULONG CCCS:1; // Command Completion Coalescing Supported
ULONG NCS:5; // number of command slots
ULONG PSC:1; // partial state capable
ULONG SSC:1; // slumber state capable
ULONG PMD:1; // PIO multiple DRQ block
- ULONG Reserved16:1;
+ ULONG FBSS:1; // FIS-based Switching Supported
ULONG SPM:1; // port multiplier
ULONG SAM:1; // AHCI mode only
ULONG SALP:1; // aggressive link power management
ULONG SSS:1; // staggered spin-up
ULONG SIS:1; // interlock switch
- ULONG Reserved29:1;
+ ULONG SSNTF:1; // Supports SNotification Register
ULONG SNCQ:1; // native command queue
ULONG S64A:1; // 64bit addr
} CAP;
#define AHCI_GHC_AE 0x80000000
// Interrupt status (bit mask)
- ULONG IS;
+ ULONG IS; // 0x08
// Ports implemented (bit mask)
- ULONG PI;
+ ULONG PI; // 0x0c
// AHCI Version
- ULONG VS;
- ULONG Reserved[3];
-
- UCHAR Reserved2[0x80];
+ ULONG VS; // 0x10
+
+ ULONG CCC_CTL; // 0x14
+ ULONG CCC_PORTS; // 0x18
+ ULONG EM_LOC; // 0x1c
+ ULONG EM_CTL; // 0x20
+
+ // Extended HBA Capabilities
+ struct { // 0x24
+ ULONG BOH:1; // BIOS/OS Handoff
+ ULONG NVMP:1; // NVMHCI Present
+ ULONG APST:1; // Automatic Partial to Slumber Transitions
+ ULONG Reserved:29;
+ } CAP2;
+
+#define AHCI_CAP2_BOH 0x00000001
+#define AHCI_CAP2_NVMP 0x00000002
+#define AHCI_CAP2_APST 0x00000004
+
+ // BIOS/OS Handoff Control and Status
+ struct { // 0x28
+ ULONG BB:1; // BIOS Busy
+ ULONG OOC:1; // OS Ownership Change
+ ULONG SOOE:1; // SMI on OS Ownership Change Enable
+ ULONG OOS:1; // OS Owned Semaphore
+ ULONG BOS:1; // BIOS Owned Semaphore
+ ULONG Reserved:27;
+ } BOHC;
+
+ UCHAR Reserved2[0x74];
UCHAR VendorSpec[0x60];
} IDE_AHCI_REGISTERS, *PIDE_AHCI_REGISTERS;
#define IDX_AHCI_IS (FIELD_OFFSET(IDE_AHCI_REGISTERS, IS))
#define IDX_AHCI_VS (FIELD_OFFSET(IDE_AHCI_REGISTERS, VS))
#define IDX_AHCI_PI (FIELD_OFFSET(IDE_AHCI_REGISTERS, PI))
+#define IDX_AHCI_CAP2 (FIELD_OFFSET(IDE_AHCI_REGISTERS, CAP2))
+#define IDX_AHCI_BOHC (FIELD_OFFSET(IDE_AHCI_REGISTERS, BOHC))
typedef union _SATA_SSTATUS_REG {
};
} SNTF; // 0x100 + 0x80*c + 0x003c
- ULONG FIS_Switching_Reserved[12];
+ // AHCI 1.2
+ union {
+ ULONG Reg;
+ struct {
+ ULONG EN:1; // Enable
+ ULONG DEC:1; // Device Error Clear
+ ULONG SDE:1; // Single Device Error
+ ULONG Reserved_3_7:5; // Reserved
+ ULONG DEV:4; // Device To Issue
+ ULONG ADO:4; // Active Device Optimization (recommended parallelism)
+ ULONG DWE:4; // Device With Error
+ ULONG Reserved_20_31:12; // Reserved
+ };
+ } FBS; // 0x100 + 0x80*c + 0x0040
+
+ ULONG Reserved_44_7f[11];
UCHAR VendorSpec[16];
} IDE_AHCI_PORT_REGISTERS, *PIDE_AHCI_PORT_REGISTERS;
};
ULONG Reserved1;
- ULONG DBC:22;
- ULONG Reserved2:9;
- ULONG I:1;
+ union {
+ struct {
+ ULONG DBC:22;
+ ULONG Reserved2:9;
+ ULONG I:1;
+ };
+ ULONG DBC_ULONG;
+ };
} IDE_AHCI_PRD_ENTRY, *PIDE_AHCI_PRD_ENTRY;
#define AHCI_FIS_TYPE_ATA_H2D 0x27
#define AHCI_FIS_TYPE_ATA_D2H 0x34
+#define AHCI_FIS_TYPE_DMA_D2H 0x39
+#define AHCI_FIS_TYPE_DMA_BiDi 0x41
+#define AHCI_FIS_TYPE_DATA_BiDi 0x46
+#define AHCI_FIS_TYPE_BIST_BiDi 0x58
+#define AHCI_FIS_TYPE_PIO_D2H 0x5f
+#define AHCI_FIS_TYPE_DEV_BITS_D2H 0xA1
+
+typedef struct _AHCI_ATA_H2D_FIS {
+ UCHAR FIS_Type; // = 0x27
+ UCHAR Reserved1:7;
+ UCHAR Cmd:1; // update Command register
+ UCHAR Command; // [2]
+ UCHAR Feature; // [3]
+
+ UCHAR BlockNumber; // [4]
+ UCHAR CylinderLow; // [5]
+ UCHAR CylinderHigh; // [6]
+ UCHAR DriveSelect; // [7]
+
+ UCHAR BlockNumberExp; // [8]
+ UCHAR CylinderLowExp; // [9]
+ UCHAR CylinderHighExp; // [10]
+ UCHAR FeatureExp; // [11]
+
+ UCHAR BlockCount; // [12]
+ UCHAR BlockCountExp; // [13]
+ UCHAR Reserved14; // [14]
+ UCHAR Control; // [15]
+
+} AHCI_ATA_H2D_FIS, *PAHCI_ATA_H2D_FIS;
+
+#define IDX_AHCI_o_Command (FIELD_OFFSET(AHCI_ATA_H2D_FIS, Command))
+#define IDX_AHCI_o_Feature (FIELD_OFFSET(AHCI_ATA_H2D_FIS, Feature))
+#define IDX_AHCI_o_BlockNumber (FIELD_OFFSET(AHCI_ATA_H2D_FIS, BlockNumber ))
+#define IDX_AHCI_o_CylinderLow (FIELD_OFFSET(AHCI_ATA_H2D_FIS, CylinderLow ))
+#define IDX_AHCI_o_CylinderHigh (FIELD_OFFSET(AHCI_ATA_H2D_FIS, CylinderHigh))
+#define IDX_AHCI_o_DriveSelect (FIELD_OFFSET(AHCI_ATA_H2D_FIS, DriveSelect ))
+#define IDX_AHCI_o_BlockCount (FIELD_OFFSET(AHCI_ATA_H2D_FIS, BlockCount))
+#define IDX_AHCI_o_Control (FIELD_OFFSET(AHCI_ATA_H2D_FIS, Control))
+#define IDX_AHCI_o_FeatureExp (FIELD_OFFSET(AHCI_ATA_H2D_FIS, FeatureExp))
+#define IDX_AHCI_o_BlockNumberExp (FIELD_OFFSET(AHCI_ATA_H2D_FIS, BlockNumberExp ))
+#define IDX_AHCI_o_CylinderLowExp (FIELD_OFFSET(AHCI_ATA_H2D_FIS, CylinderLowExp ))
+#define IDX_AHCI_o_CylinderHighExp (FIELD_OFFSET(AHCI_ATA_H2D_FIS, CylinderHighExp))
+#define IDX_AHCI_o_BlockCountExp (FIELD_OFFSET(AHCI_ATA_H2D_FIS, BlockCountExp))
#define AHCI_FIS_COMM_PM (0x80 | AHCI_DEV_SEL_PM)
/* 128-byte aligned */
typedef struct _IDE_AHCI_CMD {
UCHAR cfis[64];
- UCHAR acmd[32];
- UCHAR Reserved[32];
+ UCHAR acmd[16];
+ UCHAR Reserved[48];
IDE_AHCI_PRD_ENTRY prd_tab[ATA_AHCI_DMA_ENTRIES]; // also 128-byte aligned
} IDE_AHCI_CMD, *PIDE_AHCI_CMD;
typedef struct _IDE_AHCI_RCV_FIS {
UCHAR dsfis[28];
UCHAR Reserved1[4];
- UCHAR psfis[24];
- UCHAR Reserved2[8];
- UCHAR rfis[24];
+ UCHAR psfis[20];
+ UCHAR Reserved2[12];
+ UCHAR rfis[20];
UCHAR Reserved3[4];
- ULONG SDBFIS;
+ UCHAR SDBFIS[8];
UCHAR ufis[64];
UCHAR Reserved4[96];
} IDE_AHCI_RCV_FIS, *PIDE_AHCI_RCV_FIS;
typedef struct _IDE_AHCI_CHANNEL_CTL_BLOCK {
IDE_AHCI_CMD_LIST cmd_list[ATA_AHCI_MAX_TAGS]; // 1K-size (32*32)
IDE_AHCI_RCV_FIS rcv_fis;
- IDE_AHCI_CMD cmd; // for single internal comamnds w/o associated AtaReq
+ IDE_AHCI_CMD cmd; // for single internal commands w/o associated AtaReq
} IDE_AHCI_CHANNEL_CTL_BLOCK, *PIDE_AHCI_CHANNEL_CTL_BLOCK;
ULONG in_bcount;
ULONG in_status;
USHORT io_cmd_flags; // out
-
+ UCHAR in_error;
} ahci;
};
};
#define REQ_STATE_EXPECTING_INTR 0x40
#define REQ_STATE_ATAPI_EXPECTING_CMD_INTR 0x41
#define REQ_STATE_ATAPI_EXPECTING_DATA_INTR 0x42
-#define REQ_STATE_ATAPI_DO_NOTHING_INTR 0x43
+#define REQ_STATE_ATAPI_EXPECTING_DATA_INTR2 0x43
+#define REQ_STATE_ATAPI_DO_NOTHING_INTR 0x44
#define REQ_STATE_EARLY_INTR 0x48
struct _HW_LU_EXTENSION;
typedef struct _IORES {
- ULONG Addr; /* Base address*/
+ union {
+ ULONG Addr; /* Base address*/
+ PVOID pAddr; /* Base address in pointer form */
+ };
ULONG MemIo:1; /* Memory mapping (1) vs IO ports (0) */
- ULONG Proc:1; /* Need special process via IO_Proc */
+ ULONG Proc:1; /* Need special processing via IO_Proc */
ULONG Reserved:30;
} IORES, *PIORES;
//BOOLEAN MemIo;
BOOLEAN AltRegMap;
- //UCHAR Reserved[3];
+ UCHAR Reserved[3];
MECHANICAL_STATUS_INFORMATION_HEADER MechStatusData;
SENSE_DATA MechStatusSense;
PIDE_AHCI_CHANNEL_CTL_BLOCK AhciCtlBlock; // 128-byte aligned
ULONGLONG AHCI_CTL_PhAddr;
IORES BaseIoAHCI_Port;
+ ULONG AhciPrevCI;
+ ULONG AhciCompleteCI;
+ ULONG AhciLastIS;
//PVOID AHCI_FIS; // is not actually used by UniATA now, but is required by AHCI controller
//ULONGLONG AHCI_FIS_PhAddr;
// Note: in contrast to FBSD, we keep PRD and CMD item in AtaReq structure
+ PATA_REQ AhciInternalAtaReq;
+ PSCSI_REQUEST_BLOCK AhciInternalSrb;
#ifdef QUEUE_STATISTICS
LONGLONG QueueStat[MAX_QUEUE_STAT];
ULONG last_write;
ULONG LunSelectWaitCount;
+ ULONG AtapiReadyWaitDelay;
// tuning options
ULONG opt_GeomType;
ULONG ActiveDpcChan;
ULONG FirstDpcChan;
+ ULONG ExpectingInterrupt; // Indicates entire controller expecting an interrupt
/*
PHW_TIMER HwScsiTimer1;
PHW_TIMER HwScsiTimer2;
INTERFACE_TYPE AdapterInterfaceType;
ULONG MaximumDmaTransferLength;
ULONG AlignmentMask;
+ ULONG DmaSegmentLength;
+ ULONG DmaSegmentAlignmentMask; // must be PAGE-aligned
//ULONG BaseMemAddress;
//PIDE_SATA_REGISTERS BaseIoAddressSATA_0;
- IORES BaseIoAddressSATA_0;
+ IORES BaseIoAddressSATA_0;
//PIDE_SATA_REGISTERS BaseIoAddressSATA[IDE_MAX_CHAN];
- IORES BaseIoAHCI_0;
+ IORES BaseIoAHCI_0;
//PIDE_AHCI_PORT_REGISTERS BaseIoAHCIPort[AHCI_MAX_PORT];
- ULONG AHCI_CAP;
+ ULONG AHCI_CAP;
+ PATA_REQ AhciInternalAtaReq0;
+ PSCSI_REQUEST_BLOCK AhciInternalSrb0;
BOOLEAN opt_AtapiDmaZeroTransfer; // default FALSE
BOOLEAN opt_AtapiDmaControlCmd; // default FALSE
#define UNIATA_ALLOCATE_NEW_LUNS 0x00
-extern BOOLEAN
-NTAPI
+extern BOOLEAN NTAPI
UniataAllocateLunExt(
PHW_DEVICE_EXTENSION deviceExtension,
ULONG NewNumberChannels
);
+extern VOID NTAPI
+UniataFreeLunExt(
+ PHW_DEVICE_EXTENSION deviceExtension
+ );
+
extern ULONG NTAPI
UniataFindBusMasterController(
IN PVOID HwDeviceExtension,
SetPciConfig4(offs, a); \
}
+#define DMA_MODE_NONE 0x00
+#define DMA_MODE_BM 0x01
+#define DMA_MODE_AHCI 0x02
+
#ifndef GetDmaStatus
#define GetDmaStatus(de, c) \
- (((de)->BusMaster) ? AtapiReadPort1(&((de)->chan[c]), IDX_BM_Status) : 0)
+ (((de)->BusMaster == DMA_MODE_BM) ? AtapiReadPort1(&((de)->chan[c]), IDX_BM_Status) : 0)
#endif //GetDmaStatus
#ifdef USE_OWN_DMA
extern ULONG SkipRaids;
extern ULONG ForceSimplex;
extern BOOLEAN g_opt_AtapiDmaRawRead;
+extern BOOLEAN hasPCI;
extern BOOLEAN InDriverEntry;
#define DEF_U64(x) (x##ULL)
#define DEF_I64(x) (x##LL)
+ /* ReactOS-specific defines */
+
#ifndef DDKAPI
- #define DDKAPI __attribute__((stdcall))
+ #define DDKAPI __attribute__((stdcall))
#endif
-
#ifndef DDKCDECLAPI
- #define DDKCDECLAPI __attribute__((cdecl))
+ #define DDKCDECLAPI __attribute__((cdecl))
#endif
-
#ifndef DDKFASTAPI
- #define DDKFASTAPI __attribute__((fastcall))
+ #define DDKFASTAPI __attribute__((fastcall))
#endif
#define DECLSPEC_NAKED __attribute__((naked))
#define DEF_U64(x) (x##UI64)
#define DEF_I64(x) (x##I64)
+ /* ReactOS-specific defines */
+
#ifndef DDKAPI
- #define DDKAPI __stdcall
+ #define DDKAPI __stdcall
#endif
-
#ifndef DDKCDECLAPI
- #define DDKCDECLAPI _cdecl
+ #define DDKCDECLAPI _cdecl
#endif
-
#ifndef DDKFASTAPI
- #define DDKFASTAPI __fastcall
+ #define DDKFASTAPI __fastcall
#endif
#define DECLSPEC_NAKED __declspec(naked)
/*++
-Copyright (c) 2002-2011 Alexandr A. Telyatnikov (Alter)
+Copyright (c) 2002-2012 Alexandr A. Telyatnikov (Alter)
Module Name:
id_ata.cpp
ULONG g_opt_WaitBusyCount = 200; // 20000
ULONG g_opt_WaitBusyDelay = 10; // 150
ULONG g_opt_WaitDrqDelay = 10; // 100
-BOOLEAN g_opt_AtapiSendDisableIntr = 1; // 0
+ULONG g_opt_WaitBusyLongCount = 2000; // 2000
+ULONG g_opt_WaitBusyLongDelay = 250; // 250
+ULONG g_opt_MaxIsrWait = 40; //
+BOOLEAN g_opt_AtapiSendDisableIntr = 0; // 0
BOOLEAN g_opt_AtapiDmaRawRead = 1; // 0
+BOOLEAN hasPCI = FALSE;
ULONG g_opt_VirtualMachine = 0; // Auto
{
ULONG i;
UCHAR Status;
- for (i=0; i<200; i++) {
+
+ for (i=0; i<g_opt_WaitBusyCount; i++) {
GetStatus(chan, Status);
if (Status & IDE_STATUS_BUSY) {
- AtapiStallExecution(10);
+ AtapiStallExecution(g_opt_WaitBusyDelay);
continue;
} else {
break;
Status = WaitOnBusy(chan);
if(!(Status & IDE_STATUS_BUSY))
return Status;
- for (i=0; i<2000; i++) {
+ for (i=0; i<g_opt_WaitBusyLongCount; i++) {
GetStatus(chan, Status);
if (Status & IDE_STATUS_BUSY) {
- AtapiStallExecution(250);
+ AtapiStallExecution(g_opt_WaitBusyLongDelay);
continue;
} else {
break;
)
{
ULONG i;
- UCHAR Status = 0xff;
+ UCHAR Status = IDE_STATUS_WRONG;
for (i=0; i<g_opt_WaitBusyCount; i++) {
GetBaseStatus(chan, Status);
if (Status & IDE_STATUS_BUSY) {
{
UCHAR Status2;
- if(Status == 0xff) {
- return 0xff;
+ if(Status == IDE_STATUS_WRONG) {
+ return IDE_STATUS_WRONG;
}
if(Status & IDE_STATUS_BUSY) {
return Status;
for (i=0; i<20000; i++) {
GetStatus(chan, Status);
Status2 = UniataIsIdle(chan->DeviceExtension, Status);
- if(Status2 == 0xff) {
+ if(Status2 == IDE_STATUS_WRONG) {
// no drive ?
break;
} else
GetBaseStatus(chan, statusByte2);
KdPrint2((PRINT_PREFIX " statusByte2 %x:\n", statusByte2));
SelectDrive(chan, DeviceNumber);
- AtapiStallExecution(500);
- AtapiWritePort1(chan, IDX_IO1_o_Command, IDE_COMMAND_ATAPI_RESET);
-
- // ReactOS modification: Already stop looping when we know that the drive has finished resetting.
- // Not all controllers clear the IDE_STATUS_BUSY flag (e.g. not the VMware one), so ensure that
- // the maximum waiting time (30 * i = 0.9 seconds) does not exceed the one of the original
- // implementation. (which is around 1 second)
- while ((AtapiReadPort1(chan, IDX_IO1_i_Status) & IDE_STATUS_BUSY) &&
- i--)
- {
- AtapiStallExecution(30);
+ if(chan->lun[DeviceNumber]->DeviceFlags & DFLAGS_MANUAL_CHS) {
+ // For ESDI/MFM
+ AtapiStallExecution(10000);
+ for (i = 0; i < 1000; i++) {
+ AtapiStallExecution(999);
+ }
+ } else {
+ AtapiStallExecution(500);
+ AtapiWritePort1(chan, IDX_IO1_o_Command, IDE_COMMAND_ATAPI_RESET);
+
+ // ReactOS modification: Already stop looping when we know that the drive has finished resetting.
+ // Not all controllers clear the IDE_STATUS_BUSY flag (e.g. not the VMware one), so ensure that
+ // the maximum waiting time (30 * i = 0.9 seconds) does not exceed the one of the original
+ // implementation. (which is around 1 second)
+ while ((AtapiReadPort1(chan, IDX_IO1_i_Status) & IDE_STATUS_BUSY) &&
+ i--)
+ {
+ AtapiStallExecution(30);
+ }
}
SelectDrive(chan, DeviceNumber);
IN ULONGLONG lba,
IN USHORT count,
IN USHORT feature,
- IN ULONG flags
+ IN ULONG wait_flags
)
{
PHW_CHANNEL chan = &deviceExtension->chan[lChannel];
deviceExtension->DevIndex, deviceExtension->Channel, DeviceNumber, command, lba, count, feature ));
if(deviceExtension->HwFlags & UNIATA_AHCI) {
- PIDE_AHCI_CMD AHCI_CMD = &(chan->AhciCtlBlock->cmd);
+ //PIDE_AHCI_CMD AHCI_CMD = &(chan->AhciCtlBlock->cmd);
KdPrint3((" (ahci)\n"));
- RtlZeroMemory(AHCI_CMD->cfis, sizeof(AHCI_CMD->cfis));
+ statusByte = UniataAhciSendPIOCommand(deviceExtension, lChannel, DeviceNumber,
+ (PSCSI_REQUEST_BLOCK)NULL,
+ NULL,
+ 0,
+ command,
+ lba, count,
+ feature,
+ 0 /* ahci flags */ ,
+ wait_flags,
+ 1000 /* timeout 1 sec */
+ );
- if(!UniataAhciSetupFIS_H2D(deviceExtension, DeviceNumber, lChannel,
- &(AHCI_CMD->cfis[0]),
- command,
- lba,
- count,
- feature,
- ATA_IMMEDIATE
- )) {
- return 0xff;
- }
- if(UniataAhciSendCommand(deviceExtension, lChannel, DeviceNumber, 0, 3000) == 0xff) {
- KdPrint2((" timeout\n"));
- return 0xff;
- }
- return IDE_STATUS_IDLE;
+ return statusByte;
}
SelectDrive(chan, DeviceNumber);
// and not cleared after SELECT
//>>>>>> NV: 2006/08/03
- if((AtaCommandFlags[command] & ATA_CMD_FLAG_LBAIOsupp) &&
+ if(((AtaCommandFlags[command] & (ATA_CMD_FLAG_LBAIOsupp|ATA_CMD_FLAG_FUA)) == ATA_CMD_FLAG_LBAIOsupp) &&
CheckIfBadBlock(chan->lun[DeviceNumber], lba, count)) {
KdPrint3((PRINT_PREFIX ": artificial bad block, lba %#I64x count %#x\n", lba, count));
return IDE_STATUS_ERROR;
// write command code to device
AtapiWritePort1(chan, IDX_IO1_o_Command, command);
- switch (flags) {
+ switch (wait_flags) {
case ATA_WAIT_INTR:
// caller requested wait for interrupt
GetStatus(chan, statusByte);
statusByte = UniataIsIdle(deviceExtension, statusByte);
- if(statusByte == 0xff) {
+ if(statusByte == IDE_STATUS_WRONG) {
// no drive ?
break;
} else
KdPrint2((PRINT_PREFIX " try to continue\n"));
statusByte &= ~IDE_STATUS_ERROR;
}
- chan->ExpectingInterrupt = TRUE;
+ UniataExpectChannelInterrupt(chan, TRUE);
// !!!!!
InterlockedExchange(&(chan->CheckIntr),
CHECK_INTR_IDLE);
IN UCHAR sector,
IN UCHAR count,
IN UCHAR feature,
- IN ULONG flags
+ IN ULONG wait_flags
)
{
if(!(deviceExtension->HwFlags & UNIATA_AHCI)) {
return AtaCommand48(deviceExtension, DeviceNumber, lChannel,
command,
(ULONG)sector | ((ULONG)cylinder << 8) | ((ULONG)(head & 0x0f) << 24),
- count, feature, flags);
+ count, feature, wait_flags);
} else {
- PHW_CHANNEL chan = &deviceExtension->chan[lChannel];
- PIDE_AHCI_CMD AHCI_CMD = &(chan->AhciCtlBlock->cmd);
+ return UniataAhciSendPIOCommand(deviceExtension, lChannel, DeviceNumber,
+ (PSCSI_REQUEST_BLOCK)NULL,
+ NULL,
+ 0,
+ command,
+ (ULONG)sector | ((ULONG)cylinder << 8) | ((ULONG)(head & 0x0f) << 24),
+ count,
+ feature,
+ 0 /* ahci flags */ ,
+ wait_flags,
+ 1000 /* timeout 1 sec */
+ );
- KdPrint3(("AtaCommand(ahci)\n"));
-
- RtlZeroMemory(AHCI_CMD->cfis, sizeof(AHCI_CMD->cfis));
-
- if(!UniataAhciSetupFIS_H2D(deviceExtension, DeviceNumber, lChannel,
- &(AHCI_CMD->cfis[0]),
- command,
- (ULONG)sector | ((ULONG)cylinder << 8) | ((ULONG)(head & 0x0f) << 24),
- count,
- feature,
- ATA_IMMEDIATE
- )) {
- return 0xff;
- }
- if(UniataAhciSendCommand(deviceExtension, lChannel, DeviceNumber, 0, 3000) == 0xff) {
- KdPrint2((" timeout\n"));
- return 0xff;
- }
- return IDE_STATUS_IDLE;
}
} // end AtaCommand()
return 1;
if (ident->PioCycleTimingMode == 0)
return 0;
- return -1;
+ return IOMODE_NOT_SPECIFIED;
} // end AtaPioMode()
LONG
return 1;
if (ident->MultiWordDMASupport & 0x01)
return 0;
- return -1;
+ return IOMODE_NOT_SPECIFIED;
} // end AtaWmode()
LONG
AtaUmode(PIDENTIFY_DATA2 ident)
{
if (!ident->UdmaModesValid)
- return -1;
+ return IOMODE_NOT_SPECIFIED;
if (ident->UltraDMASupport & 0x40)
return 6;
if (ident->UltraDMASupport & 0x20)
return 1;
if (ident->UltraDMASupport & 0x01)
return 0;
- return -1;
+ return IOMODE_NOT_SPECIFIED;
} // end AtaUmode()
#endif //UNIATA_CORE
+#if DBG
VOID
NTAPI
UniataDumpATARegs(
}
return;
} // end UniataDumpATARegs()
+#endif
/*++
UCHAR signatureLow,
signatureHigh;
BOOLEAN atapiDev = FALSE;
+ BOOLEAN use_ahci = FALSE;
PHW_LU_EXTENSION LunExt = chan->lun[DeviceNumber];
+ use_ahci = UniataIsSATARangeAvailable(deviceExtension, lChannel) &&
+ (deviceExtension->HwFlags & UNIATA_AHCI);
+
if(chan->ChannelCtrlFlags & CTRFLAGS_AHCI_PM) {
if(chan->PmLunMap & (1 << DeviceNumber)) {
// OK
return FALSE;
}
- if(deviceExtension->HwFlags & UNIATA_AHCI) {
+ if(use_ahci) {
statusByte = WaitOnBusyLong(chan);
+#if DBG
+ if(!chan->AhciInternalAtaReq) {
+ KdPrint2((PRINT_PREFIX "!AhciInternalAtaReq\n"));
+ }
+#endif
} else {
SelectDrive(chan, DeviceNumber);
AtapiStallExecution(10);
statusByte = WaitOnBusyLong(chan);
// Check that the status register makes sense.
GetBaseStatus(chan, statusByte2);
-
- UniataDumpATARegs(chan);
}
if (Command == IDE_COMMAND_IDENTIFY) {
// Wait for Busy to drop.
AtapiStallExecution(100);
GetStatus(chan, statusByte);
+ if(statusByte == IDE_STATUS_WRONG) {
+ KdPrint2((PRINT_PREFIX "IssueIdentify: IDE_STATUS_WRONG (dev %d)\n", DeviceNumber));
+ return FALSE;
+ }
} while ((statusByte & IDE_STATUS_BUSY) && waitCount--);
GetBaseStatus(chan, statusByte2);
}
} else {
KdPrint2((PRINT_PREFIX "IssueIdentify: Checking for ATAPI. Status (%#x)\n", statusByte));
+ if(statusByte == IDE_STATUS_WRONG) {
+ return FALSE;
+ }
//if(!(deviceExtension->HwFlags & UNIATA_SATA)) {
if(!UniataIsSATARangeAvailable(deviceExtension, lChannel)) {
statusByte = WaitForIdleLong(chan);
}
// if(deviceExtension->HwFlags & UNIATA_SATA) {
+ if(use_ahci) {
+ statusByte = UniataAhciSendPIOCommand(HwDeviceExtension, lChannel, DeviceNumber,
+ (PSCSI_REQUEST_BLOCK)NULL,
+ (PUCHAR)(&deviceExtension->FullIdentifyData),
+ DEV_BSIZE,
+ Command,
+ 0, 0,
+ 0,
+ 0 /* ahci flags */ ,
+ ATA_WAIT_INTR,
+ 1000 /* timeout 1 sec */
+ );
+ j = 9; // AHCI is rather different, skip loop at all
+ } else
+ if(LunExt->DeviceFlags & DFLAGS_MANUAL_CHS) {
+ j = 9; // don't send IDENTIFY, assume it is not supported
+ KdPrint2((PRINT_PREFIX "IssueIdentify: Manual CHS\n"));
+ RtlZeroMemory(&(deviceExtension->FullIdentifyData), sizeof(deviceExtension->FullIdentifyData));
+ RtlCopyMemory(&(deviceExtension->FullIdentifyData), &(LunExt->IdentifyData), sizeof(LunExt->IdentifyData));
+ } else
if(UniataIsSATARangeAvailable(deviceExtension, lChannel)) {
j = 4; // skip old-style checks
} else {
}
for (; j < 4*2; j++) {
// Send IDENTIFY command.
- statusByte = AtaCommand(deviceExtension, DeviceNumber, lChannel, Command, 0, 0, 0, (j >= 4) ? 0x200 : 0, 0, ATA_WAIT_INTR);
+
+ // Load CylinderHigh and CylinderLow with number bytes to transfer for old devices, use 0 for newer.
+ statusByte = AtaCommand(deviceExtension, DeviceNumber, lChannel, Command, (j < 4) ? DEV_BSIZE : 0 /* cyl */, 0, 0, 0, 0, ATA_WAIT_INTR);
// Clear interrupt
if (statusByte & IDE_STATUS_DRQ) {
return FALSE;
}
- KdPrint2((PRINT_PREFIX "IssueIdentify: Status before read words %#x\n", statusByte));
- // Suck out 256 words. After waiting for one model that asserts busy
- // after receiving the Packet Identify command.
- statusByte = WaitForDrq(chan);
- statusByte = WaitOnBusyLong(chan);
- KdPrint2((PRINT_PREFIX "IssueIdentify: statusByte %#x\n", statusByte));
+ if(use_ahci) {
+ // everything should already be done by controller
+ } else
+ if(LunExt->DeviceFlags & DFLAGS_MANUAL_CHS) {
+ j = 9; // don't send IDENTIFY, assume it is not supported
+ KdPrint2((PRINT_PREFIX "IssueIdentify: Manual CHS (2)\n"));
+ statusByte = WaitForDrq(chan);
+ statusByte = WaitOnBusyLong(chan);
+ KdPrint2((PRINT_PREFIX "IssueIdentify: statusByte %#x\n", statusByte));
+ GetBaseStatus(chan, statusByte);
+ } else {
- if (!(statusByte & IDE_STATUS_DRQ)) {
- KdPrint2((PRINT_PREFIX "IssueIdentify: !IDE_STATUS_DRQ (2) (%#x)\n", statusByte));
+ KdPrint2((PRINT_PREFIX "IssueIdentify: Status before read words %#x\n", statusByte));
+ // Suck out 256 words. After waiting for one model that asserts busy
+ // after receiving the Packet Identify command.
+ statusByte = WaitForDrq(chan);
+ statusByte = WaitOnBusyLong(chan);
+ KdPrint2((PRINT_PREFIX "IssueIdentify: statusByte %#x\n", statusByte));
+
+ if (!(statusByte & IDE_STATUS_DRQ)) {
+ KdPrint2((PRINT_PREFIX "IssueIdentify: !IDE_STATUS_DRQ (2) (%#x)\n", statusByte));
+ GetBaseStatus(chan, statusByte);
+ return FALSE;
+ }
GetBaseStatus(chan, statusByte);
- return FALSE;
- }
- GetBaseStatus(chan, statusByte);
- KdPrint2((PRINT_PREFIX "IssueIdentify: BASE statusByte %#x\n", statusByte));
+ KdPrint2((PRINT_PREFIX "IssueIdentify: BASE statusByte %#x\n", statusByte));
- if (atapiDev || !(LunExt->DeviceFlags & DFLAGS_DWORDIO_ENABLED) /*!deviceExtension->DWordIO*/) {
+ if (atapiDev || !(LunExt->DeviceFlags & DFLAGS_DWORDIO_ENABLED) /*!deviceExtension->DWordIO*/) {
- KdPrint2((PRINT_PREFIX " use 16bit IO\n"));
+ KdPrint2((PRINT_PREFIX " use 16bit IO\n"));
#if 0
- USHORT w;
- ULONG i;
- // ATI/SII chipsets with memory-mapped IO hangs when
- // I call ReadBuffer(), probably due to PCI burst/prefetch enabled
- // Unfortunately, I don't know yet how to workaround it except the way you see below.
- KdPrint2((PRINT_PREFIX
- " IO_%#x (%#x), %s:\n",
- IDX_IO1_i_Data,
- chan->RegTranslation[IDX_IO1_i_Data].Addr,
- chan->RegTranslation[IDX_IO1_i_Data].MemIo ? "Mem" : "IO"));
- for(i=0; i<256; i++) {
-/*
+ USHORT w;
+ ULONG i;
+ // ATI/SII chipsets with memory-mapped IO hangs when
+ // I call ReadBuffer(), probably due to PCI burst/prefetch enabled
+ // Unfortunately, I don't know yet how to workaround it except the way you see below.
KdPrint2((PRINT_PREFIX
- " IO_%#x (%#x):\n",
+ " IO_%#x (%#x), %s:\n",
IDX_IO1_i_Data,
- chan->RegTranslation[IDX_IO1_i_Data].Addr));
-*/
- w = AtapiReadPort2(chan, IDX_IO1_i_Data);
- KdPrint2((PRINT_PREFIX
- " %x\n", w));
- AtapiStallExecution(1);
- ((PUSHORT)&deviceExtension->FullIdentifyData)[i] = w;
- }
+ chan->RegTranslation[IDX_IO1_i_Data].Addr,
+ chan->RegTranslation[IDX_IO1_i_Data].MemIo ? "Mem" : "IO"));
+ for(i=0; i<256; i++) {
+ /*
+ KdPrint2((PRINT_PREFIX
+ " IO_%#x (%#x):\n",
+ IDX_IO1_i_Data,
+ chan->RegTranslation[IDX_IO1_i_Data].Addr));
+ */
+ w = AtapiReadPort2(chan, IDX_IO1_i_Data);
+ KdPrint2((PRINT_PREFIX
+ " %x\n", w));
+ AtapiStallExecution(1);
+ ((PUSHORT)&deviceExtension->FullIdentifyData)[i] = w;
+ }
#else
- ReadBuffer(chan, (PUSHORT)&deviceExtension->FullIdentifyData, 256, PIO0_TIMING);
+ ReadBuffer(chan, (PUSHORT)&deviceExtension->FullIdentifyData, 256, PIO0_TIMING);
#endif
- // Work around for some IDE and one model Atapi that will present more than
- // 256 bytes for the Identify data.
- KdPrint2((PRINT_PREFIX "IssueIdentify: suck data port\n", statusByte));
- statusByte = AtapiSuckPort2(chan);
- } else {
- KdPrint2((PRINT_PREFIX " use 32bit IO\n"));
- ReadBuffer2(chan, (PUSHORT)&deviceExtension->FullIdentifyData, 256/2, PIO0_TIMING);
- }
-
- KdPrint2((PRINT_PREFIX "IssueIdentify: statusByte %#x\n", statusByte));
- statusByte = WaitForDrq(chan);
- KdPrint2((PRINT_PREFIX "IssueIdentify: statusByte %#x\n", statusByte));
- GetBaseStatus(chan, statusByte);
+ // Work around for some IDE and one model Atapi that will present more than
+ // 256 bytes for the Identify data.
+ KdPrint2((PRINT_PREFIX "IssueIdentify: suck data port\n", statusByte));
+ statusByte = AtapiSuckPort2(chan);
+ } else {
+ KdPrint2((PRINT_PREFIX " use 32bit IO\n"));
+ ReadBuffer2(chan, (PULONG)&deviceExtension->FullIdentifyData, 256/2, PIO0_TIMING);
+ }
+ KdPrint2((PRINT_PREFIX "IssueIdentify: statusByte %#x\n", statusByte));
+ statusByte = WaitForDrq(chan);
+ KdPrint2((PRINT_PREFIX "IssueIdentify: statusByte %#x\n", statusByte));
+ GetBaseStatus(chan, statusByte);
+ }
KdPrint2((PRINT_PREFIX "IssueIdentify: Status after read words %#x\n", statusByte));
if(NoSetup) {
KdPrint2((PRINT_PREFIX "UDMA: %x\n", deviceExtension->FullIdentifyData.UltraDMAActive));
}
KdPrint2((PRINT_PREFIX "SATA: %x\n", deviceExtension->FullIdentifyData.SataEnable));
+ KdPrint2((PRINT_PREFIX "SATA support: %x, CAPs %#x\n",
+ deviceExtension->FullIdentifyData.SataSupport,
+ deviceExtension->FullIdentifyData.SataCapabilities));
// Check out a few capabilities / limitations of the device.
if (deviceExtension->FullIdentifyData.RemovableStatus & 1) {
deviceExtension->FullIdentifyData.RemovableStatus));
LunExt->DeviceFlags |= DFLAGS_REMOVABLE_DRIVE;
}
+ if(use_ahci) {
+ // AHCI doesn't recommend using PIO and multiblock
+ LunExt->MaximumBlockXfer = 0;
+ } else
if (deviceExtension->FullIdentifyData.MaximumBlockTransfer) {
// Determine max. block transfer for this device.
LunExt->MaximumBlockXfer =
IDE_COMMAND_READ_NATIVE_SIZE48, 0, 0, 0, ATA_WAIT_READY);
if(!(statusByte & IDE_STATUS_ERROR)) {
- NativeNumOfSectors = (ULONG)AtapiReadPort1(chan, IDX_IO1_i_BlockNumber) |
- ((ULONG)AtapiReadPort1(chan, IDX_IO1_i_CylinderLow) << 8) |
- ((ULONG)AtapiReadPort1(chan, IDX_IO1_i_CylinderHigh) << 16) ;
-
- AtapiWritePort1(chan, IDX_IO2_o_Control,
- IDE_DC_USE_HOB );
-
- KdPrint2((PRINT_PREFIX "Read high order bytes\n"));
- NativeNumOfSectors |=
- ((ULONG)AtapiReadPort1(chan, IDX_IO1_i_BlockNumber) << 24 );
- hNativeNumOfSectors=
- (ULONG)AtapiReadPort1(chan, IDX_IO1_i_CylinderLow) |
- ((ULONG)AtapiReadPort1(chan, IDX_IO1_i_CylinderHigh) << 8) ;
- ((PULONG)&NativeNumOfSectors)[1] = hNativeNumOfSectors;
-
+ if(use_ahci) {
+ NativeNumOfSectors = chan->AhciInternalAtaReq->ahci.in_lba;
+ } else {
+ NativeNumOfSectors = (ULONG)AtapiReadPort1(chan, IDX_IO1_i_BlockNumber) |
+ ((ULONG)AtapiReadPort1(chan, IDX_IO1_i_CylinderLow) << 8) |
+ ((ULONG)AtapiReadPort1(chan, IDX_IO1_i_CylinderHigh) << 16) ;
+
+ AtapiWritePort1(chan, IDX_IO2_o_Control,
+ IDE_DC_USE_HOB );
+
+ KdPrint2((PRINT_PREFIX "Read high order bytes\n"));
+ NativeNumOfSectors |=
+ (ULONG)((ULONG)AtapiReadPort1(chan, IDX_IO1_i_BlockNumber) << 24 );
+ hNativeNumOfSectors=
+ (ULONG)AtapiReadPort1(chan, IDX_IO1_i_CylinderLow) |
+ ((ULONG)AtapiReadPort1(chan, IDX_IO1_i_CylinderHigh) << 8) ;
+ ((PULONG)&NativeNumOfSectors)[1] = hNativeNumOfSectors;
+ }
KdPrint2((PRINT_PREFIX "NativeNumOfSectors %#I64x\n", NativeNumOfSectors));
// Some drives report LBA48 capability while has capacity below 128Gb
IDE_COMMAND_READ_NATIVE_SIZE48, 0, 0, 0, ATA_WAIT_READY);
if(!(statusByte & IDE_STATUS_ERROR)) {
- NativeNumOfSectors = (ULONGLONG)AtapiReadPort1(chan, IDX_IO1_i_BlockNumber) |
+ if(use_ahci) {
+ NativeNumOfSectors = chan->AhciInternalAtaReq->ahci.in_lba;
+ } else {
+ NativeNumOfSectors = (ULONGLONG)AtapiReadPort1(chan, IDX_IO1_i_BlockNumber) |
((ULONGLONG)AtapiReadPort1(chan, IDX_IO1_i_BlockNumber) << 24) |
((ULONGLONG)AtapiReadPort1(chan, IDX_IO1_i_CylinderLow) << 8 ) |
((ULONGLONG)AtapiReadPort1(chan, IDX_IO1_i_CylinderLow) << 32) |
((ULONGLONG)AtapiReadPort1(chan, IDX_IO1_i_CylinderHigh) << 16) |
((ULONGLONG)AtapiReadPort1(chan, IDX_IO1_i_CylinderHigh) << 40)
;
+ }
}
if((NativeNumOfSectors & 0xffffff) == ((NativeNumOfSectors >> 24) & 0xffffff)) {
NumOfSectors = NativeNumOfSectors;
}
}
- }
+ } // !error
}
if(NumOfSectors < 0x2100000 /*&& NumOfSectors > 31*1000*1000*/) {
0, IDE_USE_LBA, 0, 0, 0, ATA_WAIT_READY);
if(!(statusByte & IDE_STATUS_ERROR)) {
- NativeNumOfSectors = (ULONG)AtapiReadPort1(chan, IDX_IO1_i_BlockNumber) |
- ((ULONG)AtapiReadPort1(chan, IDX_IO1_i_CylinderLow) << 8) |
- ((ULONG)AtapiReadPort1(chan, IDX_IO1_i_CylinderHigh) << 16) |
- (((ULONG)AtapiReadPort1(chan, IDX_IO1_i_DriveSelect) & 0xf) << 24);
-
+ if(use_ahci) {
+ NativeNumOfSectors = chan->AhciInternalAtaReq->ahci.in_lba;
+ } else {
+ NativeNumOfSectors = (ULONG)AtapiReadPort1(chan, IDX_IO1_i_BlockNumber) |
+ ((ULONG)AtapiReadPort1(chan, IDX_IO1_i_CylinderLow) << 8) |
+ ((ULONG)AtapiReadPort1(chan, IDX_IO1_i_CylinderHigh) << 16) |
+ (((ULONG)AtapiReadPort1(chan, IDX_IO1_i_DriveSelect) & 0xf) << 24);
+ }
KdPrint2((PRINT_PREFIX "NativeNumOfSectors %#I64x\n", NativeNumOfSectors));
if(NativeNumOfSectors > NumOfSectors) {
)
{
LunExt->DeviceFlags &= DFLAGS_HIDDEN;
+ LunExt->AtapiReadyWaitDelay = 0;
} // end UniataForgetDevice()
IN ULONG PathId
)
{
- KdPrint2((PRINT_PREFIX "AtapiResetController()\n"));
+ KdPrint2((PRINT_PREFIX "AtapiResetController(%x)\n", PathId));
return AtapiResetController__(HwDeviceExtension, PathId, RESET_COMPLETE_ALL);
} // end AtapiResetController()
UCHAR tmp16;
KdPrint2((PRINT_PREFIX "AtapiResetController: Reset IDE %#x/%#x @ %#x\n", VendorID, DeviceID, slotNumber));
+ KdPrint2((PRINT_PREFIX "simplexOnly %d\n", deviceExtension->simplexOnly));
if(!deviceExtension->simplexOnly && (PathId != CHAN_NOT_SPECIFIED)) {
// we shall reset both channels on SimplexOnly devices,
// Save control flags
ChannelCtrlFlags = chan->ChannelCtrlFlags;
// Clear expecting interrupt flag.
- chan->ExpectingInterrupt = FALSE;
+ UniataExpectChannelInterrupt(chan, FALSE);
chan->RDP = FALSE;
chan->ChannelCtrlFlags = 0;
InterlockedExchange(&(chan->CheckIntr),
// Reset controller
if(ChipFlags & UNIATA_AHCI) {
KdPrint2((PRINT_PREFIX " AHCI path\n"));
+#if DBG
+ UniataDumpAhciPortRegs(chan);
+#endif
+ AtapiDisableInterrupts(deviceExtension, j);
UniataAhciReset(HwDeviceExtension, j);
} else {
KdPrint2((PRINT_PREFIX " ATA path\n"));
GetPciConfig2(0x92, tmp16);
if (((tmp16 >> pshift) & mask) == mask) {
GetBaseStatus(chan, statusByte);
- if(statusByte != 0xff) {
+ if(statusByte != IDE_STATUS_WRONG) {
break;
}
}
if(!IssueIdentify(HwDeviceExtension,
i, j,
- (chan->lun[i]->DeviceFlags & DFLAGS_ATAPI_DEVICE) ?
+ ATAPI_DEVICE(chan, i) ?
IDE_COMMAND_ATAPI_IDENTIFY : IDE_COMMAND_IDENTIFY,
FALSE)) {
KdPrint2((PRINT_PREFIX " identify failed !\n"));
AtapiStallExecution(10);
statusByte = WaitOnBusyLong(chan);
statusByte = UniataIsIdle(deviceExtension, statusByte);
- if(statusByte == 0xff) {
+ if(statusByte == IDE_STATUS_WRONG) {
KdPrint2((PRINT_PREFIX
"no drive, status %#x\n",
statusByte));
UniataForgetDevice(chan->lun[i]);
} else
// Check for ATAPI disk.
- if (chan->lun[i]->DeviceFlags & DFLAGS_ATAPI_DEVICE) {
+ if (ATAPI_DEVICE(chan, i)) {
// Issue soft reset and issue identify.
GetStatus(chan, statusByte);
KdPrint2((PRINT_PREFIX "AtapiResetController: Status before Atapi reset (%#x).\n",
}
#endif //0
- // Enable interrupts, note, the we can have here recursive disable
+ // Enable interrupts, note, we can have here recursive disable
AtapiStallExecution(10);
KdPrint2((PRINT_PREFIX "AtapiResetController: deviceExtension->chan[%d].DisableIntr %d -> 1\n",
j,
UCHAR statusByte;
if (LunExt->DeviceFlags & DFLAGS_DEVICE_PRESENT &&
- !(LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE)) {
+ !(LunExt->DeviceFlags & (DFLAGS_ATAPI_DEVICE | DFLAGS_MANUAL_CHS))) {
statusByte = AtaCommand(deviceExtension, DeviceNumber, lChannel, IDE_COMMAND_SET_MULTIPLE, 0, 0, 0, 0, 0, ATA_WAIT_BASE_READY);
AtapiDisableInterrupts(deviceExtension, lChannel);
AtapiStallExecution(1);
- if (!(LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE)) {
+ if (!(LunExt->DeviceFlags & (DFLAGS_ATAPI_DEVICE | DFLAGS_MANUAL_CHS))) {
KdPrint2((PRINT_PREFIX "AtapiHwInitialize: IDE branch\n"));
// Enable media status notification
statusByte = AtaCommand(deviceExtension, i, lChannel,
IDE_COMMAND_SET_MULTIPLE, 0, 0, 0,
- LunExt->MaximumBlockXfer, 0, ATA_WAIT_BASE_READY);
+ 0, 0, ATA_WAIT_BASE_READY);
if (statusByte & IDE_STATUS_ERROR) {
// Read the error register.
// 10000 * 100us = 1000,000us = 1000ms = 1s
waitCount = 10000;
GetStatus(chan, statusByte);
+ if(statusByte == IDE_STATUS_WRONG) {
+ waitCount = 0;
+ }
while ((statusByte & IDE_STATUS_BUSY) && waitCount) {
- KdPrint2((PRINT_PREFIX "Wait for ATAPI (status %x\n)", statusByte));
+ KdPrint2((PRINT_PREFIX "Wait for ATAPI (status %x)\n", statusByte));
// Wait for Busy to drop.
AtapiStallExecution(100);
GetStatus(chan, statusByte);
}
// 5000 * 100us = 500,000us = 500ms = 0.5s
- waitCount = 5000;
- do {
- AtapiStallExecution(100);
- } while (waitCount--);
+ if(statusByte != IDE_STATUS_WRONG) {
+ waitCount = 5000;
+ do {
+ AtapiStallExecution(100);
+ } while (waitCount--);
+ }
}
GetBaseStatus(chan, statusByte);
AtapiEnableInterrupts(deviceExtension, lChannel);
return;
-} // end AtapiHwInitialize()
+} // end AtapiHwInitialize__()
#ifndef UNIATA_CORE
// Check other channel
// In simplex mode no interrupts must appear on other channels
- for(_c=0; _c<deviceExtension->NumberChannels-1; _c++) {
+ for(_c=0; _c<deviceExtension->NumberChannels; _c++) {
c = (_c+deviceExtension->FirstChannelToCheck) % deviceExtension->NumberChannels;
+ if(c == lChannel) {
+ continue;
+ }
+
chan = &(deviceExtension->chan[c]);
if((ULONG)CrNtInterlockedCompareExchange(CRNT_ILK_PTYPE &(chan->CheckIntr),
)
{
AtapiCallBack__(HwDeviceExtension, (UCHAR)((PHW_DEVICE_EXTENSION)HwDeviceExtension)->ActiveDpcChan);
-}
+} // end AtapiCallBack_X()
#endif //UNIATA_CORE
ULONG c_state;
ULONG i_res = 0;
ULONG pass;
- BOOLEAN checked[AHCI_MAX_PORT];
+ //BOOLEAN checked[AHCI_MAX_PORT];
ULONG hIS;
+ ULONG checked;
- KdPrint2((PRINT_PREFIX "Intr: VendorID+DeviceID/Rev %#x/%#x\n", deviceExtension->DevID, deviceExtension->RevID));
+ KdPrint2((PRINT_PREFIX "Intr: VendorID+DeviceID/Rev %#x/%#x (ex %d)\n",
+ deviceExtension->DevID, deviceExtension->RevID, deviceExtension->ExpectingInterrupt ));
if(deviceExtension->HwFlags & UNIATA_AHCI) {
+ // AHCI may generate state change notification, never skip this check
hIS = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_IS);
- KdPrint2((PRINT_PREFIX "AtapiInterrupt2: AHCI: hIS=%x cntrlr %#x chan %#x\n",hIS, deviceExtension->DevIndex, deviceExtension->Channel));
+ KdPrint2((PRINT_PREFIX "AtapiInterrupt(base): AHCI: hIS=%x cntrlr %#x chan %#x\n",hIS, deviceExtension->DevIndex, deviceExtension->Channel));
if(!hIS) {
return FALSE;
}
+ checked = ~hIS; // assume all non-interrupted ports to be already checked
+ } else {
+ checked = 0; // assume all ports are not checked
}
- for(_c=0; _c<deviceExtension->NumberChannels; _c++) {
- checked[_c] = FALSE;
+ if(!deviceExtension->ExpectingInterrupt) {
+ // if we do not expect interrupt, exit now,
+ // but keep in mind that it can be unexpected one
+ // Note: this is just a hint, not exact counter
+ KdPrint2((PRINT_PREFIX "unexpected, 1st chance\n"));
+ //deviceExtension->ExpectingInterrupt++;
+ //return FALSE;
}
+ // clear this flag now, it can be set again in sub-calls
+ deviceExtension->ExpectingInterrupt=0;
+
+
+// for(_c=0; _c<deviceExtension->NumberChannels; _c++) {
+// checked[_c] = (UCHAR)((hIS >> _c) & 0x01);
+// }
// fc =
for(pass=0; pass<2; pass++) {
+ //KdPrint2((PRINT_PREFIX "AtapiInterrupt(base): pass %d\n", pass));
+ if(status && pass) {
+ // we catched some expected interrupts now.
+ // do not touch unexpected until next ISR call
+ break;
+ }
for(_c=0; _c<deviceExtension->NumberChannels; _c++) {
c = (_c+deviceExtension->FirstChannelToCheck) % deviceExtension->NumberChannels;
- if(checked[c])
+ if((checked>>c) & 0x01)
continue;
// check non-empty and expecting interrupt channels first
if(!pass && !deviceExtension->chan[c].ExpectingInterrupt)
continue;
- checked[c] = TRUE;
+ checked |= (ULONG)1 << c;
KdPrint2((PRINT_PREFIX "AtapiInterrupt(base): cntrlr %#x chan %#x\n",deviceExtension->DevIndex, c));
if(CrNtInterlockedExchangeAdd(&(deviceExtension->chan[c].DisableIntr), 0)) {
+ // we get here on idle channels or when ISR is posted to DPC
KdPrint2((PRINT_PREFIX "AtapiInterrupt(base): disabled INTR on ch %d\n", c));
continue;
}
if(i_res == INTERRUPT_REASON_UNEXPECTED) {
KdPrint2((PRINT_PREFIX "AtapiInterrupt(base): Catch unexpected\n"));
InterlockedExchange(&(deviceExtension->chan[c].CheckIntr), CHECK_INTR_IDLE);
- return TRUE;
+ //return TRUE;
+ status = TRUE;
+ continue;
}
// disable interrupts on other channel of legacy mode
// ISA-bridged onboard controller
IN PVOID Isr2HwDeviceExtension
)
{
+ // This ISR is intended to catch interrupts when we are already in other ISR instance
+ // for the same device. This may happen when we have multiple channels,
+ // especially on SMP machines
PISR2_DEVICE_EXTENSION Isr2DeviceExtension = (PISR2_DEVICE_EXTENSION)Isr2HwDeviceExtension;
PHW_DEVICE_EXTENSION deviceExtension = Isr2DeviceExtension->HwDeviceExtension;
ULONG c_count = 0;
ULONG i_res;
ULONG hIS;
+ ULONG checked;
// we should never get here for ISA/MCA
if(!BMList[deviceExtension->DevIndex].Isr2Enable) {
}
if(deviceExtension->HwFlags & UNIATA_AHCI) {
+ // AHCI may generate state change notification, never skip this check
hIS = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_IS);
KdPrint2((PRINT_PREFIX "AtapiInterrupt2: AHCI: hIS=%x cntrlr %#x chan %#x\n",hIS, deviceExtension->DevIndex, deviceExtension->Channel));
if(!hIS) {
return FALSE;
}
+ checked = ~hIS; // assume all non-interrupted ports to be already checked
+ } else {
+ checked = 0; // assume all ports are not checked
+ }
+ if(!deviceExtension->ExpectingInterrupt) {
+ KdPrint2((PRINT_PREFIX "AtapiInterrupt2: !deviceExtension->ExpectingInterrupt\n"));
+ deviceExtension->ExpectingInterrupt++;
+ return FALSE;
}
+ //deviceExtension->ExpectingInterrupt = 0;
for(c=0; c<deviceExtension->NumberChannels; c++) {
KdPrint2((PRINT_PREFIX "AtapiInterrupt2: cntrlr %#x chan %#x\n",deviceExtension->DevIndex, c));
+ if((checked>>c) & 0x01)
+ continue;
+
+ checked |= (ULONG)1 << c;
+
if(CrNtInterlockedExchangeAdd(&(deviceExtension->chan[c].DisableIntr), 0)) {
KdPrint2((PRINT_PREFIX "AtapiInterrupt2: disabled INTR\n"));
continue;
{
PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
PHW_CHANNEL chan;
+ //UCHAR statusByte;
+
if(c >= deviceExtension->NumberChannels) {
KdPrint2((PRINT_PREFIX "AtapiEnableInterrupts_%d: WRONG CHANNEL\n",c));
return;
KdPrint2((PRINT_PREFIX "AtapiEnableInterrupts_%d: %d\n",c, chan->DisableIntr));
if(!InterlockedDecrement(&chan->DisableIntr)) {
if(deviceExtension->HwFlags & UNIATA_AHCI) {
- UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_IE, 0);
+ UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_IE,
+ (ATA_AHCI_P_IX_CPD | ATA_AHCI_P_IX_TFE | ATA_AHCI_P_IX_HBF |
+ ATA_AHCI_P_IX_HBD | ATA_AHCI_P_IX_IF | ATA_AHCI_P_IX_OF |
+ ((/*ch->pm_level == */0) ? ATA_AHCI_P_IX_PRC | ATA_AHCI_P_IX_PC : 0) |
+ ATA_AHCI_P_IX_PRC | ATA_AHCI_P_IX_PC | /* DEBUG */
+ ATA_AHCI_P_IX_DI |
+ ATA_AHCI_P_IX_DP | ATA_AHCI_P_IX_UF | ATA_AHCI_P_IX_SDB |
+ ATA_AHCI_P_IX_DS | ATA_AHCI_P_IX_PS | ATA_AHCI_P_IX_DHR)
+ );
} else {
+ //SelectDrive(chan, 0);
+ //GetBaseStatus(chan, statusByte);
AtapiWritePort1(chan, IDX_IO2_o_Control,
IDE_DC_A_4BIT );
+ //if(chan->NumberLuns) {
+ // SelectDrive(chan, 1);
+ // GetBaseStatus(chan, statusByte);
+ // AtapiWritePort1(chan, IDX_IO2_o_Control,
+ // IDE_DC_A_4BIT );
+ // SelectDrive(chan, chan->cur_cdev);
+ //}
}
chan->ChannelCtrlFlags &= ~CTRFLAGS_INTR_DISABLED;
} else {
// mark channel as busy
if(InterlockedIncrement(&chan->DisableIntr)) {
if(deviceExtension->HwFlags & UNIATA_AHCI) {
- UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_IE,
- (ATA_AHCI_P_IX_CPD | ATA_AHCI_P_IX_TFE | ATA_AHCI_P_IX_HBF |
- ATA_AHCI_P_IX_HBD | ATA_AHCI_P_IX_IF | ATA_AHCI_P_IX_OF |
- ((/*ch->pm_level == */0) ? ATA_AHCI_P_IX_PRC | ATA_AHCI_P_IX_PC : 0) |
- ATA_AHCI_P_IX_DP | ATA_AHCI_P_IX_UF | ATA_AHCI_P_IX_SDB |
- ATA_AHCI_P_IX_DS | ATA_AHCI_P_IX_PS | ATA_AHCI_P_IX_DHR)
- );
+ UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_IE, 0);
} else {
+ //SelectDrive(chan, 0);
AtapiWritePort1(chan, IDX_IO2_o_Control,
IDE_DC_DISABLE_INTERRUPTS /*| IDE_DC_A_4BIT*/ );
+ //if(chan->NumberLuns) {
+ // SelectDrive(chan, 1);
+ // AtapiWritePort1(chan, IDX_IO2_o_Control,
+ // IDE_DC_DISABLE_INTERRUPTS /*| IDE_DC_A_4BIT*/ );
+ // SelectDrive(chan, chan->cur_cdev);
+ //}
}
chan->ChannelCtrlFlags |= CTRFLAGS_INTR_DISABLED;
}
return;
} // end AtapiDisableInterrupts()
+VOID
+UniataExpectChannelInterrupt(
+ IN struct _HW_CHANNEL* chan,
+ IN BOOLEAN Expecting
+ )
+{
+ chan->ExpectingInterrupt = Expecting;
+ if(Expecting) {
+ chan->DeviceExtension->ExpectingInterrupt++;
+ } else
+ if(chan->DeviceExtension->ExpectingInterrupt) {
+ chan->DeviceExtension->ExpectingInterrupt--;
+ }
+ return;
+} // end UniataExpectChannelInterrupt()
/*
Check hardware for interrupt state
{
PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
PHW_CHANNEL chan = &(deviceExtension->chan[c]);
- PHW_LU_EXTENSION LunExt = chan->lun[chan->cur_cdev];
+ PHW_LU_EXTENSION LunExt;
ULONG VendorID = deviceExtension->DevID & 0xffff;
ULONG ChipType = deviceExtension->HwFlags & CHIPTYPE_MASK;
UCHAR lChannel;
BOOLEAN DmaTransfer = FALSE;
BOOLEAN OurInterrupt = FALSE;
+ BOOLEAN StatusValid = FALSE;
// ULONG k;
UCHAR interruptReason;
BOOLEAN EarlyIntr = FALSE;
+ BOOLEAN SingleBlockIntr = FALSE;
KdPrint2((PRINT_PREFIX "AtapiCheckInterrupt__:\n"));
lChannel = c;
Channel = (UCHAR)(deviceExtension->Channel + lChannel);
+ LunExt = chan->lun[chan->cur_cdev];
+
+ //KdPrint2((PRINT_PREFIX "AtapiCheckInterrupt__ chan %#x:\n", chan));
+ //KdPrint2((PRINT_PREFIX "AtapiCheckInterrupt__ (%d/%d):\n", Channel, chan->cur_cdev));
if((ChipFlags & UNIATA_AHCI) &&
UniataIsSATARangeAvailable(deviceExtension, lChannel)) {
- OurInterrupt = UniataAhciStatus(HwDeviceExtension, lChannel, -1);
+ OurInterrupt = UniataAhciStatus(HwDeviceExtension, lChannel, DEVNUM_NOT_SPECIFIED);
+ if((OurInterrupt == INTERRUPT_REASON_UNEXPECTED) &&
+ (LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE)) {
+ UniataAhciWaitCommandReady(chan, 2 /* ms */ );
+ statusByte = (UCHAR)UniataAhciWaitReady(chan, 0 /* immediate */);
+ if(!(statusByte & (IDE_STATUS_BUSY)) ) {
+ KdPrint2((PRINT_PREFIX "ATAPI special case READY\n"));
+ //deviceExtension->ExpectingInterrupt++; // will be updated in ISR on ReturnEnableInterrupts
+ OurInterrupt = INTERRUPT_REASON_OUR;
+ } else
+ if((statusByte & (IDE_STATUS_BUSY | IDE_STATUS_DRDY)) == (IDE_STATUS_BUSY | IDE_STATUS_DRDY) ) {
+ KdPrint2((PRINT_PREFIX "ATAPI special case pre ERR-READY\n"));
+ OurInterrupt = INTERRUPT_REASON_OUR;
+ } else
+ if(statusByte & IDE_STATUS_ERROR) {
+ KdPrint2((PRINT_PREFIX "ATAPI special case ERR-READY\n"));
+ OurInterrupt = INTERRUPT_REASON_OUR;
+ } else {
+ KdPrint2((PRINT_PREFIX "ATAPI special case ? %x\n", statusByte));
+ OurInterrupt = INTERRUPT_REASON_OUR;
+ }
+ }
return OurInterrupt;
}
} else {
KdPrint2((PRINT_PREFIX " getting status...\n"));
GetStatus(chan, statusByte);
+ StatusValid = 1;
KdPrint2((PRINT_PREFIX " status %#x\n", statusByte));
if(statusByte & IDE_STATUS_ERROR) {
KdPrint2((PRINT_PREFIX " IDE_STATUS_ERROR -> our\n", statusByte));
(LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE) &&
(dma_status == BM_STATUS_ACTIVE)) {
KdPrint2((PRINT_PREFIX " special case DMA + ATAPI + IDE_STATUS_DSC -> our\n", statusByte));
+ // some devices interrupts on each block transfer even in DMA mode
+ if(LunExt->TransferMode >= ATA_SDMA && LunExt->TransferMode <= ATA_WDMA2) {
+ KdPrint2((PRINT_PREFIX " wait for completion\n"));
+ ///* clear interrupt and get status */
+ //GetBaseStatus(chan, statusByte);
+ //return INTERRUPT_REASON_IGNORE;
+ SingleBlockIntr = TRUE;
+ }
} else {
return INTERRUPT_REASON_IGNORE;
}
}
}
skip_dma_stat_check:
- if(!(ChipFlags & UNIATA_SATA)) {
+ if(!(ChipFlags & UNIATA_SATA) && chan->ExpectingInterrupt) {
AtapiStallExecution(1);
}
/* if drive is busy it didn't interrupt */
/* the exception is DCS + BSY state of ATAPI devices */
- KdPrint2((PRINT_PREFIX " getting status...\n"));
- GetStatus(chan, statusByte);
+ if(!StatusValid) {
+ KdPrint2((PRINT_PREFIX " getting status...\n"));
+ GetStatus(chan, statusByte);
+ }
if(LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE) {
KdPrint3((PRINT_PREFIX " ATAPI status %#x\n", statusByte));
} else {
KdPrint2((PRINT_PREFIX " IDE status %#x\n", statusByte));
}
- if (statusByte == 0xff) {
+ if (statusByte == IDE_STATUS_WRONG) {
// interrupt from empty controller ?
} else
if (statusByte & IDE_STATUS_BUSY) {
KdPrint3((PRINT_PREFIX " our interrupt with BSY set, try wait in ISR or post to DPC\n"));
/* clear interrupt and get status */
GetBaseStatus(chan, statusByte);
+ if(!(dma_status & BM_STATUS_ACTIVE)) {
+ AtapiDmaDone(deviceExtension, DEVNUM_NOT_SPECIFIED ,lChannel, NULL);
+ }
KdPrint3((PRINT_PREFIX " base status %#x (+BM_STATUS_INTR)\n", statusByte));
return INTERRUPT_REASON_OUR;
}
/* clear interrupt and get status */
GetBaseStatus(chan, statusByte);
KdPrint2((PRINT_PREFIX " base status %#x\n", statusByte));
- if (statusByte == 0xff) {
+ if (statusByte == IDE_STATUS_WRONG) {
// interrupt from empty controller ?
} else
if(!(statusByte & (IDE_STATUS_DRQ | IDE_STATUS_DRDY))) {
#ifndef UNIATA_PIO_ONLY
if(DmaTransfer) {
- if(!EarlyIntr || g_WaitBusyInISR) {
+ if(!SingleBlockIntr && (!EarlyIntr || g_WaitBusyInISR)) {
dma_status = AtapiDmaDone(HwDeviceExtension, DEVNUM_NOT_SPECIFIED, lChannel, NULL/*srb*/);
} else {
PSCSI_REQUEST_BLOCK srb = UniataGetCurRequest(chan);
//ASSERT(AtaReq);
- KdPrint2((PRINT_PREFIX " set REQ_STATE_EARLY_INTR.\n"));
+ if(SingleBlockIntr) {
+ KdPrint2((PRINT_PREFIX " set REQ_STATE_ATAPI_EXPECTING_DATA_INTR2.\n"));
+ } else {
+ KdPrint2((PRINT_PREFIX " set REQ_STATE_EARLY_INTR.\n"));
+ }
if(AtaReq) {
- AtaReq->ReqState = REQ_STATE_EARLY_INTR;
+ AtaReq->ReqState = SingleBlockIntr ? REQ_STATE_ATAPI_EXPECTING_DATA_INTR2 : REQ_STATE_EARLY_INTR;
}
}
}
BOOLEAN DmaTransfer = FALSE;
UCHAR error = 0;
ULONG TimerValue = 1000;
+ ULONG TotalTimerValue = 0;
#ifdef UNIATA_USE_XXableInterrupts
BOOLEAN InDpc = (KeGetCurrentIrql() == DISPATCH_LEVEL);
#else
KdPrint2((PRINT_PREFIX " cntrlr %#x:%d, irql %#x, c %d\n", deviceExtension->DevIndex, Channel, KeGetCurrentIrql(), c));
if((chan->ChannelCtrlFlags & CTRFLAGS_DMA_ACTIVE) ||
- (AtaReq && (AtaReq->Flags & REQ_FLAG_DMA_OPERATION)) ) {
+ (AtaReq && (AtaReq->Flags & REQ_FLAG_DMA_OPERATION)) ||
+ (deviceExtension->HwFlags & UNIATA_AHCI)) {
DmaTransfer = TRUE;
KdPrint2((PRINT_PREFIX " DmaTransfer = TRUE\n"));
}
case REQ_STATE_ATAPI_EXPECTING_CMD_INTR:
KdPrint3((PRINT_PREFIX " EXPECTING_CMD_INTR\n"));
case REQ_STATE_ATAPI_EXPECTING_DATA_INTR:
+ case REQ_STATE_ATAPI_EXPECTING_DATA_INTR2:
case REQ_STATE_DPC_WAIT_BUSY0:
case REQ_STATE_DPC_WAIT_BUSY1:
KdPrint2((PRINT_PREFIX " continue service interrupt\n"));
// disable interrupts for this channel,
// but avoid recursion and double-disable
if(OldReqState != REQ_STATE_DPC_WAIT_BUSY1) {
+ UniataExpectChannelInterrupt(chan, FALSE);
AtapiDisableInterrupts(deviceExtension, lChannel);
}
// go to ISR DPC
CallTimerDpc:
AtaReq->ReqState = REQ_STATE_PROCESSING_INTR;
CallTimerDpc2:
+ if(!InDpc && OldReqState != REQ_STATE_DPC_WAIT_BUSY1) {
+ // we must block interrupts from this channel
+ // If device generate new interrupt before we get to DPC,
+ // ISR will assume, that it is NOT our interrupt
+ AtapiDisableInterrupts(deviceExtension, lChannel);
+ // We should not clean ExpectingInterrupt flag on channel, since it is used in DPC
+ }
// Will raise IRQL to DIRQL
AtapiQueueTimerDpc(HwDeviceExtension, c,
AtapiCallBack_X,
AtapiStallExecution(10);
}
*/
- /* clear interrupt and get status */
+ /* clear interrupt and get status */
if(deviceExtension->HwFlags & UNIATA_AHCI) {
UniataAhciEndTransaction(HwDeviceExtension, lChannel, DeviceNumber, srb);
- statusByte = (UCHAR)(AtaReq->ahci.in_status & 0xff);
+ statusByte = (UCHAR)(AtaReq->ahci.in_status & IDE_STATUS_MASK);
} else {
GetBaseStatus(chan, statusByte);
}
InDpc = TRUE;
}
- if(deviceExtension->HwFlags & UNIATA_AHCI) {
- KdPrint3((PRINT_PREFIX " AHCI branch\n"));
- } else
if (!atapiDev) {
// IDE
+ if(deviceExtension->HwFlags & UNIATA_AHCI) {
+ KdPrint3((PRINT_PREFIX " AHCI branch (IDE)\n"));
+ } else
if (statusByte & IDE_STATUS_BUSY) {
if (deviceExtension->DriverMustPoll) {
// Crashdump is polling and we got caught with busy asserted.
// ATAPI
if(!LunExt->IdentifyData.MajorRevision &&
InDpc &&
- !atapiDev &&
+ /*!atapiDev &&*/
!(deviceExtension->HwFlags & UNIATA_SATA)
) {
- KdPrint2((PRINT_PREFIX " additional delay 10us for old devices (2)\n"));
- AtapiStallExecution(10);
+ //KdPrint2((PRINT_PREFIX " additional delay 10us for old devices (2)\n"));
+ //AtapiStallExecution(10);
+ }
+ if(deviceExtension->HwFlags & UNIATA_AHCI) {
+ KdPrint3((PRINT_PREFIX " AHCI branch (ATAPI)\n"));
+ } else {
+ interruptReason = (AtapiReadPort1(chan, IDX_ATAPI_IO1_i_InterruptReason) & 0x3);
+ KdPrint3((PRINT_PREFIX "AtapiInterrupt: iReason %x\n", interruptReason));
}
+
if (statusByte & IDE_STATUS_BUSY) {
//if(chan->ChannelCtrlFlags & CTRFLAGS_DSC_BSY) {}
- KdPrint3((PRINT_PREFIX " BUSY on ATAPI device, waiting\n"));
+/*
+#ifndef UNIATA_CORE
+ // This is just workaround
+ // We should DISABLE interrupts before entering WAIT state
+ UniataExpectChannelInterrupt(chan, TRUE);
+#endif //UNIATA_CORE
+*/
+ KdPrint3((PRINT_PREFIX " BUSY on ATAPI device, waiting %d us\n", LunExt->AtapiReadyWaitDelay));
+#ifndef UNIATA_CORE
+ if(LunExt->AtapiReadyWaitDelay && (LunExt->AtapiReadyWaitDelay > g_opt_MaxIsrWait) && !InDpc && UseDpc) {
+ TimerValue = LunExt->AtapiReadyWaitDelay;
+ KdPrint2((PRINT_PREFIX " too long wait: ISR -> DPC (0)\n"));
+ AtaReq->ReqState = REQ_STATE_DPC_WAIT_BUSY0;
+ goto CallTimerDpc2;
+ }
+#endif //UNIATA_CORE
+ TimerValue = 10;
for(k=20; k; k--) {
- GetStatus(chan, statusByte);
+ GetBaseStatus(chan, statusByte);
KdPrint3((PRINT_PREFIX " status re-check %#x\n", statusByte));
KdPrint3((PRINT_PREFIX " Error reg (%#x)\n",
- AtapiReadPort1(chan, IDX_IO1_i_Error)));
+ AtapiReadPort1(chan, IDX_ATAPI_IO1_i_Error)));
if (!(statusByte & IDE_STATUS_BUSY)) {
KdPrint2((PRINT_PREFIX " expecting intr + cleared BUSY\n"));
break;
}
- if(k <= 18) {
+ TotalTimerValue += TimerValue;
+ if(k <= 1) {
KdPrint3((PRINT_PREFIX " too long wait -> DPC\n"));
if(!InDpc) {
KdPrint2((PRINT_PREFIX " too long wait: ISR -> DPC\n"));
AtaReq->ReqState = REQ_STATE_DPC_WAIT_BUSY1;
}
#ifndef UNIATA_CORE
- goto CallTimerDpc2;
-#else //UNIATA_CORE
- AtapiStallExecution(TimerValue);
+ if(UseDpc) {
+ if(!LunExt->AtapiReadyWaitDelay) {
+ LunExt->AtapiReadyWaitDelay = TotalTimerValue*2/3;
+ }
+ goto CallTimerDpc2;
+ }
#endif //UNIATA_CORE
}
- AtapiStallExecution(10);
+ AtapiStallExecution(TimerValue);
+ TimerValue += 10;
+ }
+ if(!LunExt->AtapiReadyWaitDelay) {
+ LunExt->AtapiReadyWaitDelay = TotalTimerValue*2/3;
+ KdPrint2((PRINT_PREFIX " store AtapiReadyWaitDelay: %d\n", LunExt->AtapiReadyWaitDelay));
}
if (statusByte & IDE_STATUS_BUSY) {
KdPrint3((PRINT_PREFIX " expecting intr + BUSY (2), try DPC wait\n"));
(dma_status & BM_STATUS_ERR)) {
if(deviceExtension->HwFlags & UNIATA_AHCI) {
- error = (UCHAR)((AtaReq->ahci.in_status >> 8) && 0xff);
+ error = (UCHAR)((AtaReq->ahci.in_status >> 8) & 0xff);
+ // wait ready
+#if DBG
+ UniataDumpAhciPortRegs(chan);
+#endif
+ UniataAhciStop(chan);
+ UniataAhciStart(chan);
+
+ UniataAhciWaitCommandReady(chan, 10);
+ // clear interrupts again
+#if DBG
+ UniataDumpAhciPortRegs(chan);
+#endif
+ UniataAhciStatus(HwDeviceExtension, lChannel, DEVNUM_NOT_SPECIFIED);
+#if DBG
+ UniataDumpAhciPortRegs(chan);
+#endif
} else {
error = AtapiReadPort1(chan, IDX_IO1_i_Error);
}
LunExt->DeviceFlags & DFLAGS_INT_DRQ));
for (k = atapiDev ? 0 : 200; k; k--) {
- GetStatus(chan, statusByte);
+ GetBaseStatus(chan, statusByte);
if (!(statusByte & IDE_STATUS_DRQ)) {
AtapiStallExecution(50);
} else {
PIO_wait_DRQ0:
// The ISR hits with DRQ low, but comes up later.
for (k = 0; k < 5000; k++) {
- GetStatus(chan, statusByte);
+ GetBaseStatus(chan, statusByte);
if (statusByte & IDE_STATUS_DRQ) {
break;
}
KdPrint2((PRINT_PREFIX "AtapiInterrupt: i-reason=%d, status=%#x\n", interruptReason, statusByte));
if(deviceExtension->HwFlags & UNIATA_AHCI) {
- KdPrint2((PRINT_PREFIX " AHCI path\n"));
- goto ReturnEnableIntr;
+ KdPrint2((PRINT_PREFIX " AHCI path, WordsTransfered %x, WordsLeft %x\n", AtaReq->WordsTransfered, AtaReq->WordsLeft));
+ if(chan->AhciLastIS & ATA_AHCI_P_IX_OF) {
+ status = SRB_STATUS_DATA_OVERRUN;
+ DataOverrun = TRUE;
+ } else {
+ status = SRB_STATUS_SUCCESS;
+ }
+ if(AtaReq->WordsTransfered >= AtaReq->WordsLeft) {
+ AtaReq->WordsLeft = 0;
+ } else {
+ AtaReq->WordsLeft -= AtaReq->WordsTransfered;
+ }
+ chan->ChannelCtrlFlags &= ~CTRFLAGS_DMA_OPERATION;
+ goto CompleteRequest;
} else
if (interruptReason == 0x1 && (statusByte & IDE_STATUS_DRQ)) {
// Write the packet.
AtapiReadPort1(chan, IDX_ATAPI_IO1_i_ByteCountLow);
wordCount |=
- AtapiReadPort1(chan, IDX_ATAPI_IO1_i_ByteCountHigh) << 8;
+ (USHORT)AtapiReadPort1(chan, IDX_ATAPI_IO1_i_ByteCountHigh) << 8;
// Covert bytes to words.
wordCount >>= 1;
}
}
- if (DmaTransfer && (chan->ChannelCtrlFlags & CTRFLAGS_DMA_OPERATION)) {
+ if (DmaTransfer &&
+ (chan->ChannelCtrlFlags & CTRFLAGS_DMA_OPERATION)) {
//ASSERT(AtaReq->WordsLeft == wordCount);
+ if(AtaReq->ReqState == REQ_STATE_ATAPI_EXPECTING_DATA_INTR2) {
+ KdPrint2((PRINT_PREFIX
+ "IdeIntr: DMA tmp INTR %#x vs %#x\n", AtaReq->WordsLeft, wordCount));
+ if(AtaReq->WordsLeft > wordCount) {
+ AtaReq->WordsLeft -= wordCount;
+ AtaReq->ReqState = REQ_STATE_ATAPI_EXPECTING_DATA_INTR;
+ goto ReturnEnableIntr;
+ }
+ dma_status = AtapiDmaDone(HwDeviceExtension, DEVNUM_NOT_SPECIFIED, lChannel, NULL/*srb*/);
+ }
AtaReq->WordsLeft = 0;
status = SRB_STATUS_SUCCESS;
chan->ChannelCtrlFlags &= ~CTRFLAGS_DMA_OPERATION;
goto CompleteRequest;
}
+
// Ensure that this is a write command.
if (srb->SrbFlags & SRB_FLAGS_DATA_OUT) {
} else {
KdPrint3((PRINT_PREFIX
- "AtapiInterrupt: Int reason %#x, but srb is for a write %#x.\n",
+ "AtapiInterrupt: Int reason %#x, but srb is for a read %#x.\n",
interruptReason,
srb));
status = SRB_STATUS_ERROR;
goto CompleteRequest;
}
-
// Advance data buffer pointer and bytes left.
AtaReq->DataBuffer += wordCount;
AtaReq->WordsLeft -= wordCount;
AtapiReadPort1(chan, IDX_ATAPI_IO1_i_ByteCountLow) |
(AtapiReadPort1(chan, IDX_ATAPI_IO1_i_ByteCountHigh) << 8);
- // Covert bytes to words.
- wordCount /= 2;
+ // Convert bytes to words.
+ wordCount >>= 1;
KdPrint2((PRINT_PREFIX "AtapiInterrupt: get R wordCount %#x\n", wordCount));
if (wordCount != AtaReq->WordsLeft) {
}
}
- if (DmaTransfer && (chan->ChannelCtrlFlags & CTRFLAGS_DMA_OPERATION)) {
+ if(DmaTransfer &&
+ (chan->ChannelCtrlFlags & CTRFLAGS_DMA_OPERATION)) {
+ if(AtaReq->ReqState == REQ_STATE_ATAPI_EXPECTING_DATA_INTR2) {
+ KdPrint2((PRINT_PREFIX
+ "IdeIntr: DMA tmp INTR %#x vs %#x\n", AtaReq->WordsLeft, wordCount));
+ if(AtaReq->WordsLeft > wordCount) {
+ AtaReq->WordsLeft -= wordCount;
+ AtaReq->ReqState = REQ_STATE_ATAPI_EXPECTING_DATA_INTR;
+ goto ReturnEnableIntr;
+ }
+ dma_status = AtapiDmaDone(HwDeviceExtension, DEVNUM_NOT_SPECIFIED, lChannel, NULL/*srb*/);
+ }
//ASSERT(AtaReq->WordsLeft == wordCount);
AtaReq->WordsLeft = 0;
status = SRB_STATUS_SUCCESS;
KdDump(AtaReq->DataBuffer, wordCount*2);
}
- GetStatus(chan, statusByte);
+ GetBaseStatus(chan, statusByte);
KdPrint2((PRINT_PREFIX " status re-check %#x\n", statusByte));
if(DataOverrun) {
*((ULONG *) &(AtaReq->DataBuffer[2])) = 0x00080000;
AtaReq->DataBuffer += wordCount;
}
+
+ GetStatus(chan, statusByte);
+ if(!(statusByte & IDE_STATUS_BUSY)) {
+ // Assume command is completed if BUSY is cleared
+ // and all data read
+ // Optionally, we may receive COMPLETE interrupt later and
+ // treat it as unexpected
+ KdPrint2((PRINT_PREFIX "AtapiInterrupt: early complete ? status %x\n", statusByte));
+
+ status = SRB_STATUS_SUCCESS;
+ goto CompleteRequest;
+ }
+
} else {
/*
} else {
if (atapiDev) {
AtaReq->ReqState = REQ_STATE_ATAPI_EXPECTING_DATA_INTR;
+ GetStatus(chan, statusByte);
+ if(!(statusByte & IDE_STATUS_BUSY)) {
+ // Assume command is completed if BUSY is cleared
+ // even if NOT all data read
+ // Optionally, we may receive COMPLETE interrupt later and
+ // treat it as unexpected
+ KdPrint2((PRINT_PREFIX "AtapiInterrupt: early complete + underrun ? status %x\n", statusByte));
+
+ status = SRB_STATUS_SUCCESS;
+ goto CompleteRequest;
+ }
}
}
if ((senseData->SenseKey != SCSI_SENSE_ILLEGAL_REQUEST) &&
chan->MechStatusRetryCount) {
+ KdPrint3((PRINT_PREFIX "AtapiInterrupt: MechStatusRetryCount %#x\n", chan->MechStatusRetryCount));
// The sense key doesn't say the last request is illegal, so try again
chan->MechStatusRetryCount--;
srb = AtaReq->Srb = BuildMechanismStatusSrb (
KdPrint2((PRINT_PREFIX "AtapiInterrupt: PIO completion, wait BUSY\n"));
// Wait for busy to drop.
for (i = 0; i < 5*30; i++) {
- GetStatus(chan, statusByte);
+ GetBaseStatus(chan, statusByte);
if (!(statusByte & IDE_STATUS_BUSY)) {
break;
}
PIO_wait_DRQ:
KdPrint2((PRINT_PREFIX "AtapiInterrupt: PIO_wait_DRQ\n"));
for (i = 0; i < 200; i++) {
- GetStatus(chan, statusByte);
+ GetBaseStatus(chan, statusByte);
if (!(statusByte & IDE_STATUS_DRQ)) {
break;
}
}
// Clear interrupt expecting flag.
- chan->ExpectingInterrupt = FALSE;
+ UniataExpectChannelInterrupt(chan, FALSE);
+ // clear this flag now, it can be set again in sub-calls
InterlockedExchange(&(chan->CheckIntr),
CHECK_INTR_IDLE);
}
}
if(status == SRB_STATUS_SUCCESS) {
- AtaReq->WordsTransfered += AtaReq->bcount * DEV_BSIZE/2;
+ if(!(deviceExtension->HwFlags & UNIATA_AHCI)) {
+ // This should be set in UniataAhciEndTransaction() for AHCI
+ AtaReq->WordsTransfered += AtaReq->bcount * DEV_BSIZE/2;
+ }
if(!atapiDev &&
AtaReq->WordsTransfered*2 < AtaReq->TransferLength) {
KdPrint2((PRINT_PREFIX "AtapiInterrupt: more I/O required (%x of %x bytes) -> reenqueue\n",
if (chan->RDP) {
// Check DSC
for (i = 0; i < 5; i++) {
- GetStatus(chan, statusByte);
+ GetBaseStatus(chan, statusByte);
if(!(statusByte & IDE_STATUS_BUSY)) {
KdPrint2((PRINT_PREFIX "AtapiInterrupt: RDP + cleared BUSY\n"));
chan->RDP = FALSE;
ReturnEnableIntr:
KdPrint2((PRINT_PREFIX "AtapiInterrupt: ReturnEnableIntr\n",srb));
+ //UniataExpectChannelInterrupt(chan, TRUE); // device may interrupt
+ deviceExtension->ExpectingInterrupt = TRUE;
if(UseDpc) {
if(CrNtInterlockedExchangeAdd(&(chan->DisableIntr), 0)) {
KdPrint2((PRINT_PREFIX "AtapiInterrupt: call AtapiEnableInterrupts__()\n"));
// assume best case here
// we cannot reinit Dma until previous request is completed
+ if(deviceExtension->HwFlags & UNIATA_AHCI) {
+ UniataAhciSetupCmdPtr(AtaReq);
+ if(!AtapiDmaSetup(HwDeviceExtension, DeviceNumber, lChannel, Srb,
+ (PUCHAR)(AtaReq->DataBuffer),
+ AtaReq->bcount * DEV_BSIZE)) {
+ KdPrint3((PRINT_PREFIX "IdeReadWrite: AHCI !DMA\n"));
+ return SRB_STATUS_ERROR;
+ }
+ } else
if ((LunExt->LimitedTransferMode >= ATA_DMA)) {
use_dma = TRUE;
// this will set REQ_FLAG_DMA_OPERATION in AtaReq->Flags on success
}
}
- if(use_dma && (deviceExtension->HwFlags & UNIATA_AHCI)) {
- UniataAhciSetupCmdPtr(AtaReq);
- KdPrint2((PRINT_PREFIX "AtapiSendCommand: setup AHCI FIS\n"));
+ if(deviceExtension->HwFlags & UNIATA_AHCI) {
+ KdPrint2((PRINT_PREFIX "IdeReadWrite: setup AHCI FIS\n"));
RtlZeroMemory(&(AtaReq->ahci.ahci_cmd_ptr->cfis), sizeof(AtaReq->ahci_cmd0.cfis));
fis_size = UniataAhciSetupFIS_H2D(deviceExtension, DeviceNumber, lChannel,
&(AtaReq->ahci.ahci_cmd_ptr->cfis[0]),
- (AtaReq->Flags & REQ_FLAG_READ) ? IDE_COMMAND_READ_DMA : /*IDE_COMMAND_WRITE_DMA*/ IDE_COMMAND_READ_DMA,
+ (AtaReq->Flags & REQ_FLAG_READ) ? IDE_COMMAND_READ_DMA : IDE_COMMAND_WRITE_DMA,
lba,
(USHORT)(AtaReq->bcount),
- 0,
- ATA_IMMEDIATE
+ 0
+ /*,(AtaReq->Flags & REQ_FLAG_READ) ? 0 : ATA_AHCI_CMD_WRITE*/
);
if(!fis_size) {
- KdPrint3((PRINT_PREFIX "AtapiSendCommand: AHCI !FIS\n"));
+ KdPrint3((PRINT_PREFIX "IdeReadWrite: AHCI !FIS\n"));
return SRB_STATUS_ERROR;
}
- AtaReq->ahci.io_cmd_flags = (USHORT)(((AtaReq->Flags & REQ_FLAG_READ) ? 0 : ATA_AHCI_CMD_WRITE) |
- /*((LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE) ? (ATA_AHCI_CMD_ATAPI | ATA_AHCI_CMD_PREFETCH) : 0) |*/
- (fis_size / sizeof(ULONG)) |
- (DeviceNumber << 12));
+ AtaReq->ahci.io_cmd_flags = UniAtaAhciAdjustIoFlags(0, (AtaReq->Flags & REQ_FLAG_READ) ? 0 : ATA_AHCI_CMD_WRITE, fis_size, DeviceNumber);
KdPrint2((PRINT_PREFIX "IdeReadWrite ahci io flags %x: \n", AtaReq->ahci.io_cmd_flags));
}
chan->ChannelCtrlFlags &= ~CTRFLAGS_DMA_OPERATION;
}
- if(use_dma && (deviceExtension->HwFlags & UNIATA_AHCI)) {
+ if(deviceExtension->HwFlags & UNIATA_AHCI) {
+ // AHCI doesn't distinguish DMA and PIO
//AtapiDmaStart(HwDeviceExtension, DeviceNumber, lChannel, Srb);
- UniataAhciBeginTransaction(HwDeviceExtension, DeviceNumber, lChannel, Srb);
+ UniataAhciBeginTransaction(HwDeviceExtension, lChannel, DeviceNumber, Srb);
+ UniataExpectChannelInterrupt(chan, TRUE); // device may interrupt
+ InterlockedExchange(&(chan->CheckIntr),
+ CHECK_INTR_IDLE);
return SRB_STATUS_PENDING;
}
(USHORT)(AtaReq->bcount),
// (UCHAR)((wordCount*2 + DEV_BSIZE-1) / DEV_BSIZE),
0, ATA_IMMEDIATE);
- if(statusByte2 != 0xff) {
+ if(statusByte2 != IDE_STATUS_WRONG) {
GetStatus(chan, statusByte2);
}
if(statusByte2 & IDE_STATUS_ERROR) {
0, ATA_WAIT_INTR);
if (!(statusByte & IDE_STATUS_DRQ) ||
- statusByte == 0xff) {
+ statusByte == IDE_STATUS_WRONG) {
- if(statusByte == 0xff) {
+ if(statusByte == IDE_STATUS_WRONG) {
KdPrint2((PRINT_PREFIX
"IdeReadWrite: error sending command (%#x)\n",
statusByte));
AtaReq->WordsLeft = 0;
// Clear interrupt expecting flag.
- chan->ExpectingInterrupt = FALSE;
+ UniataExpectChannelInterrupt(chan, FALSE);
InterlockedExchange(&(chan->CheckIntr),
CHECK_INTR_IDLE);
// Clear current SRB.
UniataRemoveRequest(chan, Srb);
- return (statusByte == 0xff) ? SRB_STATUS_ERROR : SRB_STATUS_TIMEOUT;
+ return (statusByte == IDE_STATUS_WRONG) ? SRB_STATUS_ERROR : SRB_STATUS_TIMEOUT;
}
- chan->ExpectingInterrupt = TRUE;
+ UniataExpectChannelInterrupt(chan, TRUE);
InterlockedExchange(&(chan->CheckIntr),
CHECK_INTR_IDLE);
if(AtaReq->ReqState < REQ_STATE_PREPARE_TO_TRANSFER)
AtaReq->ReqState = REQ_STATE_PREPARE_TO_TRANSFER;
+
#ifdef UNIATA_DUMP_ATAPI
if(CmdAction & CMD_ACTION_PREPARE) {
UCHAR ScsiCommand;
if(CmdAction == CMD_ACTION_PREPARE) {
- KdPrint2((PRINT_PREFIX "AtapiSendCommand: CMD_ACTION_PREPARE\n"));
+ KdPrint2((PRINT_PREFIX "AtapiSendCommand: CMD_ACTION_PREPARE, Cdb %x\n", &(Srb->Cdb)));
switch (Srb->Cdb[0]) {
+ case SCSIOP_RECEIVE:
+ case SCSIOP_SEND:
case SCSIOP_READ:
case SCSIOP_WRITE:
case SCSIOP_READ12:
}
}
+#ifndef UNIATA_CORE
+ // We need to know how many platters our atapi cd-rom device might have.
+ // Before anyone tries to send a srb to our target for the first time,
+ // we must "secretly" send down a separate mechanism status srb in order to
+ // initialize our device extension changer data. That's how we know how
+ // many platters our target has.
+
+ if (!(LunExt->DeviceFlags & DFLAGS_CHANGER_INITED) &&
+ !AtaReq->OriginalSrb) {
+
+ ULONG srbStatus;
+
+ KdPrint3((PRINT_PREFIX "AtapiSendCommand: BuildMechanismStatusSrb()\n"));
+ // Set this flag now. If the device hangs on the mech. status
+ // command, we will not have the chance to set it.
+ LunExt->DeviceFlags |= DFLAGS_CHANGER_INITED;
+
+ chan->MechStatusRetryCount = 3;
+ AtaReq->OriginalSrb = Srb;
+ AtaReq->Srb = BuildMechanismStatusSrb (
+ HwDeviceExtension,
+ Srb);
+
+ KdPrint3((PRINT_PREFIX "AtapiSendCommand: AtapiSendCommand recursive\n"));
+ srbStatus = AtapiSendCommand(HwDeviceExtension, AtaReq->Srb, CMD_ACTION_ALL);
+ if (srbStatus == SRB_STATUS_PENDING) {
+ KdPrint2((PRINT_PREFIX "AtapiSendCommand: SRB_STATUS_PENDING (2)\n"));
+ return srbStatus;
+ } else {
+ AtaReq->Srb = AtaReq->OriginalSrb;
+ AtaReq->OriginalSrb = NULL;
+ KdPrint2((PRINT_PREFIX "AtapiSendCommand: AtapiHwInitializeChanger()\n"));
+ AtapiHwInitializeChanger (HwDeviceExtension, Srb,
+ (PMECHANICAL_STATUS_INFORMATION_HEADER) NULL);
+ // fall out
+ }
+ }
+#endif //UNIATA_CORE
+
if((CmdAction & CMD_ACTION_PREPARE) &&
(AtaReq->ReqState != REQ_STATE_READY_TO_TRANSFER)) {
- KdPrint2((PRINT_PREFIX "AtapiSendCommand: prepare..., ATAPI CMD %x\n", Srb->Cdb[0]));
+ KdPrint2((PRINT_PREFIX "AtapiSendCommand: prepare..., ATAPI CMD %x (Cdb %x)\n", Srb->Cdb[0], &(Srb->Cdb)));
// Set data buffer pointer and words left.
AtaReq->DataBuffer = (PUSHORT)Srb->DataBuffer;
AtaReq->WordsLeft = Srb->DataTransferLength / 2;
AtaReq->TransferLength = Srb->DataTransferLength;
AtaReq->Flags &= ~REQ_FLAG_DMA_OPERATION;
+ // reset this to force PRD init. May be already setup by recursive SRB
+ AtaReq->dma_entries = 0;
// check if reorderable
switch(Srb->Cdb[0]) {
switch(Srb->Cdb[0]) {
case SCSIOP_WRITE:
case SCSIOP_WRITE12:
+ case SCSIOP_SEND:
if(chan->ChannelCtrlFlags & CTRFLAGS_DMA_RO)
break;
/* FALLTHROUGH */
+ case SCSIOP_RECEIVE:
case SCSIOP_READ:
case SCSIOP_READ12:
if(deviceExtension->opt_AtapiDmaReadWrite) {
call_dma_setup:
+ if(deviceExtension->HwFlags & UNIATA_AHCI) {
+ KdPrint2((PRINT_PREFIX "AtapiSendCommand: use dma (ahci)\n"));
+ use_dma = TRUE;
+ } else
if(AtapiDmaSetup(HwDeviceExtension, DeviceNumber, lChannel, Srb,
(PUCHAR)(AtaReq->DataBuffer),
Srb->DataTransferLength
}
// try setup DMA
if(use_dma) {
+ if(deviceExtension->HwFlags & UNIATA_AHCI) {
+ KdPrint2((PRINT_PREFIX "AtapiSendCommand: use dma (ahci)\n"));
+ //use_dma = TRUE;
+ } else
if(!AtapiDmaSetup(HwDeviceExtension, DeviceNumber, lChannel, Srb,
(PUCHAR)(AtaReq->DataBuffer),
Srb->DataTransferLength)) {
if(deviceExtension->HwFlags & UNIATA_AHCI) {
UniataAhciSetupCmdPtr(AtaReq);
+
+ if(!AtapiDmaSetup(HwDeviceExtension, DeviceNumber, lChannel, Srb,
+ (PUCHAR)(AtaReq->DataBuffer),
+ Srb->DataTransferLength)) {
+ KdPrint2((PRINT_PREFIX "AtapiSendCommand: no AHCI dma!\n"));
+ return SRB_STATUS_ERROR;
+ }
+ if(!use_dma) {
+ AtaReq->Flags &= ~REQ_FLAG_DMA_OPERATION;
+ }
+
KdPrint2((PRINT_PREFIX "AtapiSendCommand: setup AHCI FIS\n"));
RtlZeroMemory(&(AtaReq->ahci.ahci_cmd_ptr->cfis), sizeof(AtaReq->ahci_cmd0.cfis));
RtlCopyMemory(&(AtaReq->ahci.ahci_cmd_ptr->acmd), Srb->Cdb, 16);
IDE_COMMAND_ATAPI_PACKET /* command */,
0 /* lba */,
(Srb->DataTransferLength >= 0x10000) ? (USHORT)(0xffff) : (USHORT)(Srb->DataTransferLength),
- use_dma ? ATA_F_DMA : 0/* feature */,
- ATA_IMMEDIATE /* flags */
+ use_dma ? ATA_F_DMA : 0/* feature */
);
if(!fis_size) {
return SRB_STATUS_ERROR;
}
+ AtaReq->ahci.io_cmd_flags = UniAtaAhciAdjustIoFlags(0,
+ ((AtaReq->Flags & REQ_FLAG_READ) ? 0 : ATA_AHCI_CMD_WRITE) |
+ (ATA_AHCI_CMD_ATAPI | ATA_AHCI_CMD_PREFETCH),
+ fis_size, DeviceNumber);
+#if 0
AtaReq->ahci.io_cmd_flags = (USHORT)(((AtaReq->Flags & REQ_FLAG_READ) ? 0 : ATA_AHCI_CMD_WRITE) |
/*((LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE) ? (ATA_AHCI_CMD_ATAPI | ATA_AHCI_CMD_PREFETCH) : 0) |*/
(ATA_AHCI_CMD_ATAPI | ATA_AHCI_CMD_PREFETCH) |
(fis_size / sizeof(ULONG)) |
(DeviceNumber << 12));
+#endif
KdPrint2((PRINT_PREFIX "AtapiSendCommand ahci io flags %x: \n", AtaReq->ahci.io_cmd_flags));
}
KdPrint2((PRINT_PREFIX "AtapiSendCommand: !CMD_ACTION_EXEC => SRB_STATUS_PENDING\n"));
return SRB_STATUS_PENDING;
}
- KdPrint3((PRINT_PREFIX "AtapiSendCommand: use_dma=%d\n", use_dma));
+ KdPrint3((PRINT_PREFIX "AtapiSendCommand: use_dma=%d, Cmd %x\n", use_dma, Srb->Cdb[0]));
if(AtaReq->Flags & REQ_FLAG_DMA_OPERATION) {
KdPrint2((PRINT_PREFIX " REQ_FLAG_DMA_OPERATION\n"));
}
- if(Srb->Cdb[0] == SCSIOP_REQUEST_SENSE) {
+ if((Srb->Cdb[0] == SCSIOP_REQUEST_SENSE) /*&& !(deviceExtension->HwFlags & UNIATA_AHCI)*/) {
KdPrint2((PRINT_PREFIX "AtapiSendCommand: SCSIOP_REQUEST_SENSE -> no dma setup (2)\n"));
use_dma = FALSE;
AtaReq->Flags &= ~REQ_FLAG_DMA_OPERATION;
- //AtapiDmaReinit(deviceExtension, LunExt, AtaReq);
+ AtapiDmaReinit(deviceExtension, LunExt, AtaReq);
} if(AtaReq->TransferLength) {
if(!dma_reinited) {
KdPrint2((PRINT_PREFIX "AtapiSendCommand: AtapiDmaReinit()\n"));
KdPrint2((PRINT_PREFIX "AtapiSendCommand: CMD_ACTION_EXEC\n"));
-#ifndef UNIATA_CORE
- // We need to know how many platters our atapi cd-rom device might have.
- // Before anyone tries to send a srb to our target for the first time,
- // we must "secretly" send down a separate mechanism status srb in order to
- // initialize our device extension changer data. That's how we know how
- // many platters our target has.
-
- if (!(LunExt->DeviceFlags & DFLAGS_CHANGER_INITED) &&
- !AtaReq->OriginalSrb) {
-
- ULONG srbStatus;
-
- KdPrint3((PRINT_PREFIX "AtapiSendCommand: BuildMechanismStatusSrb()\n"));
- // Set this flag now. If the device hangs on the mech. status
- // command, we will not have the chance to set it.
- LunExt->DeviceFlags |= DFLAGS_CHANGER_INITED;
-
- chan->MechStatusRetryCount = 3;
- AtaReq->OriginalSrb = Srb;
- AtaReq->Srb = BuildMechanismStatusSrb (
- HwDeviceExtension,
- Srb);
-
- KdPrint3((PRINT_PREFIX "AtapiSendCommand: AtapiSendCommand recursive\n"));
- srbStatus = AtapiSendCommand(HwDeviceExtension, AtaReq->Srb, CMD_ACTION_ALL);
- if (srbStatus == SRB_STATUS_PENDING) {
- KdPrint2((PRINT_PREFIX "AtapiSendCommand: SRB_STATUS_PENDING (2)\n"));
- return srbStatus;
- } else {
- AtaReq->Srb = AtaReq->OriginalSrb;
- AtaReq->OriginalSrb = NULL;
- KdPrint2((PRINT_PREFIX "AtapiSendCommand: AtapiHwInitializeChanger()\n"));
- AtapiHwInitializeChanger (HwDeviceExtension, Srb,
- (PMECHANICAL_STATUS_INFORMATION_HEADER) NULL);
- // fall out
- }
- }
-#endif //UNIATA_CORE
-
- KdPrint3((PRINT_PREFIX "AtapiSendCommand: Command %#x to TargetId %d lun %d\n",
- Srb->Cdb[0], Srb->TargetId, Srb->Lun));
+ KdPrint3((PRINT_PREFIX "AtapiSendCommand: Cdb %x Command %#x to TargetId %d lun %d\n",
+ &(Srb->Cdb), Srb->Cdb[0], Srb->TargetId, Srb->Lun));
// Make sure command is to ATAPI device.
flags = LunExt->DeviceFlags;
return SRB_STATUS_SELECTION_TIMEOUT;
}
retry:
- if(deviceExtension->HwFlags & UNIATA_AHCI) {
- KdPrint2((PRINT_PREFIX "AtapiSendCommand: AHCI, begin transaction\n"));
- if(use_dma) {
- chan->ChannelCtrlFlags |= CTRFLAGS_DMA_OPERATION;
- } else {
- chan->ChannelCtrlFlags &= ~CTRFLAGS_DMA_OPERATION;
- }
- UniataAhciBeginTransaction(HwDeviceExtension, DeviceNumber, lChannel, Srb);
- return SRB_STATUS_PENDING;
- }
-
- // Select device 0 or 1.
+ // Select device 0 or 1. Or more for PM
SelectDrive(chan, DeviceNumber);
// Verify that controller is ready for next command.
GetStatus(chan, statusByte);
KdPrint3((PRINT_PREFIX "AtapiSendCommand: Entered with status %#x\n", statusByte));
- if(statusByte == 0xff) {
+ if(statusByte == IDE_STATUS_WRONG) {
KdPrint2((PRINT_PREFIX "AtapiSendCommand: bad status 0xff on entry\n"));
goto make_reset;
}
goto make_reset;
}
}
+ if(deviceExtension->HwFlags & UNIATA_AHCI) {
+ ULONG CI;
+ // Check if command list is free
+ CI = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_CI);
+ if(CI) {
+ // controller is busy, however we expect it to be free
+ KdPrint2((PRINT_PREFIX "AtapiSendCommand: Controller busy (CI=%#x) -> reset\n", CI));
+ goto make_reset;
+ }
+ }
if(statusByte & IDE_STATUS_ERROR) {
if (Srb->Cdb[0] != SCSIOP_REQUEST_SENSE) {
// Inform the port driver that the bus has been reset.
ScsiPortNotification(ResetDetected, HwDeviceExtension, 0);
// Clean up device extension fields that AtapiStartIo won't.
- chan->ExpectingInterrupt = FALSE;
+ UniataExpectChannelInterrupt(chan, FALSE);
chan->RDP = FALSE;
InterlockedExchange(&(deviceExtension->chan[GET_CHANNEL(Srb)].CheckIntr),
CHECK_INTR_IDLE);
chan->ChannelCtrlFlags &= ~CTRFLAGS_DMA_OPERATION;
}
+ if(deviceExtension->HwFlags & UNIATA_AHCI) {
+ KdPrint2((PRINT_PREFIX "AtapiSendCommand: AHCI, begin transaction\n"));
+ //AtaReq->Flags = ~REQ_FLAG_DMA_OPERATION; // keep proped DMA flag for proper RETRY handling
+ UniataExpectChannelInterrupt(chan, TRUE);
+ UniataAhciBeginTransaction(HwDeviceExtension, lChannel, DeviceNumber, Srb);
+ return SRB_STATUS_PENDING;
+ }
+
statusByte = WaitOnBusy(chan);
KdPrint3((PRINT_PREFIX "AtapiSendCommand: Entry Status (%#x)\n",
statusByte));
KdPrint3((PRINT_PREFIX "AtapiSendCommand: Wait for int. to send packet. Status (%#x)\n",
statusByte));
- chan->ExpectingInterrupt = TRUE;
+ UniataExpectChannelInterrupt(chan, TRUE);
AtaReq->ReqState = REQ_STATE_ATAPI_EXPECTING_CMD_INTR;
InterlockedExchange(&(chan->CheckIntr),
CHECK_INTR_IDLE);
KdPrint2((PRINT_PREFIX "AtapiSendCommand: Poll for int. to send packet. Status (%#x)\n",
statusByte));
- chan->ExpectingInterrupt = TRUE;
+ UniataExpectChannelInterrupt(chan, TRUE);
AtaReq->ReqState = REQ_STATE_ATAPI_DO_NOTHING_INTR;
InterlockedExchange(&(chan->CheckIntr),
CHECK_INTR_IDLE);
statusByte = WaitOnBaseBusy(chan);
// Indicate expecting an interrupt and wait for it.
- chan->ExpectingInterrupt = TRUE;
+ UniataExpectChannelInterrupt(chan, TRUE);
InterlockedExchange(&(chan->CheckIntr),
CHECK_INTR_IDLE);
AtaReq->ReqState = REQ_STATE_ATAPI_EXPECTING_DATA_INTR;
UCHAR lChannel;
PHW_CHANNEL chan;
PCDB cdb;
+ PHW_LU_EXTENSION LunExt;
SetCheckPoint(4);
chan = &(deviceExtension->chan[lChannel]);
//ldev = GET_LDEV(Srb);
DeviceNumber = GET_CDEV(Srb);
+ LunExt = chan->lun[DeviceNumber];
SetCheckPoint(0x40);
if(AtaReq->ReqState < REQ_STATE_PREPARE_TO_TRANSFER)
}
}
+ cdb = (PCDB)(Srb->Cdb);
SetCheckPoint(0x100 | Srb->Cdb[0]);
switch (Srb->Cdb[0]) {
case SCSIOP_INQUIRY:
KdPrint2((PRINT_PREFIX
"IdeSendCommand: SCSIOP_INQUIRY PATH:LUN:TID = %#x:%#x:%#x\n",
Srb->PathId, Srb->Lun, Srb->TargetId));
- // Filter out all TIDs but 0 and 1 since this is an IDE interface
- // which support up to two devices.
+ // Filter out wrong TIDs.
if ((Srb->Lun != 0) ||
(Srb->PathId >= deviceExtension->NumberChannels) ||
- (Srb->TargetId > deviceExtension->NumberLuns)) {
+ (Srb->TargetId >= deviceExtension->NumberLuns)) {
KdPrint2((PRINT_PREFIX
"IdeSendCommand: SCSIOP_INQUIRY rejected\n"));
KdPrint2((PRINT_PREFIX
"IdeSendCommand: SCSIOP_INQUIRY ok\n"));
PINQUIRYDATA inquiryData = (PINQUIRYDATA)(Srb->DataBuffer);
- PIDENTIFY_DATA2 identifyData = &(chan->lun[DeviceNumber]->IdentifyData);
+ PIDENTIFY_DATA2 identifyData = &(LunExt->IdentifyData);
if (!(chan->lun[DeviceNumber]->DeviceFlags & DFLAGS_DEVICE_PRESENT)) {
inquiryData->DeviceType = DIRECT_ACCESS_DEVICE;
// Set the removable bit, if applicable.
- if (chan->lun[DeviceNumber]->DeviceFlags & DFLAGS_REMOVABLE_DRIVE) {
+ if (LunExt->DeviceFlags & DFLAGS_REMOVABLE_DRIVE) {
KdPrint2((PRINT_PREFIX
"RemovableMedia\n"));
inquiryData->RemovableMedia = 1;
}
// Set the Relative Addressing (LBA) bit, if applicable.
- if (chan->lun[DeviceNumber]->DeviceFlags & DFLAGS_LBA_ENABLED) {
+ if (LunExt->DeviceFlags & DFLAGS_LBA_ENABLED) {
inquiryData->RelativeAddressing = 1;
KdPrint2((PRINT_PREFIX
"RelativeAddressing\n"));
// This is used to determine if the media is write-protected.
// Since IDE does not support mode sense then we will modify just the portion we need
// so the higher level driver can determine if media is protected.
- if (chan->lun[DeviceNumber]->DeviceFlags & DFLAGS_MEDIA_STATUS_ENABLED) {
+ if(cdb->MODE_SENSE.PageCode == MODE_PAGE_CACHING) {
+ PMODE_CACHING_PAGE modeData;
- SelectDrive(chan, DeviceNumber);
- AtapiWritePort1(chan, IDX_IO1_o_Command,IDE_COMMAND_GET_MEDIA_STATUS);
- statusByte = WaitOnBusy(chan);
+ KdPrint2((PRINT_PREFIX "MODE_PAGE_CACHING\n"));
+ modeData = (PMODE_CACHING_PAGE)Srb->DataBuffer;
+ if(cdb->MODE_SENSE.AllocationLength < sizeof(MODE_CACHING_PAGE)) {
+ status = STATUS_BUFFER_TOO_SMALL;
+ } else {
+ RtlZeroMemory(modeData, sizeof(MODE_CACHING_PAGE));
+ modeData->PageCode = MODE_PAGE_CACHING;
+ modeData->PageLength = sizeof(MODE_CACHING_PAGE)-sizeof(MODE_PARAMETER_HEADER);
+ modeData->ReadDisableCache = (LunExt->DeviceFlags & DFLAGS_RCACHE_ENABLED) ? 0 : 1;
+ modeData->WriteCacheEnable = (LunExt->DeviceFlags & DFLAGS_WCACHE_ENABLED) ? 1 : 0;
+ Srb->DataTransferLength = sizeof(MODE_CACHING_PAGE);
+ status = SRB_STATUS_SUCCESS;
+ }
+ } else
+ if (LunExt->DeviceFlags & DFLAGS_MEDIA_STATUS_ENABLED) {
- if (!(statusByte & IDE_STATUS_ERROR)){
+ //SelectDrive(chan, DeviceNumber);
+ //AtapiWritePort1(chan, IDX_IO1_o_Command,IDE_COMMAND_GET_MEDIA_STATUS);
+ //statusByte = WaitOnBusy(chan);
+ statusByte = AtaCommand(deviceExtension, DeviceNumber, lChannel, IDE_COMMAND_GET_MEDIA_STATUS, 0, 0, 0, 0, 0, ATA_WAIT_READY);
+
+ if (!(statusByte & IDE_STATUS_ERROR)) {
// no error occured return success, media is not protected
- chan->ExpectingInterrupt = FALSE;
+ UniataExpectChannelInterrupt(chan, FALSE);
InterlockedExchange(&(chan->CheckIntr),
CHECK_INTR_IDLE);
status = SRB_STATUS_SUCCESS;
errorByte = AtapiReadPort1(chan, IDX_IO1_i_Error);
GetBaseStatus(chan, statusByte);
- chan->ExpectingInterrupt = FALSE;
+ UniataExpectChannelInterrupt(chan, FALSE);
InterlockedExchange(&(chan->CheckIntr),
CHECK_INTR_IDLE);
status = SRB_STATUS_SUCCESS;
if (chan->lun[DeviceNumber]->DeviceFlags & DFLAGS_MEDIA_STATUS_ENABLED) {
// Select device 0 or 1.
- SelectDrive(chan, DeviceNumber);
- AtapiWritePort1(chan, IDX_IO1_o_Command,IDE_COMMAND_GET_MEDIA_STATUS);
-
+ //SelectDrive(chan, DeviceNumber);
+ //AtapiWritePort1(chan, IDX_IO1_o_Command,IDE_COMMAND_GET_MEDIA_STATUS);
// Wait for busy. If media has not changed, return success
- statusByte = WaitOnBusy(chan);
+ //statusByte = WaitOnBusy(chan);
+ statusByte = AtaCommand(deviceExtension, DeviceNumber, lChannel, IDE_COMMAND_GET_MEDIA_STATUS, 0, 0, 0, 0, 0, ATA_WAIT_READY);
if (!(statusByte & IDE_STATUS_ERROR)){
- chan->ExpectingInterrupt = FALSE;
+ UniataExpectChannelInterrupt(chan, FALSE);
InterlockedExchange(&(chan->CheckIntr),
CHECK_INTR_IDLE);
status = SRB_STATUS_SUCCESS;
// the 0xDA command will always fail since the write-protect bit
// is sticky,so we can ignore this error
GetBaseStatus(chan, statusByte);
- chan->ExpectingInterrupt = FALSE;
+ UniataExpectChannelInterrupt(chan, FALSE);
InterlockedExchange(&(chan->CheckIntr),
CHECK_INTR_IDLE);
status = SRB_STATUS_SUCCESS;
} else {
// Request sense buffer to be build
- chan->ExpectingInterrupt = TRUE;
+ UniataExpectChannelInterrupt(chan, TRUE);
InterlockedExchange(&(chan->CheckIntr),
CHECK_INTR_IDLE);
status = SRB_STATUS_PENDING;
MOV_DD_SWP( ((PREAD_CAPACITY_DATA)Srb->DataBuffer)->BytesPerBlock, i );
// Calculate last sector.
- if(!(i = (ULONG)chan->lun[DeviceNumber]->NumOfSectors)) {
- i = chan->lun[DeviceNumber]->IdentifyData.SectorsPerTrack *
- chan->lun[DeviceNumber]->IdentifyData.NumberOfHeads *
- chan->lun[DeviceNumber]->IdentifyData.NumberOfCylinders;
+ if(!(i = (ULONG)LunExt->NumOfSectors)) {
+ i = LunExt->IdentifyData.SectorsPerTrack *
+ LunExt->IdentifyData.NumberOfHeads *
+ LunExt->IdentifyData.NumberOfCylinders;
}
i--;
KdPrint2((PRINT_PREFIX
"** IDE disk %#x - #sectors %#x, #heads %#x, #cylinders %#x\n",
Srb->TargetId,
- chan->lun[DeviceNumber]->IdentifyData.SectorsPerTrack,
- chan->lun[DeviceNumber]->IdentifyData.NumberOfHeads,
- chan->lun[DeviceNumber]->IdentifyData.NumberOfCylinders));
+ LunExt->IdentifyData.SectorsPerTrack,
+ LunExt->IdentifyData.NumberOfHeads,
+ LunExt->IdentifyData.NumberOfCylinders));
status = SRB_STATUS_SUCCESS;
statusByte = WaitOnBaseBusy(chan);
// Eject media,
// first select device 0 or 1.
- SelectDrive(chan, DeviceNumber);
- AtapiWritePort1(chan, IDX_IO1_o_Command,IDE_COMMAND_MEDIA_EJECT);
+ //SelectDrive(chan, DeviceNumber);
+ //AtapiWritePort1(chan, IDX_IO1_o_Command,IDE_COMMAND_MEDIA_EJECT);
+ statusByte = AtaCommand(deviceExtension, DeviceNumber, lChannel, IDE_COMMAND_MEDIA_EJECT, 0, 0, 0, 0, 0, ATA_IMMEDIATE);
}
status = SRB_STATUS_SUCCESS;
break;
case SCSIOP_MEDIUM_REMOVAL:
- cdb = (PCDB)Srb->Cdb;
+ cdb = (PCDB)Srb->Cdb;
- statusByte = WaitOnBaseBusy(chan);
+ if(LunExt->IdentifyData.Removable) {
+ statusByte = WaitOnBaseBusy(chan);
- SelectDrive(chan, DeviceNumber);
- if (cdb->MEDIA_REMOVAL.Prevent == TRUE) {
- AtapiWritePort1(chan, IDX_IO1_o_Command,IDE_COMMAND_DOOR_LOCK);
- } else {
- AtapiWritePort1(chan, IDX_IO1_o_Command,IDE_COMMAND_DOOR_UNLOCK);
- }
- status = SRB_STATUS_SUCCESS;
- break;
+ //SelectDrive(chan, DeviceNumber);
+ if (cdb->MEDIA_REMOVAL.Prevent == TRUE) {
+ //AtapiWritePort1(chan, IDX_IO1_o_Command,IDE_COMMAND_DOOR_LOCK);
+ statusByte = AtaCommand(deviceExtension, DeviceNumber, lChannel, IDE_COMMAND_DOOR_LOCK, 0, 0, 0, 0, 0, ATA_IMMEDIATE);
+ } else {
+ //AtapiWritePort1(chan, IDX_IO1_o_Command,IDE_COMMAND_DOOR_UNLOCK);
+ statusByte = AtaCommand(deviceExtension, DeviceNumber, lChannel, IDE_COMMAND_DOOR_UNLOCK, 0, 0, 0, 0, 0, ATA_IMMEDIATE);
+ }
+ status = SRB_STATUS_SUCCESS;
+ } else {
+ status = SRB_STATUS_INVALID_REQUEST;
+ }
+ break;
+#if 0
// Note: I don't implement this, because NTFS driver too often issues this command
// It causes awful performance degrade. However, if somebody wants, I will implement
// SCSIOP_FLUSH_BUFFER/SCSIOP_SYNCHRONIZE_CACHE optionally.
-
-#if 0
case SCSIOP_FLUSH_BUFFER:
case SCSIOP_SYNCHRONIZE_CACHE:
KdPrint2((PRINT_PREFIX
"IdeSendCommand: SCSIOP_REQUEST_SENSE PATH:LUN:TID = %#x:%#x:%#x\n",
Srb->PathId, Srb->Lun, Srb->TargetId));
- if (chan->lun[DeviceNumber]->DeviceFlags & DFLAGS_MEDIA_STATUS_ENABLED) {
+ if (LunExt->DeviceFlags & DFLAGS_MEDIA_STATUS_ENABLED) {
status = IdeBuildSenseBuffer(HwDeviceExtension,Srb);
break;
}
UCHAR statusByte,errorByte;
chan = &(deviceExtension->chan[lChannel]);
+ SelectDrive(chan, DeviceNumber);
if (EnableMSN == TRUE){
*/
if(TopLevel && Srb && Srb->SrbExtension) {
KdPrint2((PRINT_PREFIX "TopLevel\n"));
- RtlZeroMemory(Srb->SrbExtension, sizeof(ATA_REQ));
+ //RtlZeroMemory(Srb->SrbExtension, sizeof(ATA_REQ));
+ UniAtaClearAtaReq(Srb->SrbExtension);
}
do {
((Srb->Function == SRB_FUNCTION_IO_CONTROL) ||
(Srb->Function == SRB_FUNCTION_EXECUTE_SCSI && Srb->Cdb[0] == SCSIOP_INQUIRY))
) {
+ // This is our virtual device
KdPrint2((PRINT_PREFIX
"AtapiStartIo: Communication port\n"));
if(Srb->Function == SRB_FUNCTION_EXECUTE_SCSI) {
// For now we support only Lun=0
// Note: reset is immediate command, it cannot be queued since it is usually used to
- // revert not- responding device to operational state
+ // revert not-responding device to operational state
KdPrint2((PRINT_PREFIX "AtapiStartIo: Reset device request received\n"));
UniataUserDeviceReset(deviceExtension, LunExt, lChannel);
status = SRB_STATUS_SUCCESS;
status = SRB_STATUS_SUCCESS;
break;
- /* case SRB_FUNCTION_SHUTDOWN:
- case SRB_FUNCTION_FLUSH:
-
- // Flush device's cache.
- KdPrint2((PRINT_PREFIX "AtapiStartIo: Device flush received\n"));
-
- if (chan->CurrentSrb) {
-
- KdPrint2((PRINT_PREFIX "AtapiStartIo (SRB_FUNCTION_FLUSH): Already have a request!\n"));
- Srb->SrbStatus = SRB_STATUS_BUSY;
- ScsiPortNotification(RequestComplete,
- deviceExtension,
- Srb);
- return FALSE;
- }
-
- if (LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE) {
- status = SRB_STATUS_SUCCESS;
- } else {
- status = AtaCommand(deviceExtension, GET_CDEV(Srb), GET_CHANNEL(Srb),
- IDE_COMMAND_FLUSH_CACHE, 0, 0, 0, 0, 0, ATA_WAIT_INTR);
- if (status & IDE_STATUS_DRQ) {
- status = SRB_STATUS_SUCCESS;
- } else {
- status = SRB_STATUS_SELECTION_TIMEOUT;
- }
- }
- break;*/
-
case SRB_FUNCTION_IO_CONTROL: {
ULONG len;
status = SRB_STATUS_SELECTION_TIMEOUT;
break;
}
-
+
if (!(LunExt->DeviceFlags & DFLAGS_DEVICE_PRESENT) ||
atapiDev) {
// S M S M
// 3 2 1 0
+ if(chan->DeviceExtension->HwFlags & UNIATA_AHCI) {
+ deviceNumber = 1 << lChannel;
+ } else
if (deviceExtension->NumberChannels == 1) {
if (chan->PrimaryAddress) {
deviceNumber = 1 << DeviceNumber;
deviceNumber = 4 << DeviceNumber;
}
} else {
- deviceNumber = (1 << DeviceNumber) << lChannel;
+ deviceNumber = 1 << (DeviceNumber+lChannel*2);
}
versionParameters->bIDEDeviceMap = deviceNumber;
// Extract the target.
targetId = cmdInParameters.bDriveNumber;
KdPrint2((PRINT_PREFIX "targetId %d\n", targetId));
- if((targetId >= deviceExtension->NumberChannels*2) ||
+ if(deviceExtension->HwFlags & UNIATA_AHCI) {
+ // cheat code for AHCI :)
+ // upper layer assumes that we have 2 devices per channel
+ // TODO: we should invent something to handle PM here
+ targetId /= 2;
+ }
+
+ if((targetId >= deviceExtension->NumberChannels*deviceExtension->NumberLuns) ||
!(deviceExtension->lun[targetId].DeviceFlags & DFLAGS_DEVICE_PRESENT)) {
KdPrint2((PRINT_PREFIX "Error: xxx_ID_CMD for non-existant device\n"));
status = SRB_STATUS_SELECTION_TIMEOUT;
// Set status in SRB.
Srb->SrbStatus = (UCHAR)status;
+ KdPrint2((PRINT_PREFIX "AtapiStartIo: AtapiDmaDBSync(%x, %x)\n", chan, Srb));
AtapiDmaDBSync(chan, Srb);
+ KdPrint2((PRINT_PREFIX "AtapiStartIo: UniataRemoveRequest(%x, %x)\n", chan, Srb));
UniataRemoveRequest(chan, Srb);
// Indicate command complete.
+ KdPrint2((PRINT_PREFIX "AtapiStartIo: ScsiPortNotification\n"));
ScsiPortNotification(RequestComplete,
deviceExtension,
Srb);
+ KdPrint2((PRINT_PREFIX "AtapiStartIo: UniataGetCurRequest\n"));
// Remove current Srb & get next one
if((Srb = UniataGetCurRequest(chan))) {
AtaReq = (PATA_REQ)(Srb->SrbExtension);
Srb = NULL;
}
}
+ KdPrint2((PRINT_PREFIX "AtapiStartIo: chan %x, Src %x\n", chan, Srb));
if(!chan) {
//ASSERT(TopLevel);
}
flags = 0;
command = i;
- KdPrint2((PRINT_PREFIX "cmd %2.2x: ", command));
+ //KdPrint2((PRINT_PREFIX "cmd %2.2x: ", command));
switch(command) {
case IDE_COMMAND_READ_DMA48:
case IDE_COMMAND_WRITE_LOG_DMA48:
case IDE_COMMAND_TRUSTED_RCV_DMA:
case IDE_COMMAND_TRUSTED_SEND_DMA:
- KdPrint2((PRINT_PREFIX "DMA "));
+ case IDE_COMMAND_DATA_SET_MGMT:
+ //KdPrint2((PRINT_PREFIX "DMA "));
flags |= ATA_CMD_FLAG_DMA;
}
switch(command) {
+ case IDE_COMMAND_WRITE_FUA_DMA48:
+ case IDE_COMMAND_WRITE_FUA_DMA_Q48:
+ case IDE_COMMAND_WRITE_MUL_FUA48:
+
+ flags |= ATA_CMD_FLAG_FUA;
+ /* FALL THROUGH */
+
case IDE_COMMAND_READ48:
case IDE_COMMAND_READ_DMA48:
case IDE_COMMAND_READ_DMA_Q48:
case IDE_COMMAND_WRITE_MUL48:
case IDE_COMMAND_WRITE_STREAM_DMA48:
case IDE_COMMAND_WRITE_STREAM48:
- case IDE_COMMAND_WRITE_FUA_DMA48:
- case IDE_COMMAND_WRITE_FUA_DMA_Q48:
- case IDE_COMMAND_WRITE_MUL_FUA48:
case IDE_COMMAND_FLUSH_CACHE48:
case IDE_COMMAND_VERIFY48:
- KdPrint2((PRINT_PREFIX "48 "));
+ //KdPrint2((PRINT_PREFIX "48 "));
flags |= ATA_CMD_FLAG_48;
/* FALL THROUGH */
case IDE_COMMAND_FLUSH_CACHE:
case IDE_COMMAND_VERIFY:
- KdPrint2((PRINT_PREFIX "LBA "));
+ //KdPrint2((PRINT_PREFIX "LBA "));
flags |= ATA_CMD_FLAG_LBAIOsupp;
}
+ switch(command) {
+ case IDE_COMMAND_READ_NATIVE_SIZE48:
+ case IDE_COMMAND_SET_NATIVE_SIZE48:
+ // we cannot set LBA flag for these commands to avoid BadBlock handling
+ //flags |= ATA_CMD_FLAG_LBAIOsupp;
+ flags |= ATA_CMD_FLAG_48;
+
+ case IDE_COMMAND_READ_NATIVE_SIZE:
+ case IDE_COMMAND_SET_NATIVE_SIZE:
+
+ flags |= ATA_CMD_FLAG_LBAIOsupp | ATA_CMD_FLAG_FUA;
+ }
+
flags |= ATA_CMD_FLAG_48supp;
switch (command) {
case IDE_COMMAND_VERIFY:
command = IDE_COMMAND_VERIFY48; break;
default:
- KdPrint2((PRINT_PREFIX "!28->48 "));
+ //KdPrint2((PRINT_PREFIX "!28->48 "));
flags &= ~ATA_CMD_FLAG_48supp;
}
- KdPrint2((PRINT_PREFIX "\t -> %2.2x (%2.2x)\n", command, flags));
+ switch (command) {
+ case IDE_COMMAND_READ:
+ case IDE_COMMAND_READ_MULTIPLE:
+ case IDE_COMMAND_READ_DMA48:
+ case IDE_COMMAND_READ_DMA_Q48:
+ case IDE_COMMAND_READ_STREAM_DMA48:
+ case IDE_COMMAND_READ_STREAM48:
+ case IDE_COMMAND_READ_DMA_Q:
+ case IDE_COMMAND_READ_DMA:
+ case IDE_COMMAND_READ_LOG_DMA48:
+ case IDE_COMMAND_TRUSTED_RCV_DMA:
+ case IDE_COMMAND_IDENTIFY:
+ case IDE_COMMAND_ATAPI_IDENTIFY:
+ //KdPrint2((PRINT_PREFIX "RD "));
+ flags |= ATA_CMD_FLAG_In;
+ break;
+ case IDE_COMMAND_WRITE:
+ case IDE_COMMAND_WRITE_MULTIPLE:
+ case IDE_COMMAND_WRITE_DMA48:
+ case IDE_COMMAND_WRITE_DMA_Q48:
+ case IDE_COMMAND_WRITE_DMA:
+ case IDE_COMMAND_WRITE_DMA_Q:
+ case IDE_COMMAND_WRITE_STREAM_DMA48:
+ case IDE_COMMAND_WRITE_STREAM48:
+ case IDE_COMMAND_WRITE_FUA_DMA48:
+ case IDE_COMMAND_WRITE_FUA_DMA_Q48:
+ //KdPrint2((PRINT_PREFIX "WR "));
+ flags |= ATA_CMD_FLAG_Out;
+ break;
+ }
+
+ //KdPrint2((PRINT_PREFIX "\t -> %2.2x (%2.2x)\n", command, flags));
AtaCommands48[i] = command;
AtaCommandFlags[i] = flags;
}
return status;
}
#endif // USE_REACTOS_DDK
- KdPrint(("UniATA Init: OS ver %x.%x (%d)\n", MajorVersion, MinorVersion, BuildNumber));
+ KdPrint(("UniATA Init: OS ver %x.%x (%d), %d CPU(s)\n", MajorVersion, MinorVersion, BuildNumber, *KeNumberProcessors));
KeQuerySystemTime(&t0);
do {
switch(g_opt_VirtualMachine) {
case VM_VBOX:
+ KdPrint2((PRINT_PREFIX "adjust options for VirtualBox\n"));
// adjust options for VirtualBox
g_opt_WaitBusyCount = 20000;
g_opt_WaitBusyDelay = 150;
g_opt_WaitDrqDelay = 100;
+ g_opt_WaitBusyLongCount = 20000;
+ g_opt_MaxIsrWait = 200;
g_opt_AtapiSendDisableIntr = 0;
g_opt_AtapiDmaRawRead = FALSE;
break;
}
+ if(!hasPCI) {
+ KdPrint2((PRINT_PREFIX "old slow machine, adjust timings\n"));
+ // old slow machine, adjust timings
+ g_opt_WaitBusyCount = 20000;
+ g_opt_WaitBusyDelay = 150;
+ g_opt_WaitDrqDelay = 100;
+ g_opt_WaitBusyLongCount = 20000;
+ g_opt_MaxIsrWait = 200;
+ }
+
g_opt_WaitBusyCount = AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"WaitBusyCount", g_opt_WaitBusyCount); // 200 vs 20000
g_opt_WaitBusyDelay = AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"WaitBusyDelay", g_opt_WaitBusyDelay); // 10 vs 150
g_opt_WaitDrqDelay = AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"WaitDrqDelay", g_opt_WaitDrqDelay); // 10 vs 100
+ g_opt_WaitBusyLongCount = AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"WaitBusyLongCount", g_opt_WaitBusyLongCount); // 2000 vs 20000
+ g_opt_WaitBusyLongDelay = AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"WaitBusyLongDelay", g_opt_WaitBusyLongDelay); // 250 vs 250
g_opt_AtapiSendDisableIntr = (BOOLEAN)AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"AtapiSendDisableIntr", g_opt_AtapiSendDisableIntr); // 1 vs 0
g_opt_AtapiDmaRawRead = (BOOLEAN)AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"AtapiDmaRawRead", g_opt_AtapiDmaRawRead); // 1 vs 0
-
+ g_opt_MaxIsrWait = AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"MaxIsrWait", g_opt_MaxIsrWait); // 40 vs xxx
}
// Look for legacy ISA-bridged PCI IDE controller (onboard)
hwInitializationData.comm.DeviceId = 0;
hwInitializationData.comm.DeviceIdLength = 0;
+ if(!BMListLen) {
+ hwInitializationData.comm.SrbExtensionSize = FIELD_OFFSET(ATA_REQ, ata);
+ KdPrint2((PRINT_PREFIX "using AtaReq sz %x\n", hwInitializationData.comm.SrbExtensionSize));
+ }
+
// The adapter count is used by the find adapter routine to track how
// which adapter addresses have been tested.
for(i=0; i<Length; i++) {
cDevSerial[i] = (UCHAR)(DevSerial[i]);
}
+ cDevSerial[i] = 0;
KdPrint(( "S/N:%s\n", cDevSerial));
#endif
/*++
-Copyright (c) 2002-2011 Alexander A. Telyatnikov (Alter)
+Copyright (c) 2002-2012 Alexander A. Telyatnikov (Alter)
Module Name:
id_dma.cpp
IN ULONG channel // physical channel number (0-1)
);
-#define ATAPI_DEVICE(de, ldev) (de->lun[ldev].DeviceFlags & DFLAGS_ATAPI_DEVICE)
-
ULONG
NTAPI
AtapiVirtToPhysAddr_(
IN PVOID HwDeviceExtension,
IN PSCSI_REQUEST_BLOCK Srb,
IN PUCHAR data,
- IN PULONG count,
+ OUT PULONG count, /* bytes */
OUT PULONG ph_addru
)
{
IN ULONG lChannel, // logical channel,
IN PSCSI_REQUEST_BLOCK Srb,
IN PUCHAR data,
- IN ULONG count
+ IN ULONG count /* bytes */
)
{
PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
ULONG dma_count, dma_base, dma_baseu;
+ ULONG dma_count0, dma_base0;
ULONG i;
PHW_CHANNEL chan = &(deviceExtension->chan[lChannel]);
PATA_REQ AtaReq = (PATA_REQ)(Srb->SrbExtension);
BOOLEAN use_AHCI = (deviceExtension->HwFlags & UNIATA_AHCI) ? TRUE : FALSE;
ULONG orig_count = count;
ULONG max_entries = use_AHCI ? ATA_AHCI_DMA_ENTRIES : ATA_DMA_ENTRIES;
+ //ULONG max_frag = use_AHCI ? (0x3fffff+1) : (4096); // DEBUG, replace 4096 for procer chipset-specific value
+ ULONG max_frag = deviceExtension->DmaSegmentLength;
+ ULONG seg_align = deviceExtension->DmaSegmentAlignmentMask;
+ if(AtaReq->dma_entries) {
+ KdPrint2((PRINT_PREFIX "AtapiDmaSetup: already setup, %d entries\n", AtaReq->dma_entries));
+ return TRUE;
+ }
+ AtaReq->ata.dma_base = 0;
AtaReq->Flags &= ~REQ_FLAG_DMA_OPERATION;
KdPrint2((PRINT_PREFIX "AtapiDmaSetup: mode %#x, data %x, count %x, lCh %x, dev %x\n",
//KdPrint2((PRINT_PREFIX " checkpoint 4\n" ));
if(use_AHCI) {
- KdPrint2((PRINT_PREFIX " get Phys(AHCI_CMD=%x)\n", &(AtaReq->ahci.ahci_cmd_ptr->prd_tab) ));
- dma_base = AtapiVirtToPhysAddr(HwDeviceExtension, NULL, (PUCHAR)&(AtaReq->ahci.ahci_cmd_ptr->prd_tab), &i, &dma_baseu);
- AtaReq->ahci.ahci_base64 = NULL; // clear before setup
+ KdPrint2((PRINT_PREFIX " get Phys(AHCI_CMD=%x)\n", AtaReq->ahci.ahci_cmd_ptr ));
+ dma_base = AtapiVirtToPhysAddr(HwDeviceExtension, NULL, (PUCHAR)(AtaReq->ahci.ahci_cmd_ptr), &i, &dma_baseu);
+ AtaReq->ahci.ahci_base64 = 0; // clear before setup
} else {
KdPrint2((PRINT_PREFIX " get Phys(PRD=%x)\n", &(AtaReq->dma_tab) ));
dma_base = AtapiVirtToPhysAddr(HwDeviceExtension, NULL, (PUCHAR)&(AtaReq->dma_tab) /*chan->dma_tab*/, &i, &dma_baseu);
KdPrint2((PRINT_PREFIX "AtapiDmaSetup: No BASE\n" ));
return FALSE;
}
- AtaReq->ata.dma_base = dma_base; // aliased to ahci_base64
+ AtaReq->ata.dma_base = dma_base; // aliased to AtaReq->ahci.ahci_base64
- KdPrint2((PRINT_PREFIX " get Phys(data=%x)\n", data ));
+ KdPrint2((PRINT_PREFIX " get Phys(data[0]=%x)\n", data ));
dma_base = AtapiVirtToPhysAddr(HwDeviceExtension, Srb, data, &dma_count, &dma_baseu);
if(dma_baseu) {
KdPrint2((PRINT_PREFIX "AtapiDmaSetup: 1st block of buffer above 4Gb: %8.8x%8.8x\n", dma_baseu, dma_base));
count -= dma_count;
i = 0;
+ dma_count0 = dma_count;
+ dma_base0 = dma_base;
+
while (count) {
+/* KdPrint2((PRINT_PREFIX " segments %#x+%#x == %#x && %#x+%#x <= %#x\n",
+ dma_base0, dma_count0, dma_base,
+ dma_count0, dma_count, max_frag));*/
+ if(dma_base0+dma_count0 == dma_base &&
+ dma_count0+dma_count <= max_frag) {
+ // 'i' should be always > 0 here
+ // for BM we cannot cross 64k boundary
+ if(dma_base & seg_align) {
+ //KdPrint2((PRINT_PREFIX " merge segments\n" ));
+ ASSERT(i);
+ //BrutePoint();
+ i--;
+ dma_base = dma_base0;
+ dma_count += dma_count0;
+ }
+ }
if(use_AHCI) {
AtaReq->ahci.ahci_cmd_ptr->prd_tab[i].base = dma_base;
AtaReq->ahci.ahci_cmd_ptr->prd_tab[i].baseu = dma_baseu;
- AtaReq->ahci.ahci_cmd_ptr->prd_tab[i].DBC = ((dma_count-1) & 0x3fffff);
+ AtaReq->ahci.ahci_cmd_ptr->prd_tab[i].Reserved1 = 0;
+ *((PULONG)&(AtaReq->ahci.ahci_cmd_ptr->prd_tab[i].DBC_ULONG)) = ((dma_count-1) & 0x3fffff);
+/* AtaReq->ahci.ahci_cmd_ptr->prd_tab[i].Reserved2 = 0;
+ AtaReq->ahci.ahci_cmd_ptr->prd_tab[i].I = 0;*/
+ KdPrint2((PRINT_PREFIX " ph data[%d]=%x:%x (%x)\n", i, dma_baseu, dma_base, AtaReq->ahci.ahci_cmd_ptr->prd_tab[i].DBC));
} else {
AtaReq->dma_tab[i].base = dma_base;
AtaReq->dma_tab[i].count = (dma_count & 0xffff);
}
+ dma_count0 = dma_count;
+ dma_base0 = dma_base;
i++;
if (i >= max_entries) {
KdPrint2((PRINT_PREFIX "too many segments in DMA table\n" ));
AtaReq->ahci.ahci_base64 = NULL;
return FALSE;
}
- KdPrint2((PRINT_PREFIX " get Phys(data[n]=%x)\n", data ));
+ KdPrint2((PRINT_PREFIX " get Phys(data[n=%d]=%x)\n", i, data ));
dma_base = AtapiVirtToPhysAddr(HwDeviceExtension, Srb, data, &dma_count, &dma_baseu);
if(dma_baseu) {
KdPrint2((PRINT_PREFIX "AtapiDmaSetup: block of buffer above 4Gb: %8.8x%8.8x\n", dma_baseu, dma_base));
count -= min(count, PAGE_SIZE);
}
KdPrint2((PRINT_PREFIX " set TERM\n" ));
+/* KdPrint2((PRINT_PREFIX " segments %#x+%#x == %#x && #x+%#x <= %#x\n",
+ dma_base0, dma_count0, dma_base,
+ dma_count0, dma_count, max_frag));*/
+ if(dma_base0+dma_count0 == dma_base &&
+ dma_count0+dma_count <= max_frag) {
+ // 'i' should be always > 0 here
+ if(dma_base & seg_align) {
+ //KdPrint2((PRINT_PREFIX " merge segments\n" ));
+ //BrutePoint();
+ ASSERT(i);
+ i--;
+ dma_base = dma_base0;
+ dma_count += dma_count0;
+ }
+ }
if(use_AHCI) {
AtaReq->ahci.ahci_cmd_ptr->prd_tab[i].base = dma_base;
AtaReq->ahci.ahci_cmd_ptr->prd_tab[i].baseu = dma_baseu;
- AtaReq->ahci.ahci_cmd_ptr->prd_tab[i].DBC = ((dma_count-1) & 0x3fffff);
+ AtaReq->ahci.ahci_cmd_ptr->prd_tab[i].Reserved1 = 0;
+ //AtaReq->ahci.ahci_cmd_ptr->prd_tab[i].DBC = ((dma_count-1) & 0x3fffff);
+ //AtaReq->ahci.ahci_cmd_ptr->prd_tab[i].Reserved2 = 0;
+ *((PULONG)&(AtaReq->ahci.ahci_cmd_ptr->prd_tab[i].DBC_ULONG)) = ((dma_count-1) & 0x3fffff);
+ //AtaReq->ahci.ahci_cmd_ptr->prd_tab[i].I = 1; // interrupt when ready
+ KdPrint2((PRINT_PREFIX " ph data[%d]=%x:%x (%x)\n", i, dma_baseu, dma_base, AtaReq->ahci.ahci_cmd_ptr->prd_tab[i].DBC));
+ if(((ULONG)&(AtaReq->ahci.ahci_cmd_ptr->prd_tab) & ~PAGE_MASK) != ((ULONG)&(AtaReq->ahci.ahci_cmd_ptr->prd_tab[i]) & ~PAGE_MASK)) {
+ KdPrint2((PRINT_PREFIX "PRD table crosses page boundary! %x vs %x\n",
+ &AtaReq->ahci.ahci_cmd_ptr->prd_tab, &(AtaReq->ahci.ahci_cmd_ptr->prd_tab[i]) ));
+ //AtaReq->Flags |= REQ_FLAG_DMA_DBUF_PRD;
+ }
} else {
AtaReq->dma_tab[i].base = dma_base;
AtaReq->dma_tab[i].count = (dma_count & 0xffff) | ATA_DMA_EOT;
+ if(((ULONG)&(AtaReq->dma_tab) & ~PAGE_MASK) != ((ULONG)&(AtaReq->dma_tab[i]) & ~PAGE_MASK)) {
+ KdPrint2((PRINT_PREFIX "DMA table crosses page boundary! %x vs %x\n",
+ &AtaReq->dma_tab, &(AtaReq->dma_tab[i]) ));
+ //AtaReq->Flags |= REQ_FLAG_DMA_DBUF_PRD;
+ }
}
- AtaReq->dma_entries = i;
+ AtaReq->dma_entries = i+1;
if(use_DB_IO) {
AtaReq->Flags |= REQ_FLAG_DMA_DBUF;
if(deviceExtension->HwFlags & UNIATA_AHCI) {
KdPrint2((PRINT_PREFIX " ACHTUNG! should not be called for AHCI!\n"));
- return 0xff;
+ return IDE_STATUS_WRONG;
}
switch(VendorID) {
{
SCHAR apiomode;
+ if((deviceExtension->HwFlags & UNIATA_AHCI) &&
+ !(LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE)) {
+ // skip unnecessary checks
+ KdPrint2((PRINT_PREFIX "AtapiDmaReinit: ahci, nothing to do for HDD\n"));
+ return;
+ }
+
apiomode = (CHAR)AtaPioMode(&(LunExt->IdentifyData));
if(!(AtaReq->Flags & REQ_FLAG_DMA_OPERATION)) {
if(deviceExtension->HwFlags & UNIATA_AHCI) {
if(!AtaReq->ahci.ahci_base64) {
KdPrint2((PRINT_PREFIX
- "AtapiDmaReinit: no AHCI PRD, fall to PIO on Device %d\n", LunExt->Lun));
- goto limit_pio;
+ "AtapiDmaReinit: no AHCI PRD, fatal on Device %d\n", LunExt->Lun));
+ goto exit;
}
} else
if(!AtaReq->ata.dma_base) {
"AtapiDmaReinit: restore IO mode on Device %d\n", LunExt->Lun));
AtapiDmaInit__(deviceExtension, LunExt);
}
+
+exit:
+ return;
} // end AtapiDmaReinit()
VOID
LONG statusByte = 0;
CHAR apiomode;
- statusByte = AtaCommand(deviceExtension, DeviceNumber, lChannel,
- IDE_COMMAND_SET_FEATURES, 0, 0, 0,
- (UCHAR)((mode > ATA_UDMA6) ? ATA_UDMA6 : mode), ATA_C_F_SETXFER, ATA_WAIT_BASE_READY);
+ if(LunExt->DeviceFlags & DFLAGS_MANUAL_CHS) {
+ statusByte = mode <= ATA_PIO2 ? IDE_STATUS_IDLE : IDE_STATUS_ERROR;
+ } else {
+ if(deviceExtension->HwFlags & UNIATA_AHCI) {
+ AtapiDisableInterrupts(deviceExtension, lChannel);
+ }
+ statusByte = AtaCommand(deviceExtension, DeviceNumber, lChannel,
+ IDE_COMMAND_SET_FEATURES, 0, 0, 0,
+ (UCHAR)((mode > ATA_UDMA6) ? ATA_UDMA6 : mode), ATA_C_F_SETXFER, ATA_WAIT_BASE_READY);
+ if(deviceExtension->HwFlags & UNIATA_AHCI) {
+ AtapiEnableInterrupts(deviceExtension, lChannel);
+ }
+ }
if(statusByte & IDE_STATUS_ERROR) {
KdPrint3((PRINT_PREFIX " wait ready after error\n"));
if(LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE) {
PHW_CHANNEL chan = &deviceExtension->chan[lChannel];
//LONG statusByte = 0;
ULONG dev = Channel*2 + DeviceNumber; // for non-SATA/AHCI only!
- ULONG ldev = lChannel*2 + DeviceNumber; // for non-SATA/AHCI only!
+ //ULONG ldev = lChannel*2 + DeviceNumber; // for non-SATA/AHCI only!
+ BOOLEAN isAtapi = ATAPI_DEVICE(chan, DeviceNumber);
ULONG slotNumber = deviceExtension->slotNumber;
ULONG SystemIoBusNumber = deviceExtension->SystemIoBusNumber;
LONG i;
PHW_LU_EXTENSION LunExt = chan->lun[DeviceNumber];
+ UCHAR ModeByte;
ULONG VendorID = deviceExtension->DevID & 0xffff;
//ULONG DeviceID = (deviceExtension->DevID >> 16) & 0xffff;
apiomode = 0;
}
- SelectDrive(chan, DeviceNumber);
- GetStatus(chan, statusByte);
- // we can see here IDE_STATUS_ERROR status after previous operation
- if(statusByte & IDE_STATUS_ERROR) {
- KdPrint2((PRINT_PREFIX "IDE_STATUS_ERROR detected on entry, statusByte = %#x\n", statusByte));
- //GetBaseStatus(chan, statusByte);
- }
- if(statusByte && UniataIsIdle(deviceExtension, statusByte & ~IDE_STATUS_ERROR) != IDE_STATUS_IDLE) {
- KdPrint2((PRINT_PREFIX "Can't setup transfer mode: statusByte = %#x\n", statusByte));
- return;
- }
+ //if(!(ChipFlags & UNIATA_AHCI)) {
- if(deviceExtension->UnknownDev) {
- KdPrint2((PRINT_PREFIX "Unknown chip, omit Vendor/Dev checks\n"));
- goto try_generic_dma;
- }
+ // this is necessary for future PM support
+ SelectDrive(chan, DeviceNumber);
+ GetStatus(chan, statusByte);
+ // we can see here IDE_STATUS_ERROR status after previous operation
+ if(statusByte & IDE_STATUS_ERROR) {
+ KdPrint2((PRINT_PREFIX "IDE_STATUS_ERROR detected on entry, statusByte = %#x\n", statusByte));
+ //GetBaseStatus(chan, statusByte);
+ }
+ if(statusByte && UniataIsIdle(deviceExtension, statusByte & ~IDE_STATUS_ERROR) != IDE_STATUS_IDLE) {
+ KdPrint2((PRINT_PREFIX "Can't setup transfer mode: statusByte = %#x\n", statusByte));
+ return;
+ }
+ //}
if(UniataIsSATARangeAvailable(deviceExtension, lChannel)) {
- //if(ChipFlags & UNIATA_SATA) {
+ //if(ChipFlags & (UNIATA_SATA | UNIATA_AHCI)) {
/****************/
/* SATA Generic */
/****************/
- UCHAR ModeByte;
KdPrint2((PRINT_PREFIX "SATA Generic\n"));
if(udmamode > 5) {
if(AtaSetTransferMode(deviceExtension, DeviceNumber, lChannel, LunExt, min(LunExt->LimitedTransferMode, LunExt->OrigTransferMode))) {
return;
}
- udmamode = min(udmamode, 5);
+ udmamode = min(udmamode, 6);
} else {
KdPrint2((PRINT_PREFIX "SATA -> PATA adapter ?\n"));
udmamode = 2;
apiomode = min( apiomode, (CHAR)(LunExt->LimitedTransferMode - ATA_PIO0));
} else {
- udmamode = min(udmamode, 5);
+ udmamode = min(udmamode, 6);
}
}
}
AtaSetTransferMode(deviceExtension, DeviceNumber, lChannel, LunExt, ModeByte);
return;
}
+
+ if(deviceExtension->UnknownDev) {
+ KdPrint2((PRINT_PREFIX "Unknown chip, omit Vendor/Dev checks\n"));
+ goto try_generic_dma;
+ }
+
if(udmamode > 2 && !LunExt->IdentifyData.HwResCableId) {
- KdPrint2((PRINT_PREFIX "AtapiDmaInit: DMA limited to UDMA33, non-ATA66 compliant cable\n"));
- udmamode = 2;
- apiomode = min( apiomode, (CHAR)(LunExt->LimitedTransferMode - ATA_PIO));
+ if(LunExt->IdentifyData.SataCapabilities != 0x0000 &&
+ LunExt->IdentifyData.SataCapabilities != 0xffff) {
+ KdPrint2((PRINT_PREFIX "AtapiDmaInit: SATA beyond adapter or Controller compat mode\n"));
+ } else {
+ KdPrint2((PRINT_PREFIX "AtapiDmaInit: DMA limited to UDMA33, non-ATA66 compliant cable\n"));
+ udmamode = 2;
+ apiomode = min( apiomode, (CHAR)(LunExt->LimitedTransferMode - ATA_PIO));
+ }
}
KdPrint2((PRINT_PREFIX "Setup chip a:w:u=%d:%d:%d\n",
/* the older Aladdin doesn't support ATAPI DMA on both master & slave */
if ((ChipFlags & ALIOLD) &&
(udmamode >= 0 || wdmamode >= 0)) {
- if(ATAPI_DEVICE(deviceExtension, lChannel*2) &&
- ATAPI_DEVICE(deviceExtension, lChannel*2 + 1)) {
+ if(ATAPI_DEVICE(chan, 0) &&
+ ATAPI_DEVICE(chan, 1)) {
// 2 devices on this channel - NO DMA
chan->MaxTransferMode =
min(chan->MaxTransferMode, ATA_PIO4);
SetPciConfig2(0x4a, (reg4a & ~(0x3 << (dev<<2))) |
(0x01 + !(i & 0x01)) );
}
- if(i >= 3) {
+ if(i >= 2) {
reg54 |= (0x1 << dev);
} else {
reg54 &= ~(0x1 << dev);
GetPciConfig1(0x44, reg44);
/* Allow PIO/WDMA timing controls. */
- reg40 &= ~0x00ff00ff;
- reg40 |= ~0x40774077;
+ mask40 = 0x000000ff;
/* Set PIO/WDMA timings. */
if(!(DeviceNumber & 1)) {
mask40 |= 0x00003300;
new44 = ((intel_timings[idx] & 0x30) >> 2) |
(intel_timings[idx] & 0x03);
}
+ new40 |= 0x00004077;
if (Channel) {
mask40 <<= 16;
/* Promise */
/***********/
if(ChipType < PRTX) {
- if (ATAPI_DEVICE(deviceExtension, ldev)) {
+ if (isAtapi) {
udmamode =
wdmamode = -1;
}
reg40 &= 0xff00;
reg40 |= 0x4033;
- if(!(ldev & 1)) {
- reg40 |= (ATAPI_DEVICE(deviceExtension, ldev) ? 0x04 : 0x00);
+ if(!(DeviceNumber & 1)) {
+ reg40 |= (isAtapi ? 0x04 : 0x00);
mask40 = 0x3300;
new40 = timing << 8;
} else {
- reg40 |= (ATAPI_DEVICE(deviceExtension, ldev) ? 0x40 : 0x00);
+ reg40 |= (isAtapi ? 0x40 : 0x00);
mask44 = 0x0f;
new44 = ((timing & 0x30) >> 2) |
(timing & 0x03);
/* unknown controller chip */
/* better not try generic DMA on ATAPI devices it almost never works */
- if (ATAPI_DEVICE(deviceExtension, ldev)) {
+ if (isAtapi) {
KdPrint2((PRINT_PREFIX "ATAPI on unknown controller -> PIO\n"));
udmamode =
wdmamode = -1;
/* if controller says its setup for DMA take the easy way out */
/* the downside is we dont know what DMA mode we are in */
if ((udmamode >= 0 || /*wdmamode > 1*/ wdmamode >= 0) &&
- /*deviceExtension->BaseIoAddressBM[lChannel]*/ deviceExtension->BusMaster &&
+ /*deviceExtension->BaseIoAddressBM[lChannel]*/ (deviceExtension->BusMaster==DMA_MODE_BM) &&
(GetDmaStatus(deviceExtension, lChannel) &
- (!(ldev & 1) ?
+ (!(DeviceNumber & 1) ?
BM_STATUS_DRIVE_0_DMA : BM_STATUS_DRIVE_1_DMA))) {
// LunExt->TransferMode = ATA_DMA;
// return;
/*++
-Copyright (c) 2004-2011 Alexandr A. Telyatnikov (Alter)
+Copyright (c) 2004-2012 Alexandr A. Telyatnikov (Alter)
Module Name:
id_init.cpp
deviceExtension->NumberChannels = 1;
}
if(AtapiRegCheckDevValue(deviceExtension, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"IgnoreAhciPM", 1 /* DEBUG */)) {
- KdPrint2((PRINT_PREFIX "SATA/AHCI w/o PM, max luns 1\n"));
- deviceExtension->NumberLuns = 2;
+ KdPrint2((PRINT_PREFIX "SATA/AHCI w/o PM, max luns 1 or 2\n"));
+ deviceExtension->NumberLuns = 2; // we may be in Legacy mode
//chan->ChannelCtrlFlags |= CTRFLAGS_NO_SLAVE;
} else {
KdPrint2((PRINT_PREFIX "SATA/AHCI -> possible PM, max luns %d\n", SATA_MAX_PM_UNITS));
if(ChipFlags & SIIBUG) {
/* work around errata in early chips */
- ConfigInfo->AlignmentMask = 0x1fff;
- deviceExtension->MaximumDmaTransferLength = 15 * DEV_BSIZE;
+ deviceExtension->DmaSegmentLength = 15 * DEV_BSIZE;
+ deviceExtension->DmaSegmentAlignmentMask = 8192-1;
}
if(ChipType != SIIMIO) {
break;
deviceExtension->MaxTransferMode = BaseIoAddressBM ? ATA_DMA : ATA_PIO4;
ConfigInfo->MaximumTransferLength = DEV_BSIZE*256;
deviceExtension->MaximumDmaTransferLength = ConfigInfo->MaximumTransferLength;
+ //deviceExtension->NumberOfPhysicalBreaks = min(deviceExtension->MaximumDmaTransferLength/PAGE_SIZE+1, ATA_DMA_ENTRIES);
+ deviceExtension->DmaSegmentLength = 0x10000;
+ deviceExtension->DmaSegmentAlignmentMask = 0xffff;
KdPrint2((PRINT_PREFIX "i: %#x\n", i));
if(i != BMLIST_TERMINATOR) {
DevTypeInfo = (PBUSMASTER_CONTROLLER_INFORMATION)&BusMasterAdapters[i];
} else {
+unknown_dev:
if(Ata_is_ahci_dev(pciData)) {
KdPrint2((PRINT_PREFIX " AHCI candidate"));
KdPrint2((PRINT_PREFIX " AHCI init failed - not detected\n"));
return STATUS_UNSUCCESSFUL;
}
- KdPrint2((PRINT_PREFIX " unknown AHCI dev, addr %#x", deviceExtension->BaseIoAHCI_0.Addr));
+ KdPrint2((PRINT_PREFIX " unknown AHCI dev, addr %#x ", deviceExtension->BaseIoAHCI_0.Addr));
}
-unknown_dev:
- KdPrint2((PRINT_PREFIX " unknown dev, BM addr %#I64x", BaseIoAddressBM));
+ KdPrint2((PRINT_PREFIX " unknown dev, BM addr %#x ", BaseIoAddressBM));
DevTypeInfo = NULL;
KdPrint2((PRINT_PREFIX " MaxTransferMode %#x\n", deviceExtension->MaxTransferMode));
if(!UniataAllocateLunExt(deviceExtension, UNIATA_ALLOCATE_NEW_LUNS)) {
return STATUS_UNSUCCESSFUL;
}
-
- return STATUS_NOT_FOUND;
+ // DEBUG, we shall return success when AHCI is completly supported
+ //return STATUS_NOT_FOUND;
+ return STATUS_SUCCESS;
}
static BUSMASTER_CONTROLLER_INFORMATION const SiSAdapters[] = {
deviceExtension->BaseIoAddressBM_0);
deviceExtension->BaseIoAddressBM_0 = 0;
- deviceExtension->BusMaster = FALSE;
+ deviceExtension->BusMaster = DMA_MODE_NONE;
deviceExtension->MaxTransferMode = ATA_PIO4;
break;
/* if BAR(5) is IO it should point to SATA interface registers */
if(deviceExtension->DevID == 0x28288086 &&
pciData->u.type0.SubVendorID == 0x106b) {
- BaseMemAddress = 0;
+ /* Skip BAR(5) on ICH8M Apples, system locks up on access. */
KdPrint2((PRINT_PREFIX "Ignore BAR5 on ICH8M Apples\n"));
+ BaseMemAddress = 0;
} else {
- /* Skip BAR(5) on ICH8M Apples, system locks up on access. */
BaseMemAddress = AtapiGetIoRange(HwDeviceExtension, ConfigInfo, pciData, SystemIoBusNumber,
5, 0, 0x10);
if(BaseMemAddress && (*ConfigInfo->AccessRanges)[5].RangeInMemory) {
}
tmp32 = AtapiRegCheckDevValue(deviceExtension, channel, DeviceNumber, L"GeomType", 0xffffffff);
- if(tmp32 > 2) {
+ if(tmp32 > GEOM_MANUAL) {
tmp32 = 0xffffffff;
}
LunExt->opt_GeomType = tmp32;
+ if(tmp32 == GEOM_MANUAL) {
+ LunExt->DeviceFlags |= DFLAGS_MANUAL_CHS;
+ LunExt->opt_GeomType = GEOM_ORIG;
+ // assume IdentifyData is already zero-filled
+ tmp32 = AtapiRegCheckDevValue(deviceExtension, channel, DeviceNumber, L"C", 0);
+ LunExt->IdentifyData.NumberOfCurrentCylinders =
+ LunExt->IdentifyData.NumberOfCylinders = (USHORT)tmp32;
+ tmp32 = AtapiRegCheckDevValue(deviceExtension, channel, DeviceNumber, L"H", 0);
+ LunExt->IdentifyData.NumberOfCurrentHeads =
+ LunExt->IdentifyData.NumberOfHeads = (USHORT)tmp32;
+ tmp32 = AtapiRegCheckDevValue(deviceExtension, channel, DeviceNumber, L"S", 0);
+ LunExt->IdentifyData.CurrentSectorsPerTrack =
+ LunExt->IdentifyData.SectorsPerTrack = (USHORT)tmp32;
+ memcpy(LunExt->IdentifyData.ModelNumber, "SEIDH DD", 8); // ESDI HDD
+ memcpy(LunExt->IdentifyData.SerialNumber, ".10", 4);
+ memcpy(LunExt->IdentifyData.FirmwareRevision, ".10", 4);
+ if(!LunExt->IdentifyData.SectorsPerTrack ||
+ !LunExt->IdentifyData.NumberOfCylinders ||
+ !LunExt->IdentifyData.SectorsPerTrack) {
+ // ERROR
+ KdPrint2((PRINT_PREFIX "Wrong CHS\n"));
+ LunExt->opt_GeomType = GEOM_AUTO;
+ } else {
+ LunExt->DeviceFlags |= DFLAGS_MANUAL_CHS;
+ LunExt->opt_GeomType = GEOM_ORIG;
+ }
+ }
tmp32 = AtapiRegCheckDevValue(deviceExtension, channel, DeviceNumber, L"Hidden", 0);
if(tmp32) {
LunExt->DeviceFlags |= DFLAGS_HIDDEN;
}
+
return;
} // end UniAtaReadLunConfig()
BaseIoAddressBM_0++;
}
}
+ return;
} // end UniataInitMapBM()
VOID
chan->RegTranslation[IDX_IO2+i].MemIo = FALSE;
}
UniataInitSyncBaseIO(chan);
+ return;
} // end UniataInitMapBase()
VOID
{
RtlCopyMemory(&chan->RegTranslation[IDX_IO1_o], &chan->RegTranslation[IDX_IO1], IDX_IO1_SZ*sizeof(chan->RegTranslation[0]));
RtlCopyMemory(&chan->RegTranslation[IDX_IO2_o], &chan->RegTranslation[IDX_IO2], IDX_IO2_SZ*sizeof(chan->RegTranslation[0]));
+ return;
} // end UniataInitSyncBaseIO()
VOID
{
ULONG i;
+ KdPrint2((PRINT_PREFIX "AtapiSetupLunPtrs for channel %d of %d, %d luns \n", c, deviceExtension->NumberChannels, deviceExtension->NumberLuns));
+
if(!deviceExtension->NumberLuns) {
+ KdPrint2((PRINT_PREFIX "Achtung !deviceExtension->NumberLuns \n"));
deviceExtension->NumberLuns = IDE_MAX_LUN_PER_CHAN;
}
chan->DeviceExtension = deviceExtension;
chan->lun[i]->chan = chan;
chan->lun[i]->Lun = i;
}
+ if((deviceExtension->HwFlags & UNIATA_AHCI) &&
+ deviceExtension->AhciInternalAtaReq0 &&
+ deviceExtension->AhciInternalSrb0) {
+ chan->AhciInternalAtaReq = &(deviceExtension->AhciInternalAtaReq0[c]);
+ chan->AhciInternalSrb = &(deviceExtension->AhciInternalSrb0[c]);
+ UniataAhciSetupCmdPtr(chan->AhciInternalAtaReq);
+ chan->AhciInternalSrb->SrbExtension = chan->AhciInternalAtaReq;
+ chan->AhciInternalAtaReq->Srb = chan->AhciInternalSrb;
+ }
+ return;
} // end AtapiSetupLunPtrs()
+BOOLEAN
+NTAPI
+UniataAllocateLunExt(
+ PHW_DEVICE_EXTENSION deviceExtension,
+ ULONG NewNumberChannels
+ )
+{
+ PHW_LU_EXTENSION old_luns = NULL;
+ PHW_CHANNEL old_chans = NULL;
+
+ KdPrint2((PRINT_PREFIX "allocate %d Luns for %d channels\n", deviceExtension->lun, deviceExtension->NumberChannels));
+
+ old_luns = deviceExtension->lun;
+ old_chans = deviceExtension->chan;
+
+ if(old_luns || old_chans) {
+ if(NewNumberChannels == UNIATA_ALLOCATE_NEW_LUNS) {
+ KdPrint2((PRINT_PREFIX "already allocated!\n"));
+ return FALSE;
+ }
+ }
+
+ if(!deviceExtension->NumberLuns) {
+ KdPrint2((PRINT_PREFIX "default NumberLuns=2\n"));
+ deviceExtension->NumberLuns = 2;
+ }
+
+ if(deviceExtension->HwFlags & UNIATA_AHCI) {
+ if(!deviceExtension->AhciInternalAtaReq0) {
+ deviceExtension->AhciInternalAtaReq0 = (PATA_REQ)ExAllocatePool(NonPagedPool, sizeof(ATA_REQ)*deviceExtension->NumberChannels);
+ if (!deviceExtension->AhciInternalAtaReq0) {
+ KdPrint2((PRINT_PREFIX "!deviceExtension->AhciInternalAtaReq0 => SP_RETURN_ERROR\n"));
+ return FALSE;
+ }
+ RtlZeroMemory(deviceExtension->AhciInternalAtaReq0, sizeof(ATA_REQ)*deviceExtension->NumberChannels);
+ }
+ if(!deviceExtension->AhciInternalSrb0) {
+ deviceExtension->AhciInternalSrb0 = (PSCSI_REQUEST_BLOCK)ExAllocatePool(NonPagedPool, sizeof(SCSI_REQUEST_BLOCK)*deviceExtension->NumberChannels);
+ if (!deviceExtension->AhciInternalSrb0) {
+ KdPrint2((PRINT_PREFIX "!deviceExtension->AhciInternalSrb0 => SP_RETURN_ERROR\n"));
+ UniataFreeLunExt(deviceExtension);
+ return FALSE;
+ }
+ RtlZeroMemory(deviceExtension->AhciInternalSrb0, sizeof(SCSI_REQUEST_BLOCK)*deviceExtension->NumberChannels);
+ }
+ }
+
+ deviceExtension->lun = (PHW_LU_EXTENSION)ExAllocatePool(NonPagedPool, sizeof(HW_LU_EXTENSION) * (deviceExtension->NumberChannels+1) * deviceExtension->NumberLuns);
+ if (!deviceExtension->lun) {
+ KdPrint2((PRINT_PREFIX "!deviceExtension->lun => SP_RETURN_ERROR\n"));
+ UniataFreeLunExt(deviceExtension);
+ return FALSE;
+ }
+ RtlZeroMemory(deviceExtension->lun, sizeof(HW_LU_EXTENSION) * (deviceExtension->NumberChannels+1) * deviceExtension->NumberLuns);
+
+ deviceExtension->chan = (PHW_CHANNEL)ExAllocatePool(NonPagedPool, sizeof(HW_CHANNEL) * (deviceExtension->NumberChannels+1));
+ if (!deviceExtension->chan) {
+ UniataFreeLunExt(deviceExtension);
+ KdPrint2((PRINT_PREFIX "!deviceExtension->chan => SP_RETURN_ERROR\n"));
+ return FALSE;
+ }
+ RtlZeroMemory(deviceExtension->chan, sizeof(HW_CHANNEL) * (deviceExtension->NumberChannels+1));
+ return TRUE;
+} // end UniataAllocateLunExt()
+
+VOID
+NTAPI
+UniataFreeLunExt(
+ PHW_DEVICE_EXTENSION deviceExtension
+ )
+{
+ if (deviceExtension->lun) {
+ ExFreePool(deviceExtension->lun);
+ deviceExtension->lun = NULL;
+ }
+ if (deviceExtension->chan) {
+ ExFreePool(deviceExtension->chan);
+ deviceExtension->chan = NULL;
+ }
+ if(deviceExtension->AhciInternalAtaReq0) {
+ ExFreePool(deviceExtension->AhciInternalAtaReq0);
+ deviceExtension->AhciInternalAtaReq0 = NULL;
+ }
+ if(deviceExtension->AhciInternalSrb0) {
+ ExFreePool(deviceExtension->AhciInternalSrb0);
+ deviceExtension->AhciInternalSrb0 = NULL;
+ }
+
+ return;
+} // end UniataFreeLunExt()
+
/*++
-Copyright (c) 2002-2011 Alexandr A. Telyatnikov (Alter)
+Copyright (c) 2002-2012 Alexandr A. Telyatnikov (Alter)
Module Name:
id_probe.cpp
(*ConfigInfo->AccessRanges)[rid].RangeInMemory
));
+ if(!(*ConfigInfo->AccessRanges)[rid].RangeInMemory) {
+ io_start = (pciData->u.type0.BaseAddresses[rid] & ~0x07/*PCI_ADDRESS_IOMASK*/) + offset;
+ // if(pciData->u.type0.BaseAddresses[rid] != 0) ;)
+ if(io_start > offset) {
+ if(/*(WinVer_Id() <= WinVer_NT) &&*/ offset && rid == 4) {
+ // MS atapi.sys does so for BusMaster controllers
+ (*ConfigInfo->AccessRanges)[rid+1].RangeStart =
+ ScsiPortConvertUlongToPhysicalAddress(io_start);
+ (*ConfigInfo->AccessRanges)[rid+1].RangeLength = length;
+ } else {
+ (*ConfigInfo->AccessRanges)[rid].RangeStart =
+ ScsiPortConvertUlongToPhysicalAddress(io_start);
+ (*ConfigInfo->AccessRanges)[rid].RangeLength = length;
+ }
+ if((pciData->u.type0.BaseAddresses[rid] & PCI_ADDRESS_IO_SPACE)) {
+ (*ConfigInfo->AccessRanges)[rid].RangeInMemory = FALSE;
+ } else {
+ KdPrint2((PRINT_PREFIX " AtapiGetIoRange: adjust mem 0 -> 1\n"));
+ (*ConfigInfo->AccessRanges)[rid].RangeInMemory = TRUE;
+ }
+ } else {
+ io_start = 0;
+ }
+ }
+
if((*ConfigInfo->AccessRanges)[rid].RangeInMemory) {
+ if(offset) {
+ KdPrint2((PRINT_PREFIX " AtapiGetIoRange: can't map memory range with offset\n"));
+ return 0;
+ }
io_start =
// Get the system physical address for this IO range.
((ULONG_PTR)ScsiPortGetDeviceBase(HwDeviceExtension,
// }
}
- io_start = (pciData->u.type0.BaseAddresses[rid] & ~0x07/*PCI_ADDRESS_IOMASK*/) + offset;
- // if(pciData->u.type0.BaseAddresses[rid] != 0) ;)
- if(io_start > offset) {
- if(/*(WinVer_Id() <= WinVer_NT) &&*/ offset && rid == 4) {
- // MS atapi.sys does so for BusMaster controllers
- (*ConfigInfo->AccessRanges)[rid+1].RangeStart =
- ScsiPortConvertUlongToPhysicalAddress(io_start);
- (*ConfigInfo->AccessRanges)[rid+1].RangeLength = length;
- } else {
- (*ConfigInfo->AccessRanges)[rid].RangeStart =
- ScsiPortConvertUlongToPhysicalAddress(io_start);
- (*ConfigInfo->AccessRanges)[rid].RangeLength = length;
- }
- if((pciData->u.type0.BaseAddresses[rid] & PCI_ADDRESS_IO_SPACE)) {
- (*ConfigInfo->AccessRanges)[rid].RangeInMemory = FALSE;
- } else {
- (*ConfigInfo->AccessRanges)[rid].RangeInMemory = TRUE;
- }
- } else {
- io_start = 0;
- }
KdPrint2((PRINT_PREFIX " AtapiGetIoRange: (2) %#x\n", io_start));
return io_start;
Do nothing, but build list of supported IDE controllers
It is a hack, ScsiPort architecture assumes, that DriverEntry
can support only KNOWN Vendor/Device combinations.
- Thus, we build list here. Later will pretend that always knew
+ Thus, we build list here. Later we pretend that always knew
about found devices.
We shall initiate ISA device init, but callback will use
maxPciBus = busNumber;
break;
}
+ // indicate that system has PCI bus(es)
+ hasPCI =TRUE;
+
// no device in this slot
if(busDataRead == 2) {
NeedPciAltInit = TRUE;
//KdPrint2((PRINT_PREFIX "DevId = %8.8X Class = %4.4X/%4.4X\n", dev_id, BaseClass, SubClass ));
+ // check for (g_opt_VirtualMachine == VM_AUTO) is performed inside each
+ // VM check for debug purposes
+ // Do not optimize :)
if(VendorID == 0x80ee && DeviceID == 0xcafe) {
KdPrint2((PRINT_PREFIX "-- BusID: %#x:%#x:%#x - VirtualBox Guest Service\n",busNumber,slotNumber,funcNumber));
if(g_opt_VirtualMachine == VM_AUTO) {
g_opt_VirtualMachine = VM_VBOX;
}
- //continue;
} else
if((VendorID == 0x15ad) ||
(SubVendorID == 0x15ad && SubSystemID == 0x1976)) {
if(g_opt_VirtualMachine == VM_AUTO) {
g_opt_VirtualMachine = VM_VMWARE;
}
- //g_opt_VirtualBox = TRUE;
} else
if(SubVendorID == 0x1af4 && SubSystemID == 0x1100) {
KdPrint2((PRINT_PREFIX "-- BusID: %#x:%#x:%#x - QEmu\n",busNumber,slotNumber,funcNumber));
KdPrint2((PRINT_PREFIX "-- BusID: %#x:%#x:%#x\n",busNumber,slotNumber,funcNumber));
KdPrint2((PRINT_PREFIX "Storage Class\n"));
- KdPrint2((PRINT_PREFIX "DevId = %8.8X Class = %4.4X/%4.4X\n", dev_id, BaseClass, SubClass ));
+ KdPrint2((PRINT_PREFIX "DevId = %8.8X Class = %4.4X/%4.4X, ProgIf %2.2X\n", dev_id, BaseClass, SubClass, pciData.ProgIf ));
// look for known chipsets
found = FALSE;
known = FALSE;
);
} // end UniataFindCompatBusMasterController2()
-BOOLEAN
-NTAPI
-UniataAllocateLunExt(
- PHW_DEVICE_EXTENSION deviceExtension,
- ULONG NewNumberChannels
- )
-{
- PHW_LU_EXTENSION old_luns = NULL;
- PHW_CHANNEL old_chans = NULL;
-
- KdPrint2((PRINT_PREFIX "allocate Luns for %d channels\n", deviceExtension->NumberChannels));
-
- old_luns = deviceExtension->lun;
- old_chans = deviceExtension->chan;
-
- if(old_luns || old_chans) {
- if(NewNumberChannels == UNIATA_ALLOCATE_NEW_LUNS) {
- KdPrint2((PRINT_PREFIX "already allocated!\n"));
- return FALSE;
- }
- }
-
- if(!deviceExtension->NumberLuns) {
- KdPrint2((PRINT_PREFIX "default NumberLuns=2\n"));
- deviceExtension->NumberLuns = 2;
- }
-
- deviceExtension->lun = (PHW_LU_EXTENSION)ExAllocatePool(NonPagedPool, sizeof(HW_LU_EXTENSION) * (deviceExtension->NumberChannels+1) * deviceExtension->NumberLuns);
- if (!deviceExtension->lun) {
- KdPrint2((PRINT_PREFIX "!deviceExtension->lun => SP_RETURN_ERROR\n"));
- return FALSE;
- }
- RtlZeroMemory(deviceExtension->lun, sizeof(HW_LU_EXTENSION) * (deviceExtension->NumberChannels+1) * deviceExtension->NumberLuns);
-
- deviceExtension->chan = (PHW_CHANNEL)ExAllocatePool(NonPagedPool, sizeof(HW_CHANNEL) * (deviceExtension->NumberChannels+1));
- if (!deviceExtension->chan) {
- ExFreePool(deviceExtension->lun);
- deviceExtension->lun = NULL;
- KdPrint2((PRINT_PREFIX "!deviceExtension->chan => SP_RETURN_ERROR\n"));
- return FALSE;
- }
- RtlZeroMemory(deviceExtension->chan, sizeof(HW_CHANNEL) * (deviceExtension->NumberChannels+1));
- return TRUE;
-} // end UniataAllocateLunExt()
-
-
/*++
Routine Description:
}
}
}
+ if(deviceExtension->HwFlags & UNIATA_AHCI) {
+ KdPrint2((PRINT_PREFIX " AHCI registers layout\n"));
+ } else
if(deviceExtension->AltRegMap) {
KdPrint2((PRINT_PREFIX " Non-standard registers layout\n"));
if(deviceExtension->HwFlags & UNIATA_SATA) {
KdPrint2((PRINT_PREFIX "UNIATA_SATA -> IsBusMaster == TRUE\n"));
- deviceExtension->BusMaster = TRUE;
+ if(!deviceExtension->BusMaster) {
+ deviceExtension->BusMaster = DMA_MODE_BM;
+ }
}
} else {
- deviceExtension->BusMaster = FALSE;
+ deviceExtension->BusMaster = DMA_MODE_NONE;
if(WinVer_WDM_Model && !deviceExtension->UnknownDev) {
ULONG i;
UniataInitMapBM(deviceExtension,
BaseIoAddressBM_0,
(*ConfigInfo->AccessRanges)[4].RangeInMemory ? TRUE : FALSE);
- deviceExtension->BusMaster = TRUE;
+ deviceExtension->BusMaster = DMA_MODE_BM;
deviceExtension->BaseIoAddressBM_0.Addr = (ULONGIO_PTR)BaseIoAddressBM_0;
if((*ConfigInfo->AccessRanges)[4].RangeInMemory) {
deviceExtension->BaseIoAddressBM_0.MemIo = TRUE;
KdPrint2((PRINT_PREFIX "IsBusMaster == TRUE && !MasterDev\n"));
statusByte = AtapiReadPort1(&(deviceExtension->chan[0]), IDX_BM_Status);
KdPrint2((PRINT_PREFIX " BM statusByte = %x\n", statusByte));
- if(statusByte == 0xff) {
+ if(statusByte == IDE_STATUS_WRONG) {
KdPrint2((PRINT_PREFIX " invalid port ?\n"));
+ deviceExtension->BusMaster = DMA_MODE_NONE;
/*
if(BaseIoAddressBM_0) {
ScsiPortFreeDeviceBase(HwDeviceExtension,
KdPrint2((PRINT_PREFIX "simplexOnly = %d (2)", simplexOnly));
- //TODO: fix hang with UseDpn=TRUE in Simplex mode
+ //TODO: fix hang with UseDpc=TRUE in Simplex mode
//deviceExtension->UseDpc = TRUE;
if(simplexOnly) {
KdPrint2((PRINT_PREFIX "simplexOnly => UseDpc = FALSE\n"));
KdPrint2((PRINT_PREFIX "update ConfigInfo->nt4\n"));
_ConfigInfo->nt4.DeviceExtensionSize = sizeof(HW_DEVICE_EXTENSION);
_ConfigInfo->nt4.SpecificLuExtensionSize = sizeof(HW_LU_EXTENSION);
- _ConfigInfo->nt4.SrbExtensionSize = sizeof(ATA_REQ);
+ if(deviceExtension->HwFlags & UNIATA_AHCI) {
+ _ConfigInfo->nt4.SrbExtensionSize = sizeof(ATA_REQ);
+ } else {
+ _ConfigInfo->nt4.SrbExtensionSize = FIELD_OFFSET(ATA_REQ, dma_tab) + sizeof(BM_DMA_ENTRY)*ATA_DMA_ENTRIES;
+ }
+ KdPrint2((PRINT_PREFIX "using AtaReq sz %x\n", _ConfigInfo->nt4.SrbExtensionSize));
}
if((WinVer_Id() > WinVer_2k) ||
(ConfigInfo->Length >= sizeof(_ConfigInfo->comm) + sizeof(_ConfigInfo->nt4) + sizeof(_ConfigInfo->w2k))) {
ConfigInfo->ScatterGather = TRUE;
}
- // Note: now we can support only 4 channels !!!
- // in order to add support for multichannel controllers we must rewrite
- // io-range claiming algorithm
-
KdPrint2((PRINT_PREFIX "BMList[i].channel %#x, NumberChannels %#x, channel %#x\n",BMList[i].channel, deviceExtension->NumberChannels, channel));
for (; channel < (BMList[i].channel + deviceExtension->NumberChannels); channel++, c++) {
chan->RegTranslation[IDX_SATA_IO].MemIo ? "mem" : "io"));
if(!(deviceExtension->HwFlags & UNIATA_AHCI)) {
+#if DBG
UniataDumpATARegs(chan);
+#endif
#ifndef UNIATA_CORE
#ifdef UNIATA_INIT_ON_PROBE
ScsiPortFreeDeviceBase(HwDeviceExtension,
BaseIoAddressBM_0);
+ if(deviceExtension->BaseIoAHCI_0.Addr) {
+ ScsiPortFreeDeviceBase(HwDeviceExtension,
+ deviceExtension->BaseIoAHCI_0.pAddr);
+ }
+
KdPrint2((PRINT_PREFIX "return SP_RETURN_NOT_FOUND\n"));
goto exit_notfound;
} else {
KdPrint2((PRINT_PREFIX "exit: init spinlock\n"));
//KeInitializeSpinLock(&(deviceExtension->DpcSpinLock));
deviceExtension->ActiveDpcChan =
- deviceExtension->FirstDpcChan = -1;
+ deviceExtension->FirstDpcChan = CHAN_NOT_SPECIFIED;
BMList[i].Isr2Enable = FALSE;
return SP_RETURN_FOUND;
exit_error:
- if (deviceExtension->lun) ExFreePool(deviceExtension->lun);
- if (deviceExtension->chan) ExFreePool(deviceExtension->chan);
+ UniataFreeLunExt(deviceExtension);
return SP_RETURN_ERROR;
exit_notfound:
- ExFreePool(deviceExtension->lun);
- ExFreePool(deviceExtension->chan);
+ UniataFreeLunExt(deviceExtension);
return SP_RETURN_NOT_FOUND;
} // end UniataFindBusMasterController()
UniataInitMapBM(deviceExtension,
BaseIoAddressBM_0,
(*ConfigInfo->AccessRanges)[4].RangeInMemory ? TRUE : FALSE);
- deviceExtension->BusMaster = TRUE;
+ deviceExtension->BusMaster = DMA_MODE_BM;
deviceExtension->BaseIoAddressBM_0.Addr = (ULONGIO_PTR)BaseIoAddressBM_0;
if((*ConfigInfo->AccessRanges)[4].RangeInMemory) {
deviceExtension->BaseIoAddressBM_0.MemIo = TRUE;
return SP_RETURN_FOUND;
exit_error:
- if (deviceExtension->lun) ExFreePool(deviceExtension->lun);
- if (deviceExtension->chan) ExFreePool(deviceExtension->chan);
+ UniataFreeLunExt(deviceExtension);
return SP_RETURN_ERROR;
exit_notfound:
- ExFreePool(deviceExtension->lun);
- ExFreePool(deviceExtension->chan);
+ UniataFreeLunExt(deviceExtension);
return SP_RETURN_NOT_FOUND;
} // end UniataFindFakeBusMasterController()
TRUE) {
// Ok, continue...
KdPrint2((PRINT_PREFIX "Multichannel native mode, go...\n"));
+#ifndef UNIATA_USE_XXableInterrupts
+ // If we raise IRQL to TIMER value, other interrupt cannot occure on the same CPU
+ if(KeNumberProcessors < 2) {
+ KdPrint2((PRINT_PREFIX "Unnecessary (?), UP machine\n"));
+ //return STATUS_SUCCESS;
+ }
+#endif //UNIATA_USE_XXableInterrupts
} else {
KdPrint2((PRINT_PREFIX "Unnecessary\n"));
return STATUS_SUCCESS;
UniataInitMapBase(chan, BaseIoAddress1, BaseIoAddress2);
UniataInitMapBM(deviceExtension, 0, FALSE);
+#if DBG
+ UniataDumpATARegs(chan);
+#endif
+
+ // Select master.
+ SelectDrive(chan, 0);
+
+ statusByte = AtapiReadPort1(chan, IDX_IO1_i_Status);
+
+ if(statusByte != AtapiReadPort1(chan, IDX_IO2_AltStatus)) {
+ KdPrint2((PRINT_PREFIX "AtapiFindController: Status vs AlsStatus missmatch, abort init ?\n"));
+
+ if(BaseIoAddress2) {
+ ScsiPortFreeDeviceBase(HwDeviceExtension,
+ (PCHAR)BaseIoAddress2);
+ BaseIoAddress2 = NULL;
+ }
+ BaseIoAddress2 = (PIDE_REGISTERS_2)((ULONGIO_PTR)BaseIoAddress1 + 0x0E);
+ ioSpace = (PUCHAR)ScsiPortGetDeviceBase(HwDeviceExtension,
+ ConfigInfo->AdapterInterfaceType,
+ ConfigInfo->SystemIoBusNumber,
+ ScsiPortConvertUlongToPhysicalAddress((ULONGIO_PTR)BaseIoAddress2),
+ ATA_ALTIOSIZE,
+ TRUE);
+ if(!ioSpace) {
+ BaseIoAddress2 = NULL;
+ KdPrint2((PRINT_PREFIX " abort (0)\n"));
+ goto not_found;
+ }
+ UniataInitMapBase(chan, BaseIoAddress1, BaseIoAddress2);
+ if(statusByte != AtapiReadPort1(chan, IDX_IO2_AltStatus)) {
+ KdPrint2((PRINT_PREFIX " abort\n"));
+ goto not_found;
+ }
+ }
+
retryIdentifier:
// Select master.
// Check if card at this address.
AtapiWritePort1(chan, IDX_IO1_o_CylinderLow, 0xAA);
+ statusByte = AtapiReadPort1(chan, IDX_IO1_i_CylinderLow);
// Check if indentifier can be read back.
- if ((statusByte = AtapiReadPort1(chan, IDX_IO1_i_CylinderLow)) != 0xAA) {
+ if (AtapiReadPort1(chan, IDX_IO1_i_CylinderLow) != 0xAA ||
+ statusByte == IDE_STATUS_WRONG) {
KdPrint2((PRINT_PREFIX "AtapiFindController: Identifier read back from Master (%#x)\n",
statusByte));
statusByte = AtapiReadPort1(chan, IDX_IO2_AltStatus);
- if (statusByte & IDE_STATUS_BUSY) {
+ if (statusByte != IDE_STATUS_WRONG && (statusByte & IDE_STATUS_BUSY)) {
i = 0;
// Select slave.
SelectDrive(chan, 1);
+ statusByte = AtapiReadPort1(chan, IDX_IO2_AltStatus);
// See if slave is present.
AtapiWritePort1(chan, IDX_IO1_o_CylinderLow, 0xAA);
- if ((statusByte = AtapiReadPort1(chan, IDX_IO1_i_CylinderLow)) != 0xAA) {
+ if (AtapiReadPort1(chan, IDX_IO1_i_CylinderLow) != 0xAA ||
+ statusByte == IDE_STATUS_WRONG) {
KdPrint2((PRINT_PREFIX
"AtapiFindController: Identifier read back from Slave (%#x)\n",
(*ConfigInfo->AccessRanges)[0].RangeLength = 8;
(*ConfigInfo->AccessRanges)[0].RangeInMemory = FALSE;
+ if(BaseIoAddress2) {
+ (*ConfigInfo->AccessRanges)[1].RangeStart = ScsiPortConvertUlongToPhysicalAddress((ULONG)BaseIoAddress2);
+ (*ConfigInfo->AccessRanges)[1].RangeLength = 2;
+ (*ConfigInfo->AccessRanges)[1].RangeInMemory = FALSE;
+ }
+
// Indicate the interrupt level corresponding to this IO range.
if (irq) {
ConfigInfo->BusInterruptLevel = irq;
KdPrint2((PRINT_PREFIX "chan = %#x\n", chan));
//PrintNtConsole("chan = %#x, c=%#x\n", chan, c);
+/*
+ // should be already set up in AtapiSetupLunPtrs(chan, deviceExtension, 0);
+
chan->DeviceExtension = deviceExtension;
chan->lChannel = 0;
chan->lun[0] = &(deviceExtension->lun[0]);
- chan->lun[1] = &(deviceExtension->lun[1]);
+ chan->lun[1] = &(deviceExtension->lun[1]);*/
/* do extra channel-specific setups */
AtapiReadChipConfig(HwDeviceExtension, DEVNUM_NOT_SPECIFIED, 0);
// Save the Interrupe Mode for later use
deviceExtension->InterruptMode = ConfigInfo->InterruptMode;
+ deviceExtension->BusInterruptLevel = ConfigInfo->BusInterruptLevel;
+ deviceExtension->BusInterruptVector = ConfigInfo->BusInterruptVector;
KdPrint2((PRINT_PREFIX
"AtapiFindController: look for devices\n"));
MCACount++;
}
+ ConfigInfo->NumberOfBuses++; // add virtual channel for communication port
KdPrint2((PRINT_PREFIX
"AtapiFindController: return SP_RETURN_FOUND\n"));
return(SP_RETURN_FOUND);
KdPrint2((PRINT_PREFIX
"AtapiFindController: return SP_RETURN_NOT_FOUND\n"));
- ExFreePool(deviceExtension->lun);
- ExFreePool(deviceExtension->chan);
+ UniataFreeLunExt(deviceExtension);
return(SP_RETURN_NOT_FOUND);
exit_error:
- if (deviceExtension->lun) ExFreePool(deviceExtension->lun);
- if (deviceExtension->chan) ExFreePool(deviceExtension->chan);
+ UniataFreeLunExt(deviceExtension);
return SP_RETURN_ERROR;
} // end AtapiFindController()
-BOOLEAN
+ULONG
NTAPI
UniataAnybodyHome(
IN PVOID HwDeviceExtension,
SATA_SSTATUS_REG SStatus;
UCHAR signatureLow;
UCHAR signatureHigh;
-
+
if(LunExt->DeviceFlags & DFLAGS_HIDDEN) {
KdPrint2((PRINT_PREFIX " hidden\n"));
UniataForgetDevice(LunExt);
- return FALSE;
+ return ATA_AT_HOME_NOBODY;
+ }
+ if(UniataIsSATARangeAvailable(deviceExtension, lChannel)) {
+
+ SStatus.Reg = UniataSataReadPort4(chan, IDX_SATA_SStatus, deviceNumber);
+ KdPrint2((PRINT_PREFIX "SStatus %x\n", SStatus.Reg));
+ if(SStatus.DET <= SStatus_DET_Dev_NoPhy) {
+ KdPrint2((PRINT_PREFIX " SATA DET <= SStatus_DET_Dev_NoPhy\n"));
+ return ATA_AT_HOME_NOBODY;
+ }
+ if(SStatus.SPD < SStatus_SPD_Gen1) {
+ KdPrint2((PRINT_PREFIX " SATA SPD < SStatus_SPD_Gen1\n"));
+ return ATA_AT_HOME_NOBODY;
+ }
+ if(SStatus.IPM == SStatus_IPM_NoDev) {
+ KdPrint2((PRINT_PREFIX " SATA IPN == SStatus_IPM_NoDev\n"));
+ return ATA_AT_HOME_NOBODY;
+ }
+ if(!(deviceExtension->HwFlags & UNIATA_AHCI)) {
+ // Select the device for legacy.
+ goto legacy_select;
+ }
+
+ } else {
+legacy_select:
+ // Select the device.
+ SelectDrive(chan, deviceNumber);
+ AtapiStallExecution(5);
}
- // Select the device.
- SelectDrive(chan, deviceNumber);
- signatureLow = AtapiReadPort1(chan, IDX_IO1_i_CylinderLow);
- signatureHigh = AtapiReadPort1(chan, IDX_IO1_i_CylinderHigh);
+ if((deviceExtension->HwFlags & UNIATA_AHCI) &&
+ UniataIsSATARangeAvailable(deviceExtension, lChannel)) {
+ KdPrint2((PRINT_PREFIX " AHCI check\n"));
+ ULONG SIG = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_SIG);
+ signatureLow = (UCHAR)(SIG >> 16);
+ signatureHigh = (UCHAR)(SIG >> 24);
+ } else {
+ signatureLow = AtapiReadPort1(chan, IDX_IO1_i_CylinderLow);
+ signatureHigh = AtapiReadPort1(chan, IDX_IO1_i_CylinderHigh);
+ }
if (signatureLow == ATAPI_MAGIC_LSB && signatureHigh == ATAPI_MAGIC_MSB) {
- KdPrint2((PRINT_PREFIX " ATAPI at home\n", signatureLow));
- return TRUE;
+ KdPrint2((PRINT_PREFIX " ATAPI at home\n"));
+ return ATA_AT_HOME_ATAPI;
+ }
+ if(deviceExtension->HwFlags & UNIATA_AHCI) {
+ KdPrint2((PRINT_PREFIX " AHCI HDD at home\n"));
+ return ATA_AT_HOME_HDD;
}
- if(!UniataIsSATARangeAvailable(deviceExtension, lChannel)) {
- AtapiStallExecution(10);
+ AtapiStallExecution(10);
- AtapiWritePort1(chan, IDX_IO1_o_BlockNumber, 0x55);
- AtapiWritePort1(chan, IDX_IO1_o_BlockNumber, 0x55);
- AtapiStallExecution(5);
- signatureLow = AtapiReadPort1(chan, IDX_IO1_i_BlockNumber);
- if(signatureLow != 0x55) {
+ AtapiWritePort1(chan, IDX_IO1_o_BlockNumber, 0x55);
+ AtapiWritePort1(chan, IDX_IO1_o_BlockNumber, 0x55);
+ AtapiStallExecution(5);
+ signatureLow = AtapiReadPort1(chan, IDX_IO1_i_BlockNumber);
+ if(signatureLow != 0x55) {
+ if(signatureLow == 0xff || signatureLow == 0) {
KdPrint2((PRINT_PREFIX " nobody home! %#x != 0x55\n", signatureLow));
UniataForgetDevice(LunExt);
- return FALSE;
+ return ATA_AT_HOME_NOBODY;
}
-
- AtapiWritePort1(chan, IDX_IO1_o_BlockNumber, 0xAA);
- AtapiWritePort1(chan, IDX_IO1_o_BlockNumber, 0xAA);
+ // another chance
+ signatureLow = AtapiReadPort1(chan, IDX_ATAPI_IO1_o_ByteCountHigh);
+ signatureLow += 2;
+ AtapiWritePort1(chan, IDX_ATAPI_IO1_o_ByteCountHigh, signatureLow);
AtapiStallExecution(5);
- signatureLow = AtapiReadPort1(chan, IDX_IO1_i_BlockNumber);
- if(signatureLow != 0xAA) {
- KdPrint2((PRINT_PREFIX " nobody home! %#x != 0xAA\n", signatureLow));
+ signatureHigh = AtapiReadPort1(chan, IDX_ATAPI_IO1_o_ByteCountHigh);
+ if(signatureLow != signatureHigh) {
+ KdPrint2((PRINT_PREFIX " nobody home! last chance failed %#x != %#x\n", signatureLow, signatureHigh));
UniataForgetDevice(LunExt);
- return FALSE;
+ return ATA_AT_HOME_NOBODY;
}
- } else {
+ return ATA_AT_HOME_XXX;
+ }
- SStatus.Reg = UniataSataReadPort4(chan, IDX_SATA_SStatus, deviceNumber);
- KdPrint2((PRINT_PREFIX "SStatus %x\n", SStatus.Reg));
- if(SStatus.DET <= SStatus_DET_Dev_NoPhy) {
- KdPrint2((PRINT_PREFIX " SATA DET <= SStatus_DET_Dev_NoPhy\n"));
- return FALSE;
- }
- if(SStatus.SPD < SStatus_SPD_Gen1) {
- KdPrint2((PRINT_PREFIX " SATA SPD < SStatus_SPD_Gen1\n"));
- return FALSE;
- }
- if(SStatus.IPM == SStatus_IPM_NoDev) {
- KdPrint2((PRINT_PREFIX " SATA IPN == SStatus_IPM_NoDev\n"));
- return FALSE;
- }
+ AtapiWritePort1(chan, IDX_IO1_o_BlockNumber, 0xAA);
+ AtapiWritePort1(chan, IDX_IO1_o_BlockNumber, 0xAA);
+ AtapiStallExecution(5);
+ signatureLow = AtapiReadPort1(chan, IDX_IO1_i_BlockNumber);
+ if(signatureLow != 0xAA) {
+ KdPrint2((PRINT_PREFIX " nobody home! %#x != 0xAA\n", signatureLow));
+ UniataForgetDevice(LunExt);
+ return ATA_AT_HOME_NOBODY;
}
- return TRUE;
+ KdPrint2((PRINT_PREFIX " HDD at home\n"));
+ return ATA_AT_HOME_HDD;
} // end UniataAnybodyHome()
ULONG
KdPrint2((PRINT_PREFIX "CheckDevice: Device %#x\n",
deviceNumber));
- if(deviceNumber > chan->NumberLuns) {
+ if(deviceNumber >= chan->NumberLuns) {
return 0;
}
-
+ if(deviceExtension->HwFlags & UNIATA_AHCI) {
+ if(!UniataAnybodyHome(HwDeviceExtension, lChannel, deviceNumber)) {
+ return 0;
+ }
+ }
LunExt = chan->lun[deviceNumber];
if(ResetDev && (deviceExtension->HwFlags & UNIATA_AHCI)) {
}
statusByte = WaitOnBusy(chan);
- if((statusByte | IDE_STATUS_BUSY) == 0xff) {
+ if((statusByte | IDE_STATUS_BUSY) == IDE_STATUS_WRONG) {
KdPrint2((PRINT_PREFIX
"CheckDevice: bad status %x\n", statusByte));
} else
- if(statusByte != 0xff && (statusByte & IDE_STATUS_BUSY)) {
+ if(statusByte != IDE_STATUS_WRONG && (statusByte & IDE_STATUS_BUSY)) {
// Perform hard-reset.
KdPrint2((PRINT_PREFIX
"CheckDevice: BUSY\n"));
"CheckDevice: status after hard reset %x\n", statusByte));
}
- if((statusByte | IDE_STATUS_BUSY) == 0xff) {
+ if((statusByte | IDE_STATUS_BUSY) == IDE_STATUS_WRONG) {
KdPrint2((PRINT_PREFIX
"CheckDevice: no dev ?\n"));
+ UniataForgetDevice(LunExt);
+ return 0;
} else
if(UniataIsSATARangeAvailable(deviceExtension, lChannel)) {
//if(deviceExtension->HwFlags & UNIATA_SATA) {
KdPrint2((PRINT_PREFIX
"CheckDevice: try enable SATA Phy\n"));
statusByte = UniataSataPhyEnable(HwDeviceExtension, lChannel, deviceNumber);
- if(statusByte == 0xff) {
+ if(statusByte == IDE_STATUS_WRONG) {
KdPrint2((PRINT_PREFIX "CheckDevice: status %#x (no dev)\n", statusByte));
UniataForgetDevice(LunExt);
return 0;
}
KdPrint2((PRINT_PREFIX "CheckDevice: status %#x\n", statusByte));
- if(((statusByte | IDE_STATUS_BUSY) == 0xff) ||
+ if(((statusByte | IDE_STATUS_BUSY) == IDE_STATUS_WRONG) ||
(statusByte & IDE_STATUS_BUSY)) {
KdPrint2((PRINT_PREFIX "CheckDevice: busy => return\n"));
UniataForgetDevice(LunExt);
LunExt->RwSwitchCost = REORDER_COST_SWITCH_RW_HDD;
LunExt->RwSwitchMCost = REORDER_MCOST_SWITCH_RW_HDD;
LunExt->SeekBackMCost = REORDER_MCOST_SEEK_BACK_HDD;
+ LunExt->AtapiReadyWaitDelay = 0;
if(deviceExtension->HwFlags & UNIATA_AHCI) {
if(RetVal & DFLAGS_DEVICE_PRESENT) {
KdPrint2((PRINT_PREFIX "CheckDevice: detected AHCI Device %#x\n",
deviceNumber));
} else {
- RetVal &= ~DFLAGS_ATAPI_DEVICE;
- LunExt->DeviceFlags &= ~DFLAGS_ATAPI_DEVICE;
+ //RetVal &= ~DFLAGS_ATAPI_DEVICE;
+ //LunExt->DeviceFlags &= ~DFLAGS_ATAPI_DEVICE;
+
+ UniataForgetDevice(LunExt);
+ RetVal = 0;
}
}
} else
// AtapiWritePort1(chan, IDX_IO2_o_Control,IDE_DC_DISABLE_INTERRUPTS | IDE_DC_A_4BIT );
// Clear expecting interrupt flag and current SRB field.
- chan->ExpectingInterrupt = FALSE;
+ UniataExpectChannelInterrupt(chan, FALSE);
// chan->CurrentSrb = NULL;
// max_ldev = (chan->ChannelCtrlFlags & CTRFLAGS_NO_SLAVE) ? 1 : IDE_MAX_LUN_PER_CHAN;
max_ldev = (chan->ChannelCtrlFlags & CTRFLAGS_NO_SLAVE) ? 1 : deviceExtension->NumberLuns;
/*++
-Copyright (c) 2008-2010 Alexandr A. Telyatnikov (Alter)
+Copyright (c) 2008-2012 Alexandr A. Telyatnikov (Alter)
Module Name:
id_probe.cpp
LunExt->last_write = ((AtaReq->Flags & REQ_FLAG_RW_MASK) == REQ_FLAG_WRITE);
// get request from longest queue to balance load
- if(chan->lun[0]->queue_depth * (chan->lun[0]->LunSelectWaitCount+1) >
- chan->lun[1]->queue_depth * (chan->lun[1]->LunSelectWaitCount+1)) {
- cdev = 0;
- } else {
- cdev = 1;
+ if(chan->NumberLuns > 1) {
+ if(chan->lun[0]->queue_depth * (chan->lun[0]->LunSelectWaitCount+1) >
+ chan->lun[1]->queue_depth * (chan->lun[1]->LunSelectWaitCount+1)) {
+ cdev = 0;
+ } else {
+ cdev = 1;
+ }
}
/* // prevent too long wait for actively used device
if(chan->lun[cdev ^ 1]->queue_depth &&
// get next request for processing
chan->cur_req = chan->lun[cdev]->first_req;
chan->cur_cdev = cdev;
- if(!chan->lun[cdev ^ 1]->queue_depth) {
- chan->lun[cdev ^ 1]->LunSelectWaitCount=0;
- } else {
- chan->lun[cdev ^ 1]->LunSelectWaitCount++;
+ if(chan->NumberLuns > 1) {
+ if(!chan->lun[cdev ^ 1]->queue_depth) {
+ chan->lun[cdev ^ 1]->LunSelectWaitCount=0;
+ } else {
+ chan->lun[cdev ^ 1]->LunSelectWaitCount++;
+ }
}
chan->lun[cdev]->LunSelectWaitCount=0;
/*++
-Copyright (c) 2008-2011 Alexandr A. Telyatnikov (Alter)
+Copyright (c) 2008-2012 Alexandr A. Telyatnikov (Alter)
Module Name:
id_probe.cpp
}
if(i >= 100) {
KdPrint2((PRINT_PREFIX "UniataSataConnect: SStatus %8.8x\n", SStatus.Reg));
- return 0xff;
+ return IDE_STATUS_WRONG;
}
/* clear SATA error register */
UniataSataWritePort4(chan, IDX_SATA_SError,
}
KdPrint2((PRINT_PREFIX "UniataSataPhyEnable: failed\n"));
- return 0xff;
+ return IDE_STATUS_WRONG;
} // end UniataSataPhyEnable()
BOOLEAN
return TRUE;
}
}
+ //return TRUE;
}
}
return FALSE;
if(chan->DeviceExtension->HwFlags & UNIATA_AHCI) {
return UniataAhciWritePM(chan, DeviceNumber, Reg, value);
}
- return 0xff;
+ return IDE_STATUS_WRONG;
} // end UniataSataWritePM()
ULONG
GHC | AHCI_GHC_AE);
GHC = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_GHC);
KdPrint2((PRINT_PREFIX " AHCI GHC %#x\n", GHC));
+ if(!(GHC & AHCI_GHC_AE)) {
+ KdPrint2((PRINT_PREFIX " Can't enable AHCI mode\n"));
+ return FALSE;
+ }
deviceExtension->AHCI_CAP =
CAP = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_CAP);
ULONG i, n;
ULONG PI;
ULONG CAP;
+ ULONG CAP2;
ULONG GHC;
+ ULONG BOHC;
ULONG NumberChannels;
ULONG v_Mn, v_Mj;
ULONG BaseMemAddress;
KdPrint2((PRINT_PREFIX " UniataAhciDetect:\n"));
- if(AtapiRegCheckDevValue(deviceExtension, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"IgnoreAhci", 1 /* DEBUG */)) {
+ if(AtapiRegCheckDevValue(deviceExtension, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"IgnoreAhci", 0)) {
KdPrint((" AHCI excluded\n"));
return FALSE;
}
}
CAP = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_CAP);
- KdPrint2((PRINT_PREFIX " AHCI CAP %#x\n", CAP));
+ CAP2 = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_CAP2);
+ KdPrint2((PRINT_PREFIX " AHCI CAP %#x, CAP2 %#x\n", CAP, CAP2));
if(CAP & AHCI_CAP_S64A) {
KdPrint2((PRINT_PREFIX " AHCI 64bit\n"));
//deviceExtension->Host64 = TRUE;
}
+ if(CAP2 & AHCI_CAP2_BOH) {
+ BOHC = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_BOHC);
+ KdPrint2((PRINT_PREFIX " AHCI BOHC %#x\n", BOHC));
+ }
/* get the number of HW channels */
PI = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_PI);
KdPrint2((PRINT_PREFIX " PM supported\n"));
if(AtapiRegCheckDevValue(deviceExtension, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"IgnoreAhciPM", 1 /* DEBUG */)) {
KdPrint2((PRINT_PREFIX "SATA/AHCI w/o PM, max luns 1\n"));
- deviceExtension->NumberLuns = 2;
+ deviceExtension->NumberLuns = 1;
//chan->ChannelCtrlFlags |= CTRFLAGS_NO_SLAVE;
} else {
KdPrint2((PRINT_PREFIX "SATA/AHCI -> possible PM, max luns %d\n", SATA_MAX_PM_UNITS));
deviceExtension->NumberLuns = 1;
}
- if((v_Mj != 0x01) || (v_Mn > 0x20)) {
+ switch(version) {
+ case 0x00000905:
+ case 0x00010000:
+ case 0x00010100:
+ case 0x00010200:
+ case 0x00010300:
+ break;
+ default:
KdPrint2((PRINT_PREFIX " Unknown AHCI revision\n"));
if(AtapiRegCheckDevValue(deviceExtension, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"CheckAhciRevision", 1)) {
KdPrint((" AHCI revision excluded\n"));
}
}
- deviceExtension->HwFlags |= UNIATA_SATA;
- deviceExtension->HwFlags |= UNIATA_AHCI;
+ deviceExtension->HwFlags |= UNIATA_SATA | UNIATA_AHCI;
if(deviceExtension->NumberChannels < NumberChannels) {
deviceExtension->NumberChannels = NumberChannels;
}
+ deviceExtension->DmaSegmentLength = 0x3fffff+1; // 4MB
+ deviceExtension->DmaSegmentAlignmentMask = -1; // no restrictions
+
+ deviceExtension->BusMaster = DMA_MODE_AHCI;
+ deviceExtension->MaxTransferMode = max(deviceExtension->MaxTransferMode, ATA_SA150);
return TRUE;
} // end UniataAhciDetect()
//ULONG offs = sizeof(IDE_AHCI_REGISTERS) + Channel*sizeof(IDE_AHCI_PORT_REGISTERS);
ULONG tag=0;
- KdPrint(("UniataAhciStatus:\n"));
+ KdPrint(("UniataAhciStatus(%d-%d):\n", lChannel, Channel));
hIS = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_IS);
KdPrint((" hIS %#x\n", hIS));
UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_IS, IS.Reg);
AtapiWritePort4(chan, IDX_SATA_SError, SError.Reg);
- KdPrint((" AHCI: status=%08x sstatus=%08x error=%08x CI=%08x\n",
+ KdPrint((" AHCI: istatus=%08x sstatus=%08x serror=%08x CI=%08x\n",
IS.Reg, SStatus.Reg, SError.Reg, CI));
/* do we have cold connect surprise */
if(IS.PRCS) {
UniataSataEvent(HwDeviceExtension, lChannel, UNIATA_SATA_EVENT_DETACH);
}
+ chan->AhciCompleteCI = (chan->AhciPrevCI ^ CI) & chan->AhciPrevCI; // only 1->0 states
+ chan->AhciPrevCI = CI;
+ KdPrint((" AHCI: complete mask %#x\n", chan->AhciCompleteCI));
+ chan->AhciLastIS = IS.Reg;
if(CI & (1 << tag)) {
- return INTERRUPT_REASON_OUR;
+#ifdef DBG
+ UniataDumpAhciPortRegs(chan);
+#endif //DBG
+ //deviceExtension->ExpectingInterrupt++; // will be updated in ISR on ReturnEnableInterrupts
+ if(IS.Reg &
+ (ATA_AHCI_P_IX_OF | ATA_AHCI_P_IX_INF | ATA_AHCI_P_IX_IF |
+ ATA_AHCI_P_IX_HBD | ATA_AHCI_P_IX_HBF | ATA_AHCI_P_IX_TFE)) {
+ KdPrint((" AHCI: unexpected, error\n"));
+ } else {
+ KdPrint((" AHCI: unexpected, incomplete command or error ?\n"));
+/*
+ ULONG TFD;
+
+ TFD = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_TFD);
+ KdPrint2((" TFD %#x\n", TFD));
+ if(TFD & IDE_STATUS_BUSY) {
+ KdPrint2((" Seems to be interrupt on error\n"));
+ return INTERRUPT_REASON_OUR;
+ }
+*/
+ return INTERRUPT_REASON_UNEXPECTED;
+ }
}
- KdPrint((" AHCI: unexpected\n"));
- return INTERRUPT_REASON_UNEXPECTED;
+ return INTERRUPT_REASON_OUR;
} // end UniataAhciStatus()
IN UCHAR command,
IN ULONGLONG lba,
IN USHORT count,
- IN USHORT feature,
- IN ULONG flags
+ IN USHORT feature
)
{
- ULONG i;
+ //ULONG i;
PUCHAR plba;
BOOLEAN need48;
PHW_CHANNEL chan = &deviceExtension->chan[lChannel];
- KdPrint2((PRINT_PREFIX " AHCI setup FIS ch %d, dev %d\n", lChannel, DeviceNumber));
- i = 0;
+ KdPrint2((PRINT_PREFIX " AHCI setup FIS %x, ch %d, dev %d\n", fis, lChannel, DeviceNumber));
+ //i = 0;
plba = (PUCHAR)&lba;
+ RtlZeroMemory(fis, 20);
+
fis[0] = AHCI_FIS_TYPE_ATA_H2D; /* host to device */
fis[1] = 0x80 | ((UCHAR)DeviceNumber & 0x0f); /* command FIS (note PM goes here) */
- fis[7] = IDE_USE_LBA;
- fis[15] = IDE_DC_A_4BIT;
-
- if(chan->lun[DeviceNumber]->DeviceFlags & DFLAGS_ATAPI_DEVICE) {
- fis[2] = IDE_COMMAND_ATAPI_PACKET;
+ fis[IDX_AHCI_o_DriveSelect] = IDE_DRIVE_SELECT_1 |
+ ((AtaCommandFlags[command] & (ATA_CMD_FLAG_LBAIOsupp | ATA_CMD_FLAG_48)) ? IDE_USE_LBA : 0);
+ fis[IDX_AHCI_o_Control] = IDE_DC_A_4BIT;
+
+ // IDE_COMMAND_ATAPI_IDENTIFY should be processed as regular ATA command,
+ // the rest of ATAPI requests are processed via IDE_COMMAND_ATAPI_PACKET
+ if(/*(chan->lun[DeviceNumber]->DeviceFlags & DFLAGS_ATAPI_DEVICE) &&
+ */
+ command == IDE_COMMAND_ATAPI_PACKET) {
+ fis[IDX_AHCI_o_Command] = IDE_COMMAND_ATAPI_PACKET;
if(feature & ATA_F_DMA) {
- fis[3] = (UCHAR)(feature & 0xff);
+ fis[IDX_AHCI_o_Feature] = (UCHAR)(feature & 0xff);
} else {
- fis[5] = (UCHAR)(count & 0xff);
- fis[6] = (UCHAR)(count>>8) & 0xff;
+ fis[IDX_AHCI_o_CylinderLow] = (UCHAR)(count & 0xff);
+ fis[IDX_AHCI_o_CylinderHigh] = (UCHAR)(count>>8) & 0xff;
}
+ //fis[IDX_AHCI_o_Control] |= IDE_DC_A_4BIT;
} else {
- if((AtaCommandFlags[command] & ATA_CMD_FLAG_LBAIOsupp) &&
+ if(((AtaCommandFlags[command] & (ATA_CMD_FLAG_LBAIOsupp|ATA_CMD_FLAG_FUA)) == ATA_CMD_FLAG_LBAIOsupp) &&
CheckIfBadBlock(chan->lun[DeviceNumber], lba, count)) {
KdPrint3((PRINT_PREFIX ": artificial bad block, lba %#I64x count %#x\n", lba, count));
//return IDE_STATUS_ERROR;
}
}
- fis[2] = command;
- fis[3] = (UCHAR)feature;
+ fis[IDX_AHCI_o_Command] = command;
+ fis[IDX_AHCI_o_Feature] = (UCHAR)feature;
+
+ fis[IDX_AHCI_o_BlockNumber] = plba[0];
+ fis[IDX_AHCI_o_CylinderLow] = plba[1];
+ fis[IDX_AHCI_o_CylinderHigh] = plba[2];
+
+ fis[IDX_AHCI_o_BlockCount] = (UCHAR)count & 0xff;
- fis[4] = plba[0];
- fis[5] = plba[1];
- fis[6] = plba[2];
if(need48) {
- i++;
+ //i++;
+ fis[IDX_AHCI_o_Control] |= IDE_DC_USE_HOB;
+
+ fis[IDX_AHCI_o_BlockNumberExp] = plba[3];
+ fis[IDX_AHCI_o_CylinderLowExp] = plba[4];
+ fis[IDX_AHCI_o_CylinderHighExp] = plba[5];
+
+ fis[IDX_AHCI_o_BlockCountExp] = (UCHAR)(count>>8) & 0xff;
+
+ fis[IDX_AHCI_o_FeatureExp] = (UCHAR)(feature>>8) & 0xff;
+
+ chan->ChannelCtrlFlags |= CTRFLAGS_LBA48;
} else {
-#ifdef _MSC_VER
-#pragma warning(push)
-#pragma warning(disable:4333) // right shift by too large amount, data loss
-#endif
- fis[7] |= IDE_DRIVE_1 | ((plba[3] >> 24) & 0x0f);
-#ifdef _MSC_VER
-#pragma warning(pop)
-#endif
+//#ifdef _MSC_VER
+//#pragma warning(push)
+//#pragma warning(disable:4333) // right shift by too large amount, data loss
+//#endif
+ fis[IDX_AHCI_o_DriveSelect] |= /*IDE_DRIVE_1 |*/ (plba[3] & 0x0f);
+ chan->ChannelCtrlFlags &= ~CTRFLAGS_LBA48;
+//#ifdef _MSC_VER
+//#pragma warning(pop)
+//#endif
}
- fis[8] = plba[3];
- fis[9] = plba[4];
- fis[10] = plba[5];
- fis[11] = (UCHAR)(feature>>8) & 0xff;
-
- fis[12] = (UCHAR)count & 0xff;
- fis[13] = (UCHAR)(count>>8) & 0xff;
//fis[14] = 0x00;
}
return 20;
} // end UniataAhciSetupFIS_H2D()
+UCHAR
+NTAPI
+UniataAhciWaitCommandReady(
+ IN PHW_CHANNEL chan,
+ IN ULONG timeout
+ )
+{
+ AHCI_IS_REG IS;
+ ULONG CI=0;
+ ULONG i;
+ ULONG SError;
+ ULONG tag=0;
+
+ timeout *= 5;
+
+ for (i=0; i<timeout; i++) {
+ CI = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_CI);
+ if (!((CI >> tag) & 0x01)) {
+ break;
+ }
+ IS.Reg = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_IS);
+ //KdPrint((" IS %#x\n", IS.Reg));
+ if(IS.Reg) {
+ break;
+ }
+ SError = AtapiReadPort4(chan, IDX_SATA_SError);
+ if(SError) {
+ KdPrint((" AHCI: error %#x\n", SError));
+ i = timeout;
+ break;
+ }
+ AtapiStallExecution(200);
+ }
+ KdPrint((" CI %#x\n", CI));
+
+ //SStatus.Reg = AtapiReadPort4(chan, IDX_SATA_SStatus);
+ //SError.Reg = AtapiReadPort4(chan, IDX_SATA_SError);
+
+ /* clear interrupt(s) */
+ IS.Reg = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_IS);
+ KdPrint((" IS %#x\n", IS.Reg));
+ UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_IS, IS.Reg);
+
+ if (timeout && (i >= timeout)) {
+#ifdef DBG
+ ULONG TFD;
+
+ SError = AtapiReadPort4(chan, IDX_SATA_SError);
+ KdPrint((" AHCI: timeout, SError %#x\n", SError));
+
+ TFD = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_TFD);
+ KdPrint2((" TFD %#x\n", TFD));
+#endif //DBG
+
+ return IDE_STATUS_WRONG;
+ }
+
+ return IDE_STATUS_IDLE;
+} // end UniataAhciWaitCommandReady()
+
UCHAR
NTAPI
UniataAhciSendCommand(
IN PVOID HwDeviceExtension,
IN ULONG lChannel,
IN ULONG DeviceNumber,
- IN ULONG flags,
+ IN USHORT ahci_flags,
IN ULONG timeout
)
{
PHW_CHANNEL chan = &deviceExtension->chan[lChannel];
//ULONG Channel = deviceExtension->Channel + lChannel;
//ULONG hIS;
- ULONG CI = 0;
- AHCI_IS_REG IS;
- ULONG SError;
+ //ULONG SError;
//SATA_SSTATUS_REG SStatus;
//SATA_SERROR_REG SError;
//ULONG offs = sizeof(IDE_AHCI_REGISTERS) + Channel*sizeof(IDE_AHCI_PORT_REGISTERS);
//ULONGIO_PTR base;
ULONG tag=0;
- ULONG i;
PIDE_AHCI_CMD_LIST AHCI_CL = &(chan->AhciCtlBlock->cmd_list[tag]);
KdPrint(("UniataAhciSendCommand: lChan %d\n", chan->lChannel));
AHCI_CL->prd_length = 0;
- AHCI_CL->cmd_flags = (20 / sizeof(ULONG)) | flags | (DeviceNumber << 12);
+ //AHCI_CL->cmd_flags = (20 / sizeof(ULONG)) | ahci_flags | (DeviceNumber << 12);
+ AHCI_CL->cmd_flags = UniAtaAhciAdjustIoFlags(0, ahci_flags, 20, DeviceNumber);
+
AHCI_CL->bytecount = 0;
AHCI_CL->cmd_table_phys = chan->AHCI_CTL_PhAddr + FIELD_OFFSET(IDE_AHCI_CHANNEL_CTL_BLOCK, cmd);
if(AHCI_CL->cmd_table_phys & AHCI_CMD_ALIGNEMENT_MASK) {
KdPrint2((PRINT_PREFIX " AHCI CMD address is not aligned (mask %#x)\n", (ULONG)AHCI_CMD_ALIGNEMENT_MASK));
}
- UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_CI, ATA_AHCI_P_CMD_ST);
+ UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_CI, 1 << tag);
- for (i=0; i<timeout; i++) {
- AtapiStallExecution(1000);
- CI = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_CI);
- if (!(CI & ATA_AHCI_P_CMD_ST)) {
- break;
+ return UniataAhciWaitCommandReady(chan, timeout);
+
+} // end UniataAhciSendCommand()
+
+UCHAR
+NTAPI
+UniataAhciSendPIOCommand(
+ IN PVOID HwDeviceExtension,
+ IN ULONG lChannel,
+ IN ULONG DeviceNumber,
+ IN PSCSI_REQUEST_BLOCK Srb,
+ IN PUCHAR data,
+ IN ULONG length, /* bytes */
+ IN UCHAR command,
+ IN ULONGLONG lba,
+ IN USHORT bcount, /* block count, just ATA register */
+ IN USHORT feature,
+ IN USHORT ahci_flags,
+ IN ULONG wait_flags,
+ IN ULONG timeout
+ )
+{
+ PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
+ PHW_CHANNEL chan = &deviceExtension->chan[lChannel];
+ UCHAR statusByte;
+ PATA_REQ AtaReq;
+ ULONG fis_size;
+ ULONG tag=0;
+ //PIDE_AHCI_CMD AHCI_CMD = &(chan->AhciCtlBlock->cmd);
+ PIDE_AHCI_CMD AHCI_CMD = NULL;
+
+ PIDE_AHCI_CMD_LIST AHCI_CL = &(chan->AhciCtlBlock->cmd_list[tag]);
+
+ KdPrint2((PRINT_PREFIX "UniataAhciSendPIOCommand: cntrlr %#x:%#x dev %#x, cmd %#x, lba %#I64x bcount %#x feature %#x, buff %#x, len %#x, WF %#x \n",
+ deviceExtension->DevIndex, lChannel, DeviceNumber, command, lba, bcount, feature, data, length, wait_flags ));
+
+ if(length/DEV_BSIZE != bcount) {
+ KdPrint((" length/DEV_BSIZE != bcount\n"));
+ }
+
+#ifdef DBG
+ //UniataDumpAhciPortRegs(chan);
+#endif // DBG
+
+ if(!Srb) {
+ Srb = BuildAhciInternalSrb(HwDeviceExtension, DeviceNumber, lChannel, data, length);
+ if(!Srb) {
+ KdPrint((" !Srb\n"));
+ return IDE_STATUS_WRONG;
}
+ //UniataAhciSetupCmdPtr(AtaReq); // must be called before DMA setup
+ //should be already called on init
}
- KdPrint((" CI %#x\n", CI));
+ AtaReq = (PATA_REQ)(Srb->SrbExtension);
+ //KdPrint((" Srb %#x, AtaReq %#x\n", Srb, AtaReq));
- //SStatus.Reg = AtapiReadPort4(chan, IDX_SATA_SStatus);
- //SError.Reg = AtapiReadPort4(chan, IDX_SATA_SError);
+ AHCI_CMD = AtaReq->ahci.ahci_cmd_ptr;
- /* clear interrupt(s) */
- IS.Reg = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_IS);
- KdPrint((" IS %#x\n", IS.Reg));
- UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_IS, IS.Reg);
+ fis_size = UniataAhciSetupFIS_H2D(deviceExtension, DeviceNumber, lChannel,
+ &(AHCI_CMD->cfis[0]),
+ command,
+ lba,
+ bcount,
+ feature
+ );
- if (timeout && (i >= timeout)) {
- ULONG TFD;
+ if(!fis_size) {
+ KdPrint2(("!fis_size\n"));
+ return IDE_STATUS_WRONG;
+ }
- SError = AtapiReadPort4(chan, IDX_SATA_SError);
- KdPrint((" AHCI: timeout, SError %#x\n", SError));
+ //KdPrint2(("UniAtaAhciAdjustIoFlags(command, ahci_flags, fis_size, DeviceNumber)\n"));
+ ahci_flags = UniAtaAhciAdjustIoFlags(command, ahci_flags, fis_size, DeviceNumber);
+ KdPrint2(("ahci_flags %#x\n", ahci_flags));
- TFD = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_TFD);
- KdPrint2((" TFD %#x\n", TFD));
-
- return 0xff;
+ if(data) {
+ if(ahci_flags & ATA_AHCI_CMD_WRITE) {
+ AtaReq->Flags &= ~REQ_FLAG_READ;
+ Srb->SrbFlags |= SRB_FLAGS_DATA_OUT;
+ KdPrint((" assume OUT\n"));
+ } else {
+ AtaReq->Flags |= REQ_FLAG_READ;
+ Srb->SrbFlags |= SRB_FLAGS_DATA_IN;
+ KdPrint((" assume IN\n"));
+ }
+ if(!AtapiDmaSetup(HwDeviceExtension,
+ DeviceNumber,
+ lChannel, // logical channel,
+ Srb,
+ data,
+ length)) {
+ KdPrint2((" can't setup buffer\n"));
+ return IDE_STATUS_WRONG;
+ }
}
- return IDE_STATUS_IDLE;
+ AtaReq->ahci.io_cmd_flags = ahci_flags;
-} // end UniataAhciSendCommand()
+#ifdef DBG
+ //UniataDumpAhciPortRegs(chan);
+#endif // DBG
+
+ UniataAhciBeginTransaction(HwDeviceExtension, lChannel, DeviceNumber, Srb);
+
+#ifdef DBG
+ //UniataDumpAhciPortRegs(chan);
+#endif // DBG
+
+ if(wait_flags == ATA_IMMEDIATE) {
+ statusByte = 0;
+ KdPrint2((" return imemdiately\n"));
+ } else {
+ statusByte = UniataAhciWaitCommandReady(chan, timeout);
+ UniataAhciStatus(HwDeviceExtension, lChannel, DeviceNumber);
+ UniataAhciEndTransaction(HwDeviceExtension, lChannel, DeviceNumber, Srb);
+ }
+
+ return statusByte;
+
+} // end UniataAhciSendPIOCommand()
ULONG
NTAPI
PUCHAR RCV_FIS = &(chan->AhciCtlBlock->rcv_fis.rfis[0]);
#ifdef DBG
- UniataDumpAhciPortRegs(chan);
+// UniataDumpAhciPortRegs(chan);
#endif // DBG
/* kick controller into sane state */
UniataAhciStart(chan);
#ifdef DBG
- UniataDumpAhciPortRegs(chan);
+// UniataDumpAhciPortRegs(chan);
#endif // DBG
/* pull reset active */
//AHCI_CMD->cfis[7] = IDE_USE_LBA | IDE_DRIVE_SELECT;
AHCI_CMD->cfis[15] = (IDE_DC_A_4BIT | IDE_DC_RESET_CONTROLLER);
- if(UniataAhciSendCommand(HwDeviceExtension, lChannel, DeviceNumber, ATA_AHCI_CMD_RESET | ATA_AHCI_CMD_CLR_BUSY, 100) == 0xff) {
+ if(UniataAhciSendCommand(HwDeviceExtension, lChannel, DeviceNumber, ATA_AHCI_CMD_RESET | ATA_AHCI_CMD_CLR_BUSY, 100) == IDE_STATUS_WRONG) {
KdPrint2((" timeout\n"));
return (ULONG)(-1);
}
AHCI_CMD->cfis[1] = (UCHAR)DeviceNumber & 0x0f;
//AHCI_CMD->cfis[7] = IDE_USE_LBA | IDE_DRIVE_SELECT;
AHCI_CMD->cfis[15] = (IDE_DC_A_4BIT);
- if(UniataAhciSendCommand(HwDeviceExtension, lChannel, DeviceNumber, 0, 3000) == 0xff) {
+ if(UniataAhciSendCommand(HwDeviceExtension, lChannel, DeviceNumber, 0, 3000) == IDE_STATUS_WRONG) {
KdPrint2((" timeout (2)\n"));
return (ULONG)(-1);
}
(*signature) = 0xffffffff;
UniataAhciStop(chan);
- if(UniataSataPhyEnable(HwDeviceExtension, lChannel, 0/* dev0*/, UNIATA_SATA_RESET_ENABLE) == 0xff) {
+ if(UniataSataPhyEnable(HwDeviceExtension, lChannel, 0/* dev0*/, UNIATA_SATA_RESET_ENABLE) == IDE_STATUS_WRONG) {
KdPrint((" no PHY\n"));
- return 0xff;
+ return IDE_STATUS_WRONG;
}
/* Wait for clearing busy status. */
PIDE_AHCI_CMD_LIST AHCI_CL = &(chan->AhciCtlBlock->cmd_list[tag]);
- KdPrint2(("UniataAhciBeginTransaction: lChan %d\n", chan->lChannel));
+ KdPrint2(("UniataAhciBeginTransaction: lChan %d, AtaReq %#x\n", chan->lChannel, AtaReq));
- if(AtaReq->dma_entries > (USHORT)0xffff) {
- KdPrint2(("UniataAhciBeginTransaction too long DMA tab\n"));
+ if(Srb->DataTransferLength && (!AtaReq->dma_entries || AtaReq->dma_entries >= (USHORT)0xffff)) {
+ KdPrint2(("UniataAhciBeginTransaction wrong DMA tab len %x\n", AtaReq->dma_entries));
return 0;
}
- AHCI_CL->prd_length = (USHORT)AtaReq->dma_entries;
+ AHCI_CL->prd_length = (USHORT)(AtaReq->dma_entries);
AHCI_CL->cmd_flags = AtaReq->ahci.io_cmd_flags;
AHCI_CL->bytecount = 0;
- AHCI_CL->cmd_table_phys = AtaReq->ahci.ahci_base64;
+ if(AtaReq->ahci.ahci_base64) {
+ KdPrint2((PRINT_PREFIX " AHCI AtaReq CMD %#x (ph %#x)\n", AtaReq->ahci.ahci_cmd_ptr, (ULONG)(AtaReq->ahci.ahci_base64)));
+ AHCI_CL->cmd_table_phys = AtaReq->ahci.ahci_base64;
+ } else
+ if(AtaReq->ahci.ahci_cmd_ptr) {
+ KdPrint2((PRINT_PREFIX " AHCI AtaReq->Chan CMD %#x (ph %#x) -> %#x (ph %#x)\n",
+ AtaReq->ahci.ahci_cmd_ptr, (ULONG)(AtaReq->ahci.ahci_base64),
+ &(chan->AhciCtlBlock->cmd), chan->AHCI_CTL_PhAddr + FIELD_OFFSET(IDE_AHCI_CHANNEL_CTL_BLOCK, cmd) ));
+ RtlCopyMemory(&(chan->AhciCtlBlock->cmd), AtaReq->ahci.ahci_cmd_ptr,
+ FIELD_OFFSET(IDE_AHCI_CMD, prd_tab)+AHCI_CL->prd_length*sizeof(IDE_AHCI_PRD_ENTRY));
+ AHCI_CL->cmd_table_phys = chan->AHCI_CTL_PhAddr + FIELD_OFFSET(IDE_AHCI_CHANNEL_CTL_BLOCK, cmd);
+ } else {
+ KdPrint2((PRINT_PREFIX " no AHCI CMD\n"));
+ //AHCI_CL->cmd_table_phys = chan->AHCI_CTL_PhAddr + FIELD_OFFSET(IDE_AHCI_CHANNEL_CTL_BLOCK, cmd);
+ return 0;
+ }
if(AHCI_CL->cmd_table_phys & AHCI_CMD_ALIGNEMENT_MASK) {
KdPrint2((PRINT_PREFIX " AHCI CMD address is not aligned (mask %#x)\n", (ULONG)AHCI_CMD_ALIGNEMENT_MASK));
+ return 0;
}
+#ifdef DBG
+ KdPrint2((" prd_length %#x, flags %#x, base %I64x\n", AHCI_CL->prd_length, AHCI_CL->cmd_flags,
+ AHCI_CL->cmd_table_phys));
+#endif // DBG
+
CMD = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_CMD);
KdPrint2((" CMD %#x\n", CMD));
- CMD &= ~ATA_AHCI_P_CMD_ATAPI;
- KdPrint2((" send CMD %#x\n", CMD));
+ // switch controller to ATAPI mode for ATA_PACKET commands only
+ if(ATAPI_DEVICE(chan, DeviceNumber) &&
+ AtaReq->ahci.ahci_cmd_ptr->cfis[2] == IDE_COMMAND_ATAPI_PACKET) {
+ KdPrint2((" ATAPI\n"));
+ CMD |= ATA_AHCI_P_CMD_ATAPI;
+ } else {
+ CMD &= ~ATA_AHCI_P_CMD_ATAPI;
+ }
+ KdPrint2((" send CMD %#x, entries %#x\n", CMD, AHCI_CL->prd_length));
UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_CMD, CMD);
/* issue command to controller */
- UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_CI, ATA_AHCI_P_CMD_ST);
+ UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_CI, 0x01 << tag);
+ chan->AhciPrevCI |= 0x01 << tag;
- if(!(chan->lun[DeviceNumber]->DeviceFlags & DFLAGS_ATAPI_DEVICE)) {
+ if(!ATAPI_DEVICE(chan, DeviceNumber)) {
// TODO: check if we send ATA_RESET and wait for ready of so.
if(AtaReq->ahci.ahci_cmd_ptr->cfis[2] == IDE_COMMAND_ATAPI_RESET) {
ULONG TFD;
}
AtaReq->ahci.in_status = TFD;
- return 0x00;
+ return IDE_STATUS_SUCCESS;
}
}
PHW_CHANNEL chan = &deviceExtension->chan[lChannel];
//ULONG Channel = deviceExtension->Channel + lChannel;
//ULONG hIS;
+ ULONG CI;
PATA_REQ AtaReq = (PATA_REQ)(Srb->SrbExtension);
ULONG TFD;
PUCHAR RCV_FIS = &(chan->AhciCtlBlock->rcv_fis.rfis[0]);
+ ULONG tag=0;
+ //ULONG i;
+ PIDE_AHCI_CMD_LIST AHCI_CL = &(chan->AhciCtlBlock->cmd_list[tag]);
+ PHW_LU_EXTENSION LunExt;
KdPrint2(("UniataAhciEndTransaction: lChan %d\n", chan->lChannel));
+ LunExt = chan->lun[DeviceNumber];
+
TFD = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_TFD);
KdPrint2((" TFD %#x\n", TFD));
if(TFD & IDE_STATUS_ERROR) {
- KdPrint2((" ERROR %#x\n", (UCHAR)(TFD >> 8)));
+ AtaReq->ahci.in_error = (UCHAR)(TFD >> 8);
+ KdPrint2((" ERROR %#x\n", AtaReq->ahci.in_error));
+ } else {
+ AtaReq->ahci.in_error = 0;
}
AtaReq->ahci.in_status = TFD;
((ULONGLONG)(RCV_FIS[9]) << 32) |
((ULONGLONG)(RCV_FIS[7] & 0x0f) << 24);
}
+ AtaReq->WordsTransfered = AHCI_CL->bytecount/2;
+
+ if(LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE) {
+ KdPrint2(("RCV:\n"));
+ KdDump(RCV_FIS, 24);
+ KdPrint2(("PIO:\n"));
+ KdDump(&(chan->AhciCtlBlock->rcv_fis.psfis[0]), 24);
+
+ KdPrint2(("len: %d vs %d\n", AHCI_CL->bytecount, (ULONG)RCV_FIS[5] | ((ULONG)RCV_FIS[6] << 8) ));
+ if(!AHCI_CL->bytecount) {
+ AtaReq->WordsTransfered = ((ULONG)RCV_FIS[5] | ((ULONG)RCV_FIS[6] << 8)) / 2;
+ }
+ }
+
+ CI = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_CI);
+ if(CI & (1 << tag)) {
+ // clear CI
+ KdPrint2((" Incomplete command, CI %#x\n", CI));
+ KdPrint2((" FIS status %#x, error %#x\n", RCV_FIS[2], RCV_FIS[3]));
+#if DBG
+ UniataDumpAhciPortRegs(chan);
+#endif
+ UniataAhciStop(chan);
+ UniataAhciStart(chan);
+#if DBG
+ UniataDumpAhciPortRegs(chan);
+#endif
+ chan->AhciPrevCI = CI & ~((ULONG)1 << tag);
+ if(chan->AhciPrevCI) {
+ KdPrint2((" Need command list restart, CI %#x\n", chan->AhciPrevCI));
+ }
+ } else {
+ chan->AhciPrevCI &= ~((ULONG)1 << tag);
+ RtlZeroMemory(AHCI_CL, sizeof(IDE_AHCI_CMD_LIST));
+ }
//}
return 0;
KdPrint2(("UniataAhciResume: lChan %d\n", chan->lChannel));
#ifdef DBG
- UniataDumpAhciPortRegs(chan);
+ //UniataDumpAhciPortRegs(chan);
#endif // DBG
/* Disable port interrupts */
);
#ifdef DBG
- UniataDumpAhciPortRegs(chan);
+ //UniataDumpAhciPortRegs(chan);
#endif // DBG
UniataAhciStartFR(chan);
AHCI_CMD->cfis[7] = (UCHAR)(IDE_USE_LBA | DeviceNumber);
AHCI_CMD->cfis[15] = IDE_DC_A_4BIT;
- if(UniataAhciSendCommand(chan->DeviceExtension, chan->lChannel, DeviceNumber, 0, 10) == 0xff) {
+ if(UniataAhciSendCommand(chan->DeviceExtension, chan->lChannel, DeviceNumber, 0, 10) == IDE_STATUS_WRONG) {
KdPrint2((" PM read failed\n"));
return FALSE;
}
case IDX_SATA_SControl:
Reg = 2; break;
default:
- return 0xff;
+ return IDE_STATUS_WRONG;
}
}
AHCI_CMD->cfis[15] = IDE_DC_A_4BIT;
- if(UniataAhciSendCommand(chan->DeviceExtension, chan->lChannel, DeviceNumber, 0, 100) == 0xff) {
+ if(UniataAhciSendCommand(chan->DeviceExtension, chan->lChannel, DeviceNumber, 0, 100) == IDE_STATUS_WRONG) {
KdPrint2((" PM write failed\n"));
- return 0xff;
+ return IDE_STATUS_WRONG;
}
TFD = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_TFD);
prd_base = (PUCHAR)(&AtaReq->ahci_cmd0);
prd_base0 = prd_base;
- prd_base64 = (prd_base64 + max(FIELD_OFFSET(ATA_REQ, ahci_cmd0), AHCI_CMD_ALIGNEMENT_MASK)) & ~AHCI_CMD_ALIGNEMENT_MASK;
+ prd_base64 = (prd_base64 + max(FIELD_OFFSET(ATA_REQ, ahci_cmd0), AHCI_CMD_ALIGNEMENT_MASK+1)) & ~AHCI_CMD_ALIGNEMENT_MASK;
d = (ULONG)(prd_base64 - prd_base64_0);
- KdPrint2((PRINT_PREFIX " aligned %I64x, d=%x\n", prd_base64, d));
+ KdPrint2((PRINT_PREFIX " AtaReq %#x: cmd aligned %I64x, d=%x\n", AtaReq, prd_base64, d));
AtaReq->ahci.ahci_cmd_ptr = (PIDE_AHCI_CMD)prd_base64;
KdPrint2((PRINT_PREFIX " ahci_cmd_ptr %#x\n", AtaReq->ahci.ahci_cmd_ptr));
} // end UniataAhciSetupCmdPtr()
+
+PSCSI_REQUEST_BLOCK
+NTAPI
+BuildAhciInternalSrb (
+ IN PVOID HwDeviceExtension,
+ IN ULONG DeviceNumber,
+ IN ULONG lChannel,
+ IN PUCHAR Buffer,
+ IN ULONG Length
+ )
+{
+ PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
+ PHW_CHANNEL chan = &deviceExtension->chan[lChannel];
+ PSCSI_REQUEST_BLOCK srb;
+// PCDB cdb;
+ PATA_REQ AtaReq = chan->AhciInternalAtaReq;
+
+ KdPrint(("BuildAhciInternalSrb: lChan %d [%#x]\n", lChannel, DeviceNumber));
+
+ if(!AtaReq) {
+ KdPrint2((PRINT_PREFIX " !chan->AhciInternalAtaReq\n"));
+ return NULL;
+ }
+
+ //RtlZeroMemory((PCHAR) AtaReq, sizeof(ATA_REQ));
+ //RtlZeroMemory((PCHAR) AtaReq, FIELD_OFFSET(ATA_REQ, ahci));
+ UniAtaClearAtaReq(AtaReq);
+
+ srb = chan->AhciInternalSrb;
+
+ RtlZeroMemory((PCHAR) srb, sizeof(SCSI_REQUEST_BLOCK));
+
+ srb->PathId = (UCHAR)lChannel;
+ srb->TargetId = (UCHAR)DeviceNumber;
+ srb->Function = SRB_FUNCTION_EXECUTE_SCSI;
+ srb->Length = sizeof(SCSI_REQUEST_BLOCK);
+
+ // Set flags to disable synchronous negociation.
+ //srb->SrbFlags = SRB_FLAGS_DATA_IN | SRB_FLAGS_DISABLE_SYNCH_TRANSFER;
+
+ // Set timeout to 4 seconds.
+ srb->TimeOutValue = 4;
+
+ srb->CdbLength = 6;
+ srb->DataBuffer = Buffer;
+ srb->DataTransferLength = Length;
+ srb->SrbExtension = AtaReq;
+
+ AtaReq->Srb = srb;
+ AtaReq->DataBuffer = (PUSHORT)Buffer;
+ AtaReq->TransferLength = Length;
+
+ //if(!AtaReq->ahci.ahci_cmd_ptr) {
+ //UniataAhciSetupCmdPtr(AtaReq);
+ //AtaReq->ahci.ahci_cmd_ptr = &(chan->AhciCtlBlock->cmd);
+ //AtaReq->ahci.ahci_base64 = chan->AHCI_CTL_PhAddr + FIELD_OFFSET(IDE_AHCI_CHANNEL_CTL_BLOCK, cmd);
+ //}
+ //AtaReq->ahci.ahci_cmd_ptr = &(AtaReq->ahci_cmd0);
+ //AtaReq->ahci.ahci_base64 = NULL; // indicate that we should copy command to proper place
+
+ KdPrint2((PRINT_PREFIX " Srb %#x, AtaReq %#x, CMD %#x ph %I64x\n", srb, AtaReq,
+ AtaReq->ahci.ahci_cmd_ptr, AtaReq->ahci.ahci_base64));
+
+/* // Set CDB operation code.
+ cdb = (PCDB)srb->Cdb;
+ cdb->CDB6INQUIRY.OperationCode = SCSIOP_REQUEST_SENSE;
+ cdb->CDB6INQUIRY.AllocationLength = sizeof(SENSE_DATA);
+*/
+ return srb;
+} // end BuildAhciInternalSrb()
+
/*++
-Copyright (c) 2008-2011 Alexandr A. Telyatnikov (Alter)
+Copyright (c) 2008-2012 Alexandr A. Telyatnikov (Alter)
Module Name:
id_probe.cpp
IN PVOID HwDeviceExtension
);
+#if DBG
+VOID
+NTAPI
+UniataDumpAhciPortRegs(
+ IN PHW_CHANNEL chan
+ );
+#endif
+
BOOLEAN
NTAPI
UniataAhciDetect(
IN UCHAR command,
IN ULONGLONG lba,
IN USHORT count,
- IN USHORT feature,
- IN ULONG flags
+ IN USHORT feature
+ );
+
+UCHAR
+NTAPI
+UniataAhciWaitCommandReady(
+ IN PHW_CHANNEL chan,
+ IN ULONG timeout
);
UCHAR
IN PVOID HwDeviceExtension,
IN ULONG lChannel,
IN ULONG DeviceNumber,
+ IN USHORT ahci_flags,
+ IN ULONG timeout
+ );
+
+UCHAR
+NTAPI
+UniataAhciSendPIOCommand(
+ IN PVOID HwDeviceExtension,
+ IN ULONG lChannel,
+ IN ULONG DeviceNumber,
+ IN PSCSI_REQUEST_BLOCK Srb,
+ IN PUCHAR data,
+ IN ULONG length,
+ IN UCHAR command,
+ IN ULONGLONG lba,
+ IN USHORT count,
+ IN USHORT feature,
+ IN USHORT ahci_flags,
IN ULONG flags,
IN ULONG timeout
);
(((ULONG)(RCV_FIS[5])) << 16) |
(((ULONG)(RCV_FIS[4])) << 8) |
((ULONG)(RCV_FIS[12])) );
-}
+} // end UniataAhciUlongFromRFIS()
+
+__inline
+USHORT
+UniAtaAhciAdjustIoFlags(
+ IN UCHAR command,
+ IN USHORT ahci_flags,
+ IN ULONG fis_size,
+ IN ULONG DeviceNumber
+ )
+{
+ ahci_flags |= (fis_size / sizeof(ULONG)) | (DeviceNumber << 12);
+ if(!command) {
+ return ahci_flags;
+ }
+
+ if(AtaCommandFlags[command] & ATA_CMD_FLAG_Out) {
+ ahci_flags |= ATA_AHCI_CMD_WRITE;
+ }
+/*
+ if(AtaCommandFlags[command] & ATA_CMD_FLAG_In) {
+ ahci_flags |= ATA_AHCI_CMD_READ;
+ }
+*/
+ return ahci_flags;
+} // end UniAtaAhciAdjustIoFlags()
BOOLEAN
NTAPI
IN OUT PATA_REQ AtaReq
);
+PSCSI_REQUEST_BLOCK
+NTAPI
+BuildAhciInternalSrb (
+ IN PVOID HwDeviceExtension,
+ IN ULONG DeviceNumber,
+ IN ULONG lChannel,
+ IN PUCHAR Buffer = NULL,
+ IN ULONG Length = 0
+ );
+
#endif //__UNIATA_SATA__H__
UCHAR Control;
} ERASE, *PERASE;
+ struct _ERASE10 {
+ UCHAR OperationCode;
+ UCHAR Reserved : 1;
+ UCHAR Immediate : 1;
+ UCHAR ERA : 1;
+ UCHAR Reserved1 : 2;
+ UCHAR Lun : 3;
+ UCHAR LBA[4];
+ UCHAR Reserved2;
+ UCHAR TransferBlocks[2];
+ UCHAR Control;
+ } ERASE10, *PERASE10;
+
#define FormatUnit_Code_Mask 0x07
#define FormatUnit_Cmp 0x08
#define FormatUnit_Fmt 0x10
/*++
-Copyright (c) 2002-2005 Alexandr A. Telyatnikov (Alter)
+Copyright (c) 2002-2012 Alexandr A. Telyatnikov (Alter)
Module Name:
tools.h
}
#define DEC_TO_BCD(x) (((x / 10) << 4) + (x % 10))
-/*
-
-#if defined _X86_ && !defined(__GNUC__)
-
-#define MOV_DD_SWP(a,b) \
-{ \
- PFOUR_BYTE _from_, _to_; \
- _from_ = ((PFOUR_BYTE)&(b)); \
- _to_ = ((PFOUR_BYTE)&(a)); \
- __asm mov ebx,_from_ \
- __asm mov eax,[ebx] \
- __asm bswap eax \
- __asm mov ebx,_to_ \
- __asm mov [ebx],eax \
-}
-
-#define MOV_DW_SWP(a,b) \
-{ \
- PFOUR_BYTE _from_, _to_; \
- _from_ = ((PFOUR_BYTE)&(b)); \
- _to_ = ((PFOUR_BYTE)&(a)); \
- __asm mov ebx,_from_ \
- __asm mov ax,[ebx] \
- __asm rol ax,8 \
- __asm mov ebx,_to_ \
- __asm mov [ebx],ax \
-}
-
-#define REVERSE_DD(a) { \
- PFOUR_BYTE _from_; \
- _from_ = ((PFOUR_BYTE)&(a)); \
- __asm mov ebx,_from_ \
- __asm mov eax,[ebx] \
- __asm bswap eax \
- __asm mov [ebx],eax \
-}
-
-#define REVERSE_DW(a) { \
- PFOUR_BYTE _from_; \
- _from_ = ((PFOUR_BYTE)&(a)); \
- __asm mov eax,_from_ \
- __asm rol word ptr [eax],8 \
-}
-
-#define MOV_DW2DD_SWP(a,b) \
-{ \
- PFOUR_BYTE _from_, _to_; \
- _from_ = ((PFOUR_BYTE)&(b)); \
- _to_ = ((PFOUR_BYTE)&(a)); \
- __asm mov ebx,_from_ \
- __asm mov ax,[ebx] \
- __asm rol ax,8 \
- __asm mov ebx,_to_ \
- __asm mov [ebx+2],ax \
- __asm mov [ebx],0 \
-}
-
-#define MOV_SWP_DW2DD(a,b) \
-{ \
- PFOUR_BYTE _from_, _to_; \
- _from_ = ((PFOUR_BYTE)&(b)); \
- _to_ = ((PFOUR_BYTE)&(a)); \
- __asm mov ebx,_from_ \
- __asm xor eax,eax \
- __asm mov ax,[ebx] \
- __asm rol ax,8 \
- __asm mov ebx,_to_ \
- __asm mov [ebx],eax \
-}
-
-#define MOV_MSF(a,b) \
-{ \
- PFOUR_BYTE _from_, _to_; \
- _from_ = ((PFOUR_BYTE)&(b)); \
- _to_ = ((PFOUR_BYTE)&(a)); \
- __asm mov ebx,_from_ \
- __asm mov eax,[ebx] \
- __asm mov ebx,_to_ \
- __asm mov [ebx],ax \
- __asm shr eax,16 \
- __asm mov [ebx+2],al \
-}
-
-#define MOV_MSF_SWP(a,b) \
-{ \
- PFOUR_BYTE _from_, _to_; \
- _from_ = ((PFOUR_BYTE)&(b)); \
- _to_ = ((PFOUR_BYTE)&(a)); \
- __asm mov ebx,_from_ \
- __asm mov eax,[ebx] \
- __asm mov ebx,_to_ \
- __asm mov [ebx+2],al \
- __asm bswap eax \
- __asm shr eax,8 \
- __asm mov [ebx],ax \
-}
-
-#define XCHG_DD(a,b) \
-{ \
- PULONG _from_, _to_; \
- _from_ = ((PULONG)&(b)); \
- _to_ = ((PULONG)&(a)); \
- __asm mov ebx,_from_ \
- __asm mov ecx,_to_ \
- __asm mov eax,[ebx] \
- __asm xchg eax,[ecx] \
- __asm mov [ebx],eax \
-}
-
-#else // NO X86 optimization , use generic C/C++
-
-#define MOV_DD_SWP(a,b) \
-{ \
- PFOUR_BYTE _from_, _to_; \
- _from_ = ((PFOUR_BYTE)&(b)); \
- _to_ = ((PFOUR_BYTE)&(a)); \
- _to_->Byte0 = _from_->Byte3; \
- _to_->Byte1 = _from_->Byte2; \
- _to_->Byte2 = _from_->Byte1; \
- _to_->Byte3 = _from_->Byte0; \
-}
-
-#define MOV_DW_SWP(a,b) \
-{ \
- PFOUR_BYTE _from_, _to_; \
- _from_ = ((PFOUR_BYTE)&(b)); \
- _to_ = ((PFOUR_BYTE)&(a)); \
- _to_->Byte0 = _from_->Byte1; \
- _to_->Byte1 = _from_->Byte0; \
-}
-
-#define REVERSE_DD(a) { \
- ULONG _i_; \
- MOV_DD_SWP(_i_,(a)); \
- *((PULONG)&(a)) = _i_; \
-}
-
-#define REVERSE_DW(a) { \
- USHORT _i_; \
- MOV_DW_SWP(_i_,(a)); \
- *((PUSHORT)&(a)) = _i_; \
-}
-
-#define MOV_DW2DD_SWP(a,b) \
-{ \
- PFOUR_BYTE _from_, _to_; \
- _from_ = ((PFOUR_BYTE)&(b)); \
- _to_ = ((PFOUR_BYTE)&(a)); \
- *((PUSHORT)_to_) = 0; \
- _to_->Byte2 = _from_->Byte1; \
- _to_->Byte3 = _from_->Byte0; \
-}
-
-#define MOV_MSF(a,b) \
-{ \
- PFOUR_BYTE _from_, _to_; \
- _from_ = ((PFOUR_BYTE)&(b)); \
- _to_ = ((PFOUR_BYTE)&(a)); \
- _to_->Byte0 = _from_->Byte0; \
- _to_->Byte1 = _from_->Byte1; \
- _to_->Byte2 = _from_->Byte2; \
-}
-
-#define MOV_MSF_SWP(a,b) \
-{ \
- PFOUR_BYTE _from_, _to_; \
- _from_ = ((PFOUR_BYTE)&(b)); \
- _to_ = ((PFOUR_BYTE)&(a)); \
- _to_->Byte0 = _from_->Byte2; \
- _to_->Byte1 = _from_->Byte1; \
- _to_->Byte2 = _from_->Byte0; \
-}
-
-#define XCHG_DD(a,b) \
-{ \
- ULONG _temp_; \
- PULONG _from_, _to_; \
- _from_ = ((PULONG)&(b)); \
- _to_ = ((PULONG)&(a)); \
- _temp_ = *_from_; \
- *_from_ = *_to_; \
- *_to_ = _temp_; \
-}
-
-#endif // _X86_
-
-#define MOV_3B_SWP(a,b) MOV_MSF_SWP(a,b)
-
-*/
#ifdef DBG
KdPrint(("\n")); \
}
-#define BrutePoint() {}
+#define BrutePoint() { ASSERT(0); }
#define DbgAllocatePool(x,y) ExAllocatePool(x,y)
#define DbgFreePool(x) ExFreePool(x)
-#define UNIATA_VER_STR "41b5"
-#define UNIATA_VER_DOT 0.41.2.5
+#define UNIATA_VER_STR "42e2"
+#define UNIATA_VER_DOT 0.42.5.2
#define UNIATA_VER_MJ 0
-#define UNIATA_VER_MN 41
-#define UNIATA_VER_SUB_MJ 2
-#define UNIATA_VER_SUB_MN 5
-#define UNIATA_VER_DOT_COMMA 0,41,2,5
-#define UNIATA_VER_DOT_STR "0.41.2.5"
+#define UNIATA_VER_MN 42
+#define UNIATA_VER_SUB_MJ 5
+#define UNIATA_VER_SUB_MN 2
+#define UNIATA_VER_DOT_COMMA 0,42,5,2
+#define UNIATA_VER_DOT_STR "0.42.5.2"
#define UNIATA_VER_YEAR 2012
#define UNIATA_VER_YEAR_STR "2012"