* Sync with UniATA v0.42e2.
* Hello AHCI support, you've been missed ! (that's WIP but still)

svn path=/trunk/; revision=57018
This commit is contained in:
Amine Khaldi 2012-08-01 20:30:19 +00:00
parent e1398e05d4
commit d1f163d021
15 changed files with 2426 additions and 1138 deletions

View file

@ -1,6 +1,6 @@
/*++
Copyright (c) 2002-2011 Alexandr A. Telyatnikov (Alter)
Copyright (c) 2002-2012 Alexandr A. Telyatnikov (Alter)
Module Name:
atapi.h
@ -106,7 +106,7 @@ DbgPrint(
#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
@ -249,6 +249,7 @@ typedef struct _IDE_REGISTERS_2 {
#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.
@ -299,6 +300,7 @@ typedef struct _MODE_PARAMETER_HEADER_10 {
// 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
@ -380,6 +382,9 @@ typedef struct _MODE_PARAMETER_HEADER_10 {
#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
@ -615,7 +620,11 @@ typedef struct _IDENTIFY_DATA {
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
@ -637,7 +646,20 @@ typedef struct _IDENTIFY_DATA {
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
@ -651,6 +673,9 @@ typedef struct _IDENTIFY_DATA {
#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
@ -664,6 +689,12 @@ typedef struct _IDENTIFY_DATA {
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;
@ -734,7 +765,8 @@ typedef struct _IDENTIFY_DATA {
ULONGLONG UserAddressableSectors48; // 100-103
USHORT Reserved104[2]; // 104-105
USHORT StreamingTransferTimePIO; // 104
USHORT MaxLBARangeDescBlockCount; // 105 // in 512b blocks
union {
USHORT PhysLogSectorSize; // 106
struct {
@ -745,22 +777,101 @@ typedef struct _IDENTIFY_DATA {
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;
//
@ -813,10 +924,18 @@ typedef struct _IDENTIFY_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}
@ -1219,6 +1338,12 @@ AtapiDisableInterrupts(
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)
@ -1303,7 +1428,7 @@ UniAtaCalculateLBARegsBack(
ULONGLONG lba
);
BOOLEAN
ULONG
NTAPI
UniataAnybodyHome(
IN PVOID HwDeviceExtension,
@ -1311,10 +1436,18 @@ UniataAnybodyHome(
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];
@ -1327,6 +1460,15 @@ 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

View file

@ -1,6 +1,6 @@
/*++
Copyright (c) 2002-2011 Alexandr A. Telyatnikov (Alter)
Copyright (c) 2002-2012 Alexandr A. Telyatnikov (Alter)
Module Name:
bm_devs.h
@ -88,11 +88,17 @@ Revision History:
#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;
@ -692,10 +698,10 @@ typedef struct _BUSMASTER_CONTROLLER_INFORMATION {
#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)

View file

@ -1,6 +1,6 @@
/*++
Copyright (c) 2002-2011 Alexandr A. Telyatnikov (Alter)
Copyright (c) 2002-2012 Alexandr A. Telyatnikov (Alter)
Module Name:
bsmaster.h
@ -163,12 +163,14 @@ typedef struct _IDE_AHCI_REGISTERS {
// 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
@ -179,7 +181,7 @@ typedef struct _IDE_AHCI_REGISTERS {
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;
@ -206,14 +208,40 @@ typedef struct _IDE_AHCI_REGISTERS {
#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];
ULONG VS; // 0x10
UCHAR Reserved2[0x80];
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;
@ -223,6 +251,8 @@ typedef struct _IDE_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 {
@ -561,7 +591,22 @@ typedef struct _IDE_AHCI_PORT_REGISTERS {
};
} 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;
@ -617,9 +662,14 @@ typedef struct _IDE_AHCI_PRD_ENTRY {
};
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;
@ -628,6 +678,50 @@ typedef struct _IDE_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)
@ -638,8 +732,8 @@ typedef struct _IDE_AHCI_PRD_ENTRY {
/* 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;
@ -665,11 +759,11 @@ typedef struct _IDE_AHCI_CMD_LIST {
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;
@ -678,7 +772,7 @@ typedef struct _IDE_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;
@ -741,7 +835,7 @@ typedef union _ATA_REQ {
ULONG in_bcount;
ULONG in_status;
USHORT io_cmd_flags; // out
UCHAR in_error;
} ahci;
};
};
@ -781,7 +875,8 @@ typedef union _ATA_REQ {
#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
@ -832,9 +927,12 @@ struct _HW_DEVICE_EXTENSION;
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;
@ -867,7 +965,7 @@ typedef struct _HW_CHANNEL {
//BOOLEAN MemIo;
BOOLEAN AltRegMap;
//UCHAR Reserved[3];
UCHAR Reserved[3];
MECHANICAL_STATUS_INFORMATION_HEADER MechStatusData;
SENSE_DATA MechStatusSense;
@ -923,9 +1021,14 @@ typedef struct _HW_CHANNEL {
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];
@ -999,6 +1102,7 @@ typedef struct _HW_LU_EXTENSION {
ULONG last_write;
ULONG LunSelectWaitCount;
ULONG AtapiReadyWaitDelay;
// tuning options
ULONG opt_GeomType;
@ -1072,6 +1176,7 @@ typedef struct _HW_DEVICE_EXTENSION {
ULONG ActiveDpcChan;
ULONG FirstDpcChan;
ULONG ExpectingInterrupt; // Indicates entire controller expecting an interrupt
/*
PHW_TIMER HwScsiTimer1;
PHW_TIMER HwScsiTimer2;
@ -1115,16 +1220,20 @@ typedef struct _HW_DEVICE_EXTENSION {
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
@ -1186,13 +1295,17 @@ UniataFindCompatBusMasterController2(
#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,
@ -1476,9 +1589,13 @@ AtapiGetIoRange(
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
@ -1655,6 +1772,7 @@ UniataForgetDevice(
extern ULONG SkipRaids;
extern ULONG ForceSimplex;
extern BOOLEAN g_opt_AtapiDmaRawRead;
extern BOOLEAN hasPCI;
extern BOOLEAN InDriverEntry;

View file

@ -110,16 +110,16 @@
#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))
@ -129,16 +129,16 @@
#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)

File diff suppressed because it is too large Load diff

View file

@ -182,6 +182,7 @@ InitBadBlocks(
for(i=0; i<Length; i++) {
cDevSerial[i] = (UCHAR)(DevSerial[i]);
}
cDevSerial[i] = 0;
KdPrint(( "S/N:%s\n", cDevSerial));
#endif

View file

@ -1,6 +1,6 @@
/*++
Copyright (c) 2002-2011 Alexander A. Telyatnikov (Alter)
Copyright (c) 2002-2012 Alexander A. Telyatnikov (Alter)
Module Name:
id_dma.cpp
@ -91,15 +91,13 @@ hpt_cable80(
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
)
{
@ -242,11 +240,12 @@ AtapiDmaSetup(
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);
@ -254,7 +253,15 @@ AtapiDmaSetup(
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",
@ -282,9 +289,9 @@ AtapiDmaSetup(
//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);
@ -301,9 +308,9 @@ AtapiDmaSetup(
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));
@ -328,15 +335,40 @@ retry_DB_IO:
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" ));
@ -344,7 +376,7 @@ retry_DB_IO:
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));
@ -369,15 +401,45 @@ retry_DB_IO:
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;
@ -589,7 +651,7 @@ AtapiDmaDone(
if(deviceExtension->HwFlags & UNIATA_AHCI) {
KdPrint2((PRINT_PREFIX " ACHTUNG! should not be called for AHCI!\n"));
return 0xff;
return IDE_STATUS_WRONG;
}
switch(VendorID) {
@ -645,6 +707,13 @@ AtapiDmaReinit(
{
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)) {
@ -655,8 +724,8 @@ AtapiDmaReinit(
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) {
@ -722,6 +791,9 @@ limit_pio:
"AtapiDmaReinit: restore IO mode on Device %d\n", LunExt->Lun));
AtapiDmaInit__(deviceExtension, LunExt);
}
exit:
return;
} // end AtapiDmaReinit()
VOID
@ -773,9 +845,19 @@ AtaSetTransferMode(
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) {
@ -819,11 +901,13 @@ AtapiDmaInit(
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;
@ -888,29 +972,27 @@ AtapiDmaInit(
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) {
@ -922,7 +1004,7 @@ AtapiDmaInit(
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"));
@ -931,7 +1013,7 @@ AtapiDmaInit(
udmamode = 2;
apiomode = min( apiomode, (CHAR)(LunExt->LimitedTransferMode - ATA_PIO0));
} else {
udmamode = min(udmamode, 5);
udmamode = min(udmamode, 6);
}
}
}
@ -950,10 +1032,21 @@ AtapiDmaInit(
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",
@ -1021,8 +1114,8 @@ set_new_acard:
/* 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);
@ -1364,7 +1457,7 @@ set_new_acard:
SetPciConfig2(0x4a, (reg4a & ~(0x3 << (dev<<2))) |
(0x01 + !(i & 0x01)) );
}
if(i >= 3) {
if(i >= 2) {
reg54 |= (0x1 << dev);
} else {
reg54 &= ~(0x1 << dev);
@ -1412,8 +1505,7 @@ set_new_acard:
GetPciConfig1(0x44, reg44);
/* Allow PIO/WDMA timing controls. */
reg40 &= ~0x00ff00ff;
reg40 |= ~0x40774077;
mask40 = 0x000000ff;
/* Set PIO/WDMA timings. */
if(!(DeviceNumber & 1)) {
mask40 |= 0x00003300;
@ -1423,6 +1515,7 @@ set_new_acard:
new44 = ((intel_timings[idx] & 0x30) >> 2) |
(intel_timings[idx] & 0x03);
}
new40 |= 0x00004077;
if (Channel) {
mask40 <<= 16;
@ -1441,7 +1534,7 @@ set_new_acard:
/* Promise */
/***********/
if(ChipType < PRTX) {
if (ATAPI_DEVICE(deviceExtension, ldev)) {
if (isAtapi) {
udmamode =
wdmamode = -1;
}
@ -1919,12 +2012,12 @@ setup_drive_ite:
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);
@ -1980,7 +2073,7 @@ try_generic_dma:
/* 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;
@ -1989,9 +2082,9 @@ try_generic_dma:
/* 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;

View file

@ -1,6 +1,6 @@
/*++
Copyright (c) 2004-2011 Alexandr A. Telyatnikov (Alter)
Copyright (c) 2004-2012 Alexandr A. Telyatnikov (Alter)
Module Name:
id_init.cpp
@ -69,8 +69,8 @@ UniataChipDetectChannels(
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));
@ -133,8 +133,8 @@ UniataChipDetectChannels(
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;
@ -255,11 +255,15 @@ UniataChipDetect(
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"));
@ -268,10 +272,9 @@ UniataChipDetect(
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));
@ -281,8 +284,9 @@ unknown_dev:
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[] = {
@ -447,7 +451,7 @@ unknown_dev:
deviceExtension->BaseIoAddressBM_0);
deviceExtension->BaseIoAddressBM_0 = 0;
deviceExtension->BusMaster = FALSE;
deviceExtension->BusMaster = DMA_MODE_NONE;
deviceExtension->MaxTransferMode = ATA_PIO4;
break;
@ -1020,10 +1024,10 @@ for_ugly_chips:
/* if BAR(5) is IO it should point to SATA interface registers */
if(deviceExtension->DevID == 0x28288086 &&
pciData->u.type0.SubVendorID == 0x106b) {
BaseMemAddress = 0;
KdPrint2((PRINT_PREFIX "Ignore BAR5 on ICH8M Apples\n"));
} else {
/* Skip BAR(5) on ICH8M Apples, system locks up on access. */
KdPrint2((PRINT_PREFIX "Ignore BAR5 on ICH8M Apples\n"));
BaseMemAddress = 0;
} else {
BaseMemAddress = AtapiGetIoRange(HwDeviceExtension, ConfigInfo, pciData, SystemIoBusNumber,
5, 0, 0x10);
if(BaseMemAddress && (*ConfigInfo->AccessRanges)[5].RangeInMemory) {
@ -1465,16 +1469,44 @@ UniAtaReadLunConfig(
}
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()
@ -2284,6 +2316,7 @@ UniataInitMapBM(
BaseIoAddressBM_0++;
}
}
return;
} // end UniataInitMapBM()
VOID
@ -2305,6 +2338,7 @@ UniataInitMapBase(
chan->RegTranslation[IDX_IO2+i].MemIo = FALSE;
}
UniataInitSyncBaseIO(chan);
return;
} // end UniataInitMapBase()
VOID
@ -2315,6 +2349,7 @@ UniataInitSyncBaseIO(
{
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
@ -2327,7 +2362,10 @@ AtapiSetupLunPtrs(
{
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;
@ -2343,5 +2381,106 @@ AtapiSetupLunPtrs(
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()

View file

@ -1,6 +1,6 @@
/*++
Copyright (c) 2002-2011 Alexandr A. Telyatnikov (Alter)
Copyright (c) 2002-2012 Alexandr A. Telyatnikov (Alter)
Module Name:
id_probe.cpp
@ -112,7 +112,36 @@ AtapiGetIoRange(
(*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,
@ -132,27 +161,6 @@ AtapiGetIoRange(
// }
}
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;
@ -164,7 +172,7 @@ AtapiGetIoRange(
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
@ -298,6 +306,9 @@ UniataEnumBusMasterController__(
maxPciBus = busNumber;
break;
}
// indicate that system has PCI bus(es)
hasPCI =TRUE;
// no device in this slot
if(busDataRead == 2) {
NeedPciAltInit = TRUE;
@ -321,12 +332,14 @@ UniataEnumBusMasterController__(
//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)) {
@ -334,7 +347,6 @@ UniataEnumBusMasterController__(
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));
@ -350,7 +362,7 @@ UniataEnumBusMasterController__(
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;
@ -837,52 +849,6 @@ UniataFindCompatBusMasterController2(
);
} // 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:
@ -1194,14 +1160,19 @@ UniataFindBusMasterController(
}
}
}
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;
@ -1259,7 +1230,7 @@ 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;
@ -1277,8 +1248,9 @@ UniataFindBusMasterController(
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,
@ -1315,7 +1287,7 @@ UniataFindBusMasterController(
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"));
@ -1413,7 +1385,12 @@ UniataFindBusMasterController(
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))) {
@ -1478,10 +1455,6 @@ UniataFindBusMasterController(
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++) {
@ -1645,7 +1618,9 @@ UniataFindBusMasterController(
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
@ -1744,6 +1719,11 @@ exit_findbm:
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 {
@ -1751,7 +1731,7 @@ exit_findbm:
KdPrint2((PRINT_PREFIX "exit: init spinlock\n"));
//KeInitializeSpinLock(&(deviceExtension->DpcSpinLock));
deviceExtension->ActiveDpcChan =
deviceExtension->FirstDpcChan = -1;
deviceExtension->FirstDpcChan = CHAN_NOT_SPECIFIED;
BMList[i].Isr2Enable = FALSE;
@ -1796,13 +1776,11 @@ exit_findbm:
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()
@ -2056,7 +2034,7 @@ UniataFindFakeBusMasterController(
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;
@ -2129,13 +2107,11 @@ exit_findbm:
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()
@ -2184,6 +2160,13 @@ UniataConnectIntr2(
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;
@ -2500,6 +2483,42 @@ AtapiFindController(
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.
@ -2507,16 +2526,18 @@ retryIdentifier:
// 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;
@ -2537,11 +2558,13 @@ retryIdentifier:
// 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",
@ -2578,6 +2601,12 @@ not_found:
(*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;
@ -2604,10 +2633,13 @@ not_found:
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);
@ -2661,6 +2693,8 @@ not_found:
// 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"));
@ -2702,6 +2736,7 @@ not_found:
MCACount++;
}
ConfigInfo->NumberOfBuses++; // add virtual channel for communication port
KdPrint2((PRINT_PREFIX
"AtapiFindController: return SP_RETURN_FOUND\n"));
return(SP_RETURN_FOUND);
@ -2720,18 +2755,16 @@ not_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,
@ -2747,64 +2780,98 @@ UniataAnybodyHome(
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;
}
// Select the device.
SelectDrive(chan, deviceNumber);
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;
}
if(!UniataIsSATARangeAvailable(deviceExtension, lChannel)) {
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) {
KdPrint2((PRINT_PREFIX " nobody home! %#x != 0x55\n", signatureLow));
UniataForgetDevice(LunExt);
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 FALSE;
}
} else {
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 FALSE;
return ATA_AT_HOME_NOBODY;
}
if(SStatus.SPD < SStatus_SPD_Gen1) {
KdPrint2((PRINT_PREFIX " SATA SPD < SStatus_SPD_Gen1\n"));
return FALSE;
return ATA_AT_HOME_NOBODY;
}
if(SStatus.IPM == SStatus_IPM_NoDev) {
KdPrint2((PRINT_PREFIX " SATA IPN == SStatus_IPM_NoDev\n"));
return FALSE;
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);
}
return TRUE;
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"));
return ATA_AT_HOME_ATAPI;
}
if(deviceExtension->HwFlags & UNIATA_AHCI) {
KdPrint2((PRINT_PREFIX " AHCI HDD at home\n"));
return ATA_AT_HOME_HDD;
}
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) {
if(signatureLow == 0xff || signatureLow == 0) {
KdPrint2((PRINT_PREFIX " nobody home! %#x != 0x55\n", signatureLow));
UniataForgetDevice(LunExt);
return ATA_AT_HOME_NOBODY;
}
// another chance
signatureLow = AtapiReadPort1(chan, IDX_ATAPI_IO1_o_ByteCountHigh);
signatureLow += 2;
AtapiWritePort1(chan, IDX_ATAPI_IO1_o_ByteCountHigh, signatureLow);
AtapiStallExecution(5);
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 ATA_AT_HOME_NOBODY;
}
return ATA_AT_HOME_XXX;
}
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;
}
KdPrint2((PRINT_PREFIX " HDD at home\n"));
return ATA_AT_HOME_HDD;
} // end UniataAnybodyHome()
ULONG
@ -2830,10 +2897,14 @@ CheckDevice(
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)) {
@ -2856,11 +2927,11 @@ CheckDevice(
}
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"));
@ -2882,16 +2953,18 @@ CheckDevice(
"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;
@ -2919,7 +2992,7 @@ CheckDevice(
}
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);
@ -2934,6 +3007,7 @@ CheckDevice(
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) {
@ -2946,8 +3020,11 @@ CheckDevice(
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
@ -3074,7 +3151,7 @@ FindDevices(
// 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;

View file

@ -1,6 +1,6 @@
/*++
Copyright (c) 2008-2010 Alexandr A. Telyatnikov (Alter)
Copyright (c) 2008-2012 Alexandr A. Telyatnikov (Alter)
Module Name:
id_probe.cpp
@ -306,11 +306,13 @@ UniataRemoveRequest(
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 &&
@ -320,10 +322,12 @@ UniataRemoveRequest(
// 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;

View file

@ -1,6 +1,6 @@
/*++
Copyright (c) 2008-2011 Alexandr A. Telyatnikov (Alter)
Copyright (c) 2008-2012 Alexandr A. Telyatnikov (Alter)
Module Name:
id_probe.cpp
@ -76,7 +76,7 @@ UniataSataConnect(
}
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,
@ -156,7 +156,7 @@ UniataSataPhyEnable(
}
KdPrint2((PRINT_PREFIX "UniataSataPhyEnable: failed\n"));
return 0xff;
return IDE_STATUS_WRONG;
} // end UniataSataPhyEnable()
BOOLEAN
@ -200,6 +200,7 @@ UniataSataClearErr(
return TRUE;
}
}
//return TRUE;
}
}
return FALSE;
@ -408,7 +409,7 @@ UniataSataWritePM(
if(chan->DeviceExtension->HwFlags & UNIATA_AHCI) {
return UniataAhciWritePM(chan, DeviceNumber, Reg, value);
}
return 0xff;
return IDE_STATUS_WRONG;
} // end UniataSataWritePM()
ULONG
@ -628,6 +629,10 @@ UniataAhciInit(
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);
@ -718,7 +723,9 @@ UniataAhciDetect(
ULONG i, n;
ULONG PI;
ULONG CAP;
ULONG CAP2;
ULONG GHC;
ULONG BOHC;
ULONG NumberChannels;
ULONG v_Mn, v_Mj;
ULONG BaseMemAddress;
@ -726,7 +733,7 @@ UniataAhciDetect(
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;
}
@ -762,11 +769,16 @@ UniataAhciDetect(
}
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);
@ -807,7 +819,7 @@ UniataAhciDetect(
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));
@ -819,7 +831,14 @@ UniataAhciDetect(
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"));
@ -827,11 +846,15 @@ UniataAhciDetect(
}
}
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()
@ -855,7 +878,7 @@ UniataAhciStatus(
//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));
@ -873,7 +896,7 @@ UniataAhciStatus(
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 */
@ -887,11 +910,35 @@ UniataAhciStatus(
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()
@ -905,35 +952,42 @@ UniataAhciSetupFIS_H2D(
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;
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;
if(chan->lun[DeviceNumber]->DeviceFlags & DFLAGS_ATAPI_DEVICE) {
fis[2] = IDE_COMMAND_ATAPI_PACKET;
// 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;
@ -954,32 +1008,40 @@ UniataAhciSetupFIS_H2D(
}
}
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;
}
@ -991,48 +1053,36 @@ UniataAhciSetupFIS_H2D(
UCHAR
NTAPI
UniataAhciSendCommand(
IN PVOID HwDeviceExtension,
IN ULONG lChannel,
IN ULONG DeviceNumber,
IN ULONG flags,
UniataAhciWaitCommandReady(
IN PHW_CHANNEL chan,
IN ULONG timeout
)
{
PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
PHW_CHANNEL chan = &deviceExtension->chan[lChannel];
//ULONG Channel = deviceExtension->Channel + lChannel;
//ULONG hIS;
ULONG CI = 0;
AHCI_IS_REG IS;
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 CI=0;
ULONG i;
ULONG SError;
ULONG tag=0;
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->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);
timeout *= 5;
for (i=0; i<timeout; i++) {
AtapiStallExecution(1000);
CI = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_CI);
if (!(CI & ATA_AHCI_P_CMD_ST)) {
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));
@ -1045,6 +1095,7 @@ UniataAhciSendCommand(
UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_IS, IS.Reg);
if (timeout && (i >= timeout)) {
#ifdef DBG
ULONG TFD;
SError = AtapiReadPort4(chan, IDX_SATA_SError);
@ -1052,14 +1103,172 @@ UniataAhciSendCommand(
TFD = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_TFD);
KdPrint2((" TFD %#x\n", TFD));
#endif //DBG
return 0xff;
return IDE_STATUS_WRONG;
}
return IDE_STATUS_IDLE;
} // end UniataAhciWaitCommandReady()
UCHAR
NTAPI
UniataAhciSendCommand(
IN PVOID HwDeviceExtension,
IN ULONG lChannel,
IN ULONG DeviceNumber,
IN USHORT ahci_flags,
IN ULONG timeout
)
{
PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
PHW_CHANNEL chan = &deviceExtension->chan[lChannel];
//ULONG Channel = deviceExtension->Channel + lChannel;
//ULONG hIS;
//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;
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)) | 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, 1 << tag);
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
}
AtaReq = (PATA_REQ)(Srb->SrbExtension);
//KdPrint((" Srb %#x, AtaReq %#x\n", Srb, AtaReq));
AHCI_CMD = AtaReq->ahci.ahci_cmd_ptr;
fis_size = UniataAhciSetupFIS_H2D(deviceExtension, DeviceNumber, lChannel,
&(AHCI_CMD->cfis[0]),
command,
lba,
bcount,
feature
);
if(!fis_size) {
KdPrint2(("!fis_size\n"));
return IDE_STATUS_WRONG;
}
//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));
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;
}
}
AtaReq->ahci.io_cmd_flags = ahci_flags;
#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
UniataAhciSoftReset(
@ -1082,7 +1291,7 @@ UniataAhciSoftReset(
PUCHAR RCV_FIS = &(chan->AhciCtlBlock->rcv_fis.rfis[0]);
#ifdef DBG
UniataDumpAhciPortRegs(chan);
// UniataDumpAhciPortRegs(chan);
#endif // DBG
/* kick controller into sane state */
@ -1091,7 +1300,7 @@ UniataAhciSoftReset(
UniataAhciStart(chan);
#ifdef DBG
UniataDumpAhciPortRegs(chan);
// UniataDumpAhciPortRegs(chan);
#endif // DBG
/* pull reset active */
@ -1101,7 +1310,7 @@ UniataAhciSoftReset(
//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);
}
@ -1113,7 +1322,7 @@ UniataAhciSoftReset(
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);
}
@ -1172,9 +1381,9 @@ UniataAhciHardReset(
(*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. */
@ -1467,31 +1676,60 @@ UniataAhciBeginTransaction(
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;
@ -1511,7 +1749,7 @@ UniataAhciBeginTransaction(
}
AtaReq->ahci.in_status = TFD;
return 0x00;
return IDE_STATUS_SUCCESS;
}
}
@ -1532,17 +1770,27 @@ UniataAhciEndTransaction(
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;
@ -1560,7 +1808,42 @@ UniataAhciEndTransaction(
((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;
@ -1578,7 +1861,7 @@ UniataAhciResume(
KdPrint2(("UniataAhciResume: lChan %d\n", chan->lChannel));
#ifdef DBG
UniataDumpAhciPortRegs(chan);
//UniataDumpAhciPortRegs(chan);
#endif // DBG
/* Disable port interrupts */
@ -1617,7 +1900,7 @@ UniataAhciResume(
);
#ifdef DBG
UniataDumpAhciPortRegs(chan);
//UniataDumpAhciPortRegs(chan);
#endif // DBG
UniataAhciStartFR(chan);
@ -1710,7 +1993,7 @@ UniataAhciReadPM(
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;
}
@ -1755,7 +2038,7 @@ UniataAhciWritePM(
case IDX_SATA_SControl:
Reg = 2; break;
default:
return 0xff;
return IDE_STATUS_WRONG;
}
}
@ -1773,9 +2056,9 @@ UniataAhciWritePM(
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);
@ -1806,11 +2089,82 @@ IN OUT PATA_REQ AtaReq
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()

View file

@ -1,6 +1,6 @@
/*++
Copyright (c) 2008-2011 Alexandr A. Telyatnikov (Alter)
Copyright (c) 2008-2012 Alexandr A. Telyatnikov (Alter)
Module Name:
id_probe.cpp
@ -123,6 +123,14 @@ UniataAhciInit(
IN PVOID HwDeviceExtension
);
#if DBG
VOID
NTAPI
UniataDumpAhciPortRegs(
IN PHW_CHANNEL chan
);
#endif
BOOLEAN
NTAPI
UniataAhciDetect(
@ -149,8 +157,14 @@ UniataAhciSetupFIS_H2D(
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
@ -159,6 +173,24 @@ UniataAhciSendCommand(
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
);
@ -289,7 +321,32 @@ UniataAhciUlongFromRFIS(
(((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
@ -314,4 +371,14 @@ UniataAhciSetupCmdPtr(
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__

View file

@ -98,6 +98,19 @@ typedef union _CDB {
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

View file

@ -1,6 +1,6 @@
/*++
Copyright (c) 2002-2005 Alexandr A. Telyatnikov (Alter)
Copyright (c) 2002-2012 Alexandr A. Telyatnikov (Alter)
Module Name:
tools.h
@ -94,195 +94,6 @@ typedef struct _FOUR_BYTE {
}
#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
@ -298,7 +109,7 @@ if((a)!=NULL) { \
KdPrint(("\n")); \
}
#define BrutePoint() {}
#define BrutePoint() { ASSERT(0); }
#define DbgAllocatePool(x,y) ExAllocatePool(x,y)
#define DbgFreePool(x) ExFreePool(x)

View file

@ -1,10 +1,10 @@
#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"