mirror of
https://github.com/reactos/reactos.git
synced 2024-08-26 13:18:51 +00:00
1911 lines
60 KiB
C
1911 lines
60 KiB
C
/*++
|
|
|
|
Copyright (c) 2002-2018 Alexandr A. Telyatnikov (Alter)
|
|
|
|
Module Name:
|
|
bsmaster.h
|
|
|
|
Abstract:
|
|
This file contains DMA/UltraDMA and IDE BusMastering related definitions,
|
|
internal structures and useful macros
|
|
|
|
Author:
|
|
Alexander A. Telyatnikov (Alter)
|
|
|
|
Environment:
|
|
kernel mode only
|
|
|
|
Notes:
|
|
|
|
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
|
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
|
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
|
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
|
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
|
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
Revision History:
|
|
|
|
Code was created by
|
|
Alter, Copyright (c) 2002-2015
|
|
|
|
Some definitions were taken from FreeBSD 4.3-9.2 ATA driver by
|
|
Søren Schmidt, Copyright (c) 1998-2014
|
|
|
|
Licence:
|
|
GPLv2
|
|
|
|
--*/
|
|
|
|
#ifndef __IDE_BUSMASTER_H__
|
|
#define __IDE_BUSMASTER_H__
|
|
|
|
#include "config.h"
|
|
|
|
#include "tools.h"
|
|
|
|
//
|
|
//
|
|
//
|
|
#define ATA_IDLE 0x0
|
|
#define ATA_IMMEDIATE 0x1
|
|
#define ATA_WAIT_INTR 0x2
|
|
#define ATA_WAIT_READY 0x3
|
|
#define ATA_ACTIVE 0x4
|
|
#define ATA_ACTIVE_ATA 0x5
|
|
#define ATA_ACTIVE_ATAPI 0x6
|
|
#define ATA_REINITING 0x7
|
|
#define ATA_WAIT_BASE_READY 0x8
|
|
#define ATA_WAIT_IDLE 0x9
|
|
|
|
|
|
#include "bm_devs_decl.h"
|
|
|
|
#include "uata_ctl.h"
|
|
|
|
#pragma pack(push, 8)
|
|
|
|
#define MAX_RETRIES 6
|
|
#define RETRY_UDMA2 1
|
|
#define RETRY_WDMA 2
|
|
#define RETRY_PIO 3
|
|
|
|
|
|
#define IO_WD1 0x1F0 /* Primary Fixed Disk Controller */
|
|
#define IO_WD2 0x170 /* Secondary Fixed Disk Controller */
|
|
#define IP_PC98_BANK 0x432
|
|
#define IO_FLOPPY_INT 0x3F6 /* AltStatus inside Floppy I/O range */
|
|
|
|
#define PCI_ADDRESS_IOMASK 0xfffffff0
|
|
|
|
#define ATA_BM_OFFSET1 0x08
|
|
#define ATA_IOSIZE 0x08
|
|
#define ATA_ALTOFFSET 0x206 /* alternate registers offset */
|
|
#define ATA_PCCARD_ALTOFFSET 0x0e /* do for PCCARD devices */
|
|
#define ATA_ALTIOSIZE 0x01 /* alternate registers size */
|
|
#define ATA_BMIOSIZE 0x20
|
|
#define ATA_PC98_BANKIOSIZE 0x01
|
|
//#define ATA_MAX_LBA28 DEF_U64(0x0fffffff)
|
|
// Hitachi 1 Tb HDD didn't allow LBA28 with BCount > 1 beyond this LBA
|
|
#define ATA_MAX_IOLBA28 DEF_U64(0x0fffff80)
|
|
#define ATA_MAX_LBA28 DEF_U64(0x0fffffff)
|
|
|
|
#define ATA_MAX_IOLBA32 DEF_U64(0xffffff80)
|
|
#define ATA_MAX_LBA32 DEF_U64(0xffffffff)
|
|
|
|
#define ATA_DMA_ENTRIES 256 /* PAGESIZE/2/sizeof(BM_DMA_ENTRY)*/
|
|
#define ATA_DMA_EOT 0x80000000
|
|
|
|
#define DEV_BSIZE 512
|
|
|
|
#define ATAPI_MAGIC_LSB 0x14
|
|
#define ATAPI_MAGIC_MSB 0xeb
|
|
|
|
#define AHCI_MAX_PORT 32
|
|
|
|
#define SATA_MAX_PM_UNITS 16
|
|
|
|
typedef struct _BUSMASTER_CTX {
|
|
PBUSMASTER_CONTROLLER_INFORMATION* BMListPtr;
|
|
ULONG* BMListLen;
|
|
} BUSMASTER_CTX, *PBUSMASTER_CTX;
|
|
|
|
#define PCI_DEV_CLASS_STORAGE 0x01
|
|
|
|
#define PCI_DEV_SUBCLASS_IDE 0x01
|
|
#define PCI_DEV_SUBCLASS_RAID 0x04
|
|
#define PCI_DEV_SUBCLASS_ATA 0x05
|
|
#define PCI_DEV_SUBCLASS_SATA 0x06
|
|
|
|
#define PCI_DEV_PROGIF_AHCI_1_0 0x01
|
|
|
|
#pragma pack(push, 1)
|
|
|
|
/* structure for holding DMA address data */
|
|
typedef struct BM_DMA_ENTRY {
|
|
ULONG base;
|
|
ULONG count;
|
|
} BM_DMA_ENTRY, *PBM_DMA_ENTRY;
|
|
|
|
typedef struct _IDE_BUSMASTER_REGISTERS {
|
|
UCHAR Command;
|
|
UCHAR DeviceSpecific0;
|
|
UCHAR Status;
|
|
UCHAR DeviceSpecific1;
|
|
ULONG PRD_Table;
|
|
} IDE_BUSMASTER_REGISTERS, *PIDE_BUSMASTER_REGISTERS;
|
|
|
|
#define BM_STATUS_ACTIVE 0x01
|
|
#define BM_STATUS_ERR 0x02
|
|
#define BM_STATUS_INTR 0x04
|
|
#define BM_STATUS_MASK 0x07
|
|
#define BM_STATUS_DRIVE_0_DMA 0x20
|
|
#define BM_STATUS_DRIVE_1_DMA 0x40
|
|
#define BM_STATUS_SIMPLEX_ONLY 0x80
|
|
|
|
#define BM_COMMAND_START_STOP 0x01
|
|
/*#define BM_COMMAND_WRITE 0x08
|
|
#define BM_COMMAND_READ 0x00*/
|
|
#define BM_COMMAND_WRITE 0x00
|
|
#define BM_COMMAND_READ 0x08
|
|
|
|
#define BM_DS0_SII_DMA_ENABLE (1 << 0) /* DMA run switch */
|
|
#define BM_DS0_SII_IRQ (1 << 3) /* ??? */
|
|
#define BM_DS0_SII_DMA_SATA_IRQ (1 << 4) /* OR of all SATA IRQs */
|
|
#define BM_DS0_SII_DMA_ERROR (1 << 17) /* PCI bus error */
|
|
#define BM_DS0_SII_DMA_COMPLETE (1 << 18) /* cmd complete / IRQ pending */
|
|
|
|
|
|
#define IDX_BM_IO (IDX_IO2_o+IDX_IO2_o_SZ)
|
|
//#define IDX_BM_IO_SZ sizeof(IDE_BUSMASTER_REGISTERS)
|
|
#define IDX_BM_IO_SZ 5
|
|
|
|
#define IDX_BM_Command (FIELD_OFFSET(IDE_BUSMASTER_REGISTERS, Command )+IDX_BM_IO)
|
|
#define IDX_BM_DeviceSpecific0 (FIELD_OFFSET(IDE_BUSMASTER_REGISTERS, DeviceSpecific0)+IDX_BM_IO)
|
|
#define IDX_BM_Status (FIELD_OFFSET(IDE_BUSMASTER_REGISTERS, Status )+IDX_BM_IO)
|
|
#define IDX_BM_DeviceSpecific1 (FIELD_OFFSET(IDE_BUSMASTER_REGISTERS, DeviceSpecific1)+IDX_BM_IO)
|
|
#define IDX_BM_PRD_Table (FIELD_OFFSET(IDE_BUSMASTER_REGISTERS, PRD_Table )+IDX_BM_IO)
|
|
|
|
typedef struct _IDE_AHCI_REGISTERS {
|
|
// HBA Capabilities
|
|
struct {
|
|
ULONG NOP:5; // number of ports
|
|
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 FBSS:1; // FIS-based Switching Supported
|
|
|
|
ULONG SPM:1; // port multiplier
|
|
ULONG SAM:1; // AHCI mode only
|
|
ULONG SNZO:1; // non-zero DMA offset
|
|
ULONG ISS:4; // interface speed
|
|
ULONG SCLO:1; // command list override
|
|
ULONG SAL:1; // activity LED
|
|
ULONG SALP:1; // aggressive link power management
|
|
ULONG SSS:1; // staggered spin-up
|
|
ULONG SIS:1; // interlock switch
|
|
ULONG SSNTF:1; // Supports SNotification Register
|
|
ULONG SNCQ:1; // native command queue
|
|
ULONG S64A:1; // 64bit addr
|
|
} CAP;
|
|
|
|
#define AHCI_CAP_NOP_MASK 0x0000001f
|
|
#define AHCI_CAP_CCC 0x00000080
|
|
#define AHCI_CAP_NCS_MASK 0x00001f00
|
|
#define AHCI_CAP_PMD 0x00008000
|
|
#define AHCI_CAP_SPM 0x00020000
|
|
#define AHCI_CAP_SAM 0x00040000
|
|
#define AHCI_CAP_ISS_MASK 0x00f00000
|
|
#define AHCI_CAP_SCLO 0x01000000
|
|
#define AHCI_CAP_SNTF 0x20000000
|
|
#define AHCI_CAP_NCQ 0x40000000
|
|
#define AHCI_CAP_S64A 0x80000000
|
|
|
|
// Global HBA Control
|
|
struct {
|
|
ULONG HR:1; // HBA Reset
|
|
ULONG IE:1; // interrupt enable
|
|
ULONG Reserved2_30:1;
|
|
ULONG AE:1; // AHCI enable
|
|
} GHC;
|
|
|
|
#define AHCI_GHC 0x04
|
|
#define AHCI_GHC_HR 0x00000001
|
|
#define AHCI_GHC_IE 0x00000002
|
|
#define AHCI_GHC_AE 0x80000000
|
|
|
|
// Interrupt status (bit mask)
|
|
ULONG IS; // 0x08
|
|
// Ports implemented (bit mask)
|
|
ULONG PI; // 0x0c
|
|
// AHCI Version
|
|
ULONG VS; // 0x10
|
|
|
|
ULONG CCC_CTL; // 0x14
|
|
ULONG CCC_PORTS; // 0x18
|
|
ULONG EM_LOC; // 0x1c
|
|
ULONG EM_CTL; // 0x20
|
|
|
|
// Extended HBA Capabilities
|
|
struct { // 0x24
|
|
ULONG BOH:1; // BIOS/OS Handoff
|
|
ULONG NVMP:1; // NVMHCI Present
|
|
ULONG APST:1; // Automatic Partial to Slumber Transitions
|
|
ULONG Reserved:29;
|
|
} CAP2;
|
|
|
|
#define AHCI_CAP2_BOH 0x00000001
|
|
#define AHCI_CAP2_NVMP 0x00000002
|
|
#define AHCI_CAP2_APST 0x00000004
|
|
|
|
// BIOS/OS Handoff Control and Status
|
|
struct { // 0x28
|
|
ULONG BB:1; // BIOS Busy
|
|
ULONG OOC:1; // OS Ownership Change
|
|
ULONG SOOE:1; // SMI on OS Ownership Change Enable
|
|
ULONG OOS:1; // OS Owned Semaphore
|
|
ULONG BOS:1; // BIOS Owned Semaphore
|
|
ULONG Reserved:27;
|
|
} BOHC;
|
|
|
|
#define AHCI_BOHC_BB 0x00000001
|
|
#define AHCI_BOHC_OOC 0x00000002
|
|
#define AHCI_BOHC_SOOE 0x00000004
|
|
#define AHCI_BOHC_OOS 0x00000008
|
|
#define AHCI_BOHC_BOS 0x00000010
|
|
|
|
UCHAR Reserved2[0x74];
|
|
|
|
UCHAR VendorSpec[0x60];
|
|
} IDE_AHCI_REGISTERS, *PIDE_AHCI_REGISTERS;
|
|
|
|
#define IDX_AHCI_CAP (FIELD_OFFSET(IDE_AHCI_REGISTERS, CAP))
|
|
#define IDX_AHCI_GHC (FIELD_OFFSET(IDE_AHCI_REGISTERS, GHC))
|
|
#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 {
|
|
|
|
struct {
|
|
ULONG DET:4; // Device Detection
|
|
|
|
#define SStatus_DET_NoDev 0x00
|
|
#define SStatus_DET_Dev_NoPhy 0x01
|
|
#define SStatus_DET_Dev_Ok 0x03
|
|
#define SStatus_DET_Offline 0x04
|
|
|
|
ULONG SPD:4; // Current Interface Speed
|
|
|
|
#define SStatus_SPD_NoDev 0x00
|
|
#define SStatus_SPD_Gen1 0x01
|
|
#define SStatus_SPD_Gen2 0x02
|
|
#define SStatus_SPD_Gen3 0x03
|
|
|
|
ULONG IPM:4; // Interface Power Management
|
|
|
|
#define SStatus_IPM_NoDev 0x00
|
|
#define SStatus_IPM_Active 0x01
|
|
#define SStatus_IPM_Partial 0x02
|
|
#define SStatus_IPM_Slumber 0x06
|
|
|
|
ULONG Reserved:20;
|
|
};
|
|
ULONG Reg;
|
|
|
|
} SATA_SSTATUS_REG, *PSATA_SSTATUS_REG;
|
|
|
|
#define ATA_SS_DET_MASK 0x0000000f
|
|
#define ATA_SS_DET_NO_DEVICE 0x00000000
|
|
#define ATA_SS_DET_DEV_PRESENT 0x00000001
|
|
#define ATA_SS_DET_PHY_ONLINE 0x00000003
|
|
#define ATA_SS_DET_PHY_OFFLINE 0x00000004
|
|
|
|
#define ATA_SS_SPD_MASK 0x000000f0
|
|
#define ATA_SS_SPD_NO_SPEED 0x00000000
|
|
#define ATA_SS_SPD_GEN1 0x00000010
|
|
#define ATA_SS_SPD_GEN2 0x00000020
|
|
|
|
#define ATA_SS_IPM_MASK 0x00000f00
|
|
#define ATA_SS_IPM_NO_DEVICE 0x00000000
|
|
#define ATA_SS_IPM_ACTIVE 0x00000100
|
|
#define ATA_SS_IPM_PARTIAL 0x00000200
|
|
#define ATA_SS_IPM_SLUMBER 0x00000600
|
|
|
|
typedef union _SATA_SCONTROL_REG {
|
|
|
|
struct {
|
|
ULONG DET:4; // Device Detection Init
|
|
|
|
#define SControl_DET_DoNothing 0x00
|
|
#define SControl_DET_Idle 0x00
|
|
#define SControl_DET_Init 0x01
|
|
#define SControl_DET_Disable 0x04
|
|
|
|
ULONG SPD:4; // Speed Allowed
|
|
|
|
#define SControl_SPD_NoRestrict 0x00
|
|
#define SControl_SPD_LimGen1 0x01
|
|
#define SControl_SPD_LimGen2 0x02
|
|
#define SControl_SPD_LimGen3 0x03
|
|
|
|
ULONG IPM:4; // Interface Power Management Transitions Allowed
|
|
|
|
#define SControl_IPM_NoRestrict 0x00
|
|
#define SControl_IPM_NoPartial 0x01
|
|
#define SControl_IPM_NoSlumber 0x02
|
|
#define SControl_IPM_NoPartialSlumber 0x03
|
|
|
|
ULONG SPM:4; // Select Power Management, unused by AHCI
|
|
ULONG PMP:4; // Port Multiplier Port, unused by AHCI
|
|
ULONG Reserved:12;
|
|
};
|
|
ULONG Reg;
|
|
|
|
} SATA_SCONTROL_REG, *PSATA_SCONTROL_REG;
|
|
|
|
#define ATA_SC_DET_MASK 0x0000000f
|
|
#define ATA_SC_DET_IDLE 0x00000000
|
|
#define ATA_SC_DET_RESET 0x00000001
|
|
#define ATA_SC_DET_DISABLE 0x00000004
|
|
|
|
#define ATA_SC_SPD_MASK 0x000000f0
|
|
#define ATA_SC_SPD_NO_SPEED 0x00000000
|
|
#define ATA_SC_SPD_SPEED_GEN1 0x00000010
|
|
#define ATA_SC_SPD_SPEED_GEN2 0x00000020
|
|
#define ATA_SC_SPD_SPEED_GEN3 0x00000040
|
|
|
|
#define ATA_SC_IPM_MASK 0x00000f00
|
|
#define ATA_SC_IPM_NONE 0x00000000
|
|
#define ATA_SC_IPM_DIS_PARTIAL 0x00000100
|
|
#define ATA_SC_IPM_DIS_SLUMBER 0x00000200
|
|
|
|
typedef union _SATA_SERROR_REG {
|
|
|
|
struct {
|
|
struct {
|
|
UCHAR I:1; // Recovered Data Integrity Error
|
|
UCHAR M:1; // Recovered Communications Error
|
|
UCHAR Reserved_2_7:6;
|
|
|
|
UCHAR T:1; // Transient Data Integrity Error
|
|
UCHAR C:1; // Persistent Communication or Data Integrity Error
|
|
UCHAR P:1; // Protocol Error
|
|
UCHAR E:1; // Internal Error
|
|
UCHAR Reserved_12_15:4;
|
|
} ERR;
|
|
|
|
struct {
|
|
UCHAR N:1; // PhyRdy Change, PIS.PRCS
|
|
UCHAR I:1; // Phy Internal Error
|
|
UCHAR W:1; // Comm Wake
|
|
UCHAR B:1; // 10B to 8B Decode Error
|
|
UCHAR D:1; // Disparity Error, not used by AHCI
|
|
UCHAR C:1; // CRC Error
|
|
UCHAR H:1; // Handshake Error
|
|
UCHAR S:1; // Link Sequence Error
|
|
|
|
UCHAR T:1; // Transport state transition error
|
|
UCHAR F:1; // Unknown FIS Type
|
|
UCHAR X:1; // Exchanged
|
|
UCHAR Reserved_27_31:5;
|
|
} DIAG;
|
|
};
|
|
ULONG Reg;
|
|
|
|
} SATA_SERROR_REG, *PSATA_SERROR_REG;
|
|
|
|
#define ATA_SE_DATA_CORRECTED 0x00000001
|
|
#define ATA_SE_COMM_CORRECTED 0x00000002
|
|
#define ATA_SE_DATA_ERR 0x00000100
|
|
#define ATA_SE_COMM_ERR 0x00000200
|
|
#define ATA_SE_PROT_ERR 0x00000400
|
|
#define ATA_SE_HOST_ERR 0x00000800
|
|
#define ATA_SE_PHY_CHANGED 0x00010000
|
|
#define ATA_SE_PHY_IERROR 0x00020000
|
|
#define ATA_SE_COMM_WAKE 0x00040000
|
|
#define ATA_SE_DECODE_ERR 0x00080000
|
|
#define ATA_SE_PARITY_ERR 0x00100000
|
|
#define ATA_SE_CRC_ERR 0x00200000
|
|
#define ATA_SE_HANDSHAKE_ERR 0x00400000
|
|
#define ATA_SE_LINKSEQ_ERR 0x00800000
|
|
#define ATA_SE_TRANSPORT_ERR 0x01000000
|
|
#define ATA_SE_UNKNOWN_FIS 0x02000000
|
|
|
|
typedef struct _IDE_SATA_REGISTERS {
|
|
union {
|
|
SATA_SSTATUS_REG SStatus;
|
|
ULONG SStatus_Reg;
|
|
};
|
|
union {
|
|
SATA_SERROR_REG SError;
|
|
ULONG SError_Reg;
|
|
};
|
|
union {
|
|
SATA_SCONTROL_REG SControl;
|
|
ULONG SControl_Reg;
|
|
};
|
|
|
|
// SATA 1.2
|
|
|
|
ULONG SActive;
|
|
union {
|
|
ULONG Reg;
|
|
struct {
|
|
USHORT PMN; // PM Notify, bitmask
|
|
USHORT Reserved;
|
|
};
|
|
} SNTF;
|
|
ULONG SReserved[11];
|
|
} IDE_SATA_REGISTERS, *PIDE_SATA_REGISTERS;
|
|
|
|
#define IDX_SATA_IO (IDX_BM_IO+IDX_BM_IO_SZ)
|
|
//#define IDX_SATA_IO_SZ sizeof(IDE_SATA_REGISTERS)
|
|
#define IDX_SATA_IO_SZ 5
|
|
|
|
#define IDX_SATA_SStatus (0+IDX_SATA_IO)
|
|
#define IDX_SATA_SError (1+IDX_SATA_IO)
|
|
#define IDX_SATA_SControl (2+IDX_SATA_IO)
|
|
#define IDX_SATA_SActive (3+IDX_SATA_IO)
|
|
#define IDX_SATA_SNTF_PMN (4+IDX_SATA_IO)
|
|
|
|
#define IDX_INDEXED_IO (IDX_SATA_IO+IDX_SATA_IO_SZ)
|
|
#define IDX_INDEXED_IO_SZ 2
|
|
|
|
#define IDX_INDEXED_ADDR (0+IDX_INDEXED_IO)
|
|
#define IDX_INDEXED_DATA (1+IDX_INDEXED_IO)
|
|
|
|
#define IDX_MAX_REG (IDX_INDEXED_IO+IDX_INDEXED_IO_SZ)
|
|
|
|
|
|
typedef union _AHCI_IS_REG {
|
|
struct {
|
|
ULONG DHRS:1;// Device to Host Register FIS Interrupt
|
|
ULONG PSS:1; // PIO Setup FIS Interrupt
|
|
ULONG DSS:1; // DMA Setup FIS Interrupt
|
|
ULONG SDBS:1;// Set Device Bits Interrupt
|
|
ULONG UFS:1; // Unknown FIS Interrupt
|
|
ULONG DPS:1; // Descriptor Processed
|
|
ULONG PCS:1; // Port Connect Change Status
|
|
ULONG DMPS:1;// Device Mechanical Presence Status
|
|
|
|
ULONG Reserved_8_21:14;
|
|
ULONG PRCS:1;// PhyRdy Change Status
|
|
ULONG IPMS:1;// Incorrect Port Multiplier Status
|
|
|
|
ULONG OFS:1; // Overflow Status
|
|
ULONG Reserved_25:1;
|
|
ULONG INFS:1;// Interface Non-fatal Error Status
|
|
ULONG IFS:1; // Interface Fatal Error Status
|
|
ULONG HBDS:1;// Host Bus Data Error Status
|
|
ULONG HBFS:1;// Host Bus Fatal Error Status
|
|
ULONG TFES:1;// Task File Error Status
|
|
ULONG CPDS:1;// Cold Port Detect Status
|
|
};
|
|
ULONG Reg;
|
|
} AHCI_IS_REG, *PAHCI_IS_REG;
|
|
|
|
#define ATA_AHCI_P_IX_DHR 0x00000001
|
|
#define ATA_AHCI_P_IX_PS 0x00000002
|
|
#define ATA_AHCI_P_IX_DS 0x00000004
|
|
#define ATA_AHCI_P_IX_SDB 0x00000008
|
|
#define ATA_AHCI_P_IX_UF 0x00000010
|
|
#define ATA_AHCI_P_IX_DP 0x00000020
|
|
#define ATA_AHCI_P_IX_PC 0x00000040
|
|
#define ATA_AHCI_P_IX_DI 0x00000080
|
|
|
|
#define ATA_AHCI_P_IX_PRC 0x00400000
|
|
#define ATA_AHCI_P_IX_IPM 0x00800000
|
|
#define ATA_AHCI_P_IX_OF 0x01000000
|
|
#define ATA_AHCI_P_IX_INF 0x04000000
|
|
#define ATA_AHCI_P_IX_IF 0x08000000
|
|
#define ATA_AHCI_P_IX_HBD 0x10000000
|
|
#define ATA_AHCI_P_IX_HBF 0x20000000
|
|
#define ATA_AHCI_P_IX_TFE 0x40000000
|
|
#define ATA_AHCI_P_IX_CPD 0x80000000
|
|
|
|
#define AHCI_CLB_ALIGNEMENT_MASK ((ULONGLONG)(1024-1))
|
|
#define AHCI_FIS_ALIGNEMENT_MASK ((ULONGLONG)(256-1))
|
|
#define AHCI_CMD_ALIGNEMENT_MASK ((ULONGLONG)(128-1))
|
|
|
|
typedef struct _IDE_AHCI_PORT_REGISTERS {
|
|
union {
|
|
struct {
|
|
ULONG CLB; // command list base address, 1K-aligned
|
|
ULONG CLBU; // command list base address (upper 32bits)
|
|
};
|
|
ULONGLONG CLB64;
|
|
}; // 0x100 + 0x80*c + 0x0000
|
|
|
|
union {
|
|
struct {
|
|
ULONG FB; // FIS base address
|
|
ULONG FBU; // FIS base address (upper 32bits)
|
|
};
|
|
ULONGLONG FB64;
|
|
}; // 0x100 + 0x80*c + 0x0008
|
|
|
|
union {
|
|
ULONG IS_Reg; // interrupt status
|
|
AHCI_IS_REG IS;
|
|
}; // 0x100 + 0x80*c + 0x0010
|
|
|
|
union {
|
|
ULONG Reg; // interrupt enable
|
|
struct {
|
|
ULONG DHRE:1;// Device to Host Register FIS Interrupt Enable
|
|
ULONG PSE:1; // PIO Setup FIS Interrupt Enable
|
|
ULONG DSE:1; // DMA Setup FIS Interrupt Enable
|
|
ULONG SDBE:1;// Set Device Bits FIS Interrupt Enable
|
|
ULONG UFE:1; // Unknown FIS Interrupt Enable
|
|
ULONG DPE:1; // Descriptor Processed Interrupt Enable
|
|
ULONG PCE:1; // Port Change Interrupt Enable
|
|
ULONG DPME:1;// Device Mechanical Presence Enable
|
|
|
|
ULONG Reserved_8_21:14;
|
|
ULONG PRCE:1;// PhyRdy Change Interrupt Enable
|
|
ULONG IPME:1;// Incorrect Port Multiplier Enable
|
|
ULONG OFE:1; // Overflow Enable
|
|
ULONG Reserved_25:1;
|
|
ULONG INFE:1;// Interface Non-fatal Error Enable
|
|
ULONG IFE:1; // Interface Fatal Error Enable
|
|
ULONG HBDE:1;// Host Bus Data Error Enable
|
|
ULONG HBFE:1;// Host Bus Fatal Error Enable
|
|
ULONG TFEE:1;// Task File Error Enable
|
|
ULONG CPDE:1;// Cold Port Detect Enable
|
|
};
|
|
} IE; // 0x100 + 0x80*c + 0x0014
|
|
|
|
union {
|
|
ULONG Reg; // command register
|
|
struct {
|
|
|
|
ULONG ST:1; // Start
|
|
ULONG SUD:1; // Spin-Up Device
|
|
ULONG POD:1; // Power On Device
|
|
ULONG CLO:1; // Command List Override
|
|
ULONG FRE:1; // FIS Receive Enable
|
|
ULONG Reserved_5_7:3;
|
|
|
|
ULONG CCS:5; // Current Command Slot
|
|
ULONG MPSS:1;// Mechanical Presence Switch State
|
|
ULONG FR:1; // FIS Receive Running
|
|
ULONG CR:1; // Command List Running
|
|
|
|
ULONG CPS:1; // Cold Presence State
|
|
ULONG PMA:1; // Port Multiplier Attached
|
|
ULONG HPCP:1;// Hot Plug Capable Port
|
|
ULONG MPSP:1;// Mechanical Presence Switch Attached to Port
|
|
ULONG CPD:1; // Cold Presence Detection
|
|
ULONG ESP:1; // External SATA Port
|
|
ULONG Reserved_22_23:2;
|
|
|
|
ULONG ATAPI:1; // Device is ATAPI
|
|
ULONG DLAE:1;// Drive LED on ATAPI Enable
|
|
ULONG ALPE:1;// Aggressive Link Power Management Enable
|
|
ULONG ASP:1; // Aggressive Slumber / Partial
|
|
ULONG ICC:4; // Interface Communication Control
|
|
|
|
#define SATA_CMD_ICC_Idle 0x00
|
|
#define SATA_CMD_ICC_NoOp 0x00
|
|
#define SATA_CMD_ICC_Active 0x01
|
|
#define SATA_CMD_ICC_Partial 0x02
|
|
#define SATA_CMD_ICC_Slumber 0x06
|
|
};
|
|
} CMD; // 0x100 + 0x80*c + 0x0018
|
|
|
|
ULONG Reserved;
|
|
|
|
union {
|
|
ULONG Reg; // Task File Data
|
|
struct {
|
|
struct {
|
|
UCHAR ERR:1;
|
|
UCHAR cs1:2;// command-specific
|
|
UCHAR DRQ:1;
|
|
UCHAR cs2:3;// command-specific
|
|
UCHAR BSY:1;
|
|
} STS;
|
|
UCHAR ERR; // Contains the latest copy of the task file error register.
|
|
UCHAR Reserved[2];
|
|
};
|
|
} TFD; // 0x100 + 0x80*c + 0x0020
|
|
|
|
union {
|
|
ULONG Reg; // signature
|
|
struct {
|
|
UCHAR SectorCount;
|
|
UCHAR LbaLow; // IDX_IO1_i_BlockNumber
|
|
UCHAR LbaMid; // IDX_IO1_i_CylinderLow
|
|
UCHAR LbaHigh; // IDX_IO1_i_CylinderHigh
|
|
};
|
|
} SIG; // 0x100 + 0x80*c + 0x0024
|
|
union {
|
|
ULONG SStatus; // SCR0
|
|
SATA_SSTATUS_REG SSTS;
|
|
}; // 0x100 + 0x80*c + 0x0028
|
|
union {
|
|
ULONG SControl; // SCR2
|
|
SATA_SCONTROL_REG SCTL;
|
|
}; // 0x100 + 0x80*c + 0x002c
|
|
union {
|
|
ULONG SError; // SCR1
|
|
SATA_SERROR_REG SERR;
|
|
}; // 0x100 + 0x80*c + 0x0030
|
|
union {
|
|
ULONG SACT; // SCR3
|
|
ULONG SActive; // bitmask
|
|
}; // 0x100 + 0x80*c + 0x0034
|
|
|
|
ULONG CI; // Command issue, bitmask, 0x100 + 0x80*c + 0x0038
|
|
|
|
// AHCI 1.1
|
|
union {
|
|
ULONG Reg;
|
|
struct {
|
|
USHORT PMN; // PM Notify, bitmask
|
|
USHORT Reserved;
|
|
};
|
|
} SNTF; // 0x100 + 0x80*c + 0x003c
|
|
|
|
// 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;
|
|
|
|
#define IDX_AHCI_P_CLB (FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS, CLB))
|
|
#define IDX_AHCI_P_FB (FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS, FB))
|
|
#define IDX_AHCI_P_IS (FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS, IS))
|
|
#define IDX_AHCI_P_IE (FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS, IE))
|
|
#define IDX_AHCI_P_CI (FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS, CI))
|
|
#define IDX_AHCI_P_TFD (FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS, TFD))
|
|
#define IDX_AHCI_P_SIG (FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS, SIG))
|
|
#define IDX_AHCI_P_CMD (FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS, CMD))
|
|
#define IDX_AHCI_P_SStatus (FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS, SStatus))
|
|
#define IDX_AHCI_P_SControl (FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS, SControl))
|
|
#define IDX_AHCI_P_SError (FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS, SError))
|
|
#define IDX_AHCI_P_ACT (FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS, SACT))
|
|
|
|
#define IDX_AHCI_P_SNTF (FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS, SNTF))
|
|
|
|
// AHCI commands ( -> IDX_AHCI_P_CMD)
|
|
#define ATA_AHCI_P_CMD_ST 0x00000001
|
|
#define ATA_AHCI_P_CMD_SUD 0x00000002
|
|
#define ATA_AHCI_P_CMD_POD 0x00000004
|
|
#define ATA_AHCI_P_CMD_CLO 0x00000008
|
|
#define ATA_AHCI_P_CMD_FRE 0x00000010
|
|
#define ATA_AHCI_P_CMD_CCS_MASK 0x00001f00
|
|
#define ATA_AHCI_P_CMD_ISS 0x00002000
|
|
#define ATA_AHCI_P_CMD_FR 0x00004000
|
|
#define ATA_AHCI_P_CMD_CR 0x00008000
|
|
#define ATA_AHCI_P_CMD_CPS 0x00010000
|
|
#define ATA_AHCI_P_CMD_PMA 0x00020000
|
|
#define ATA_AHCI_P_CMD_HPCP 0x00040000
|
|
#define ATA_AHCI_P_CMD_ISP 0x00080000
|
|
#define ATA_AHCI_P_CMD_CPD 0x00100000
|
|
#define ATA_AHCI_P_CMD_ATAPI 0x01000000
|
|
#define ATA_AHCI_P_CMD_DLAE 0x02000000
|
|
#define ATA_AHCI_P_CMD_ALPE 0x04000000
|
|
#define ATA_AHCI_P_CMD_ASP 0x08000000
|
|
#define ATA_AHCI_P_CMD_ICC_MASK 0xf0000000
|
|
#define ATA_AHCI_P_CMD_NOOP 0x00000000
|
|
#define ATA_AHCI_P_CMD_ACTIVE 0x10000000
|
|
#define ATA_AHCI_P_CMD_PARTIAL 0x20000000
|
|
#define ATA_AHCI_P_CMD_SLUMBER 0x60000000
|
|
|
|
|
|
typedef struct _IDE_AHCI_PRD_ENTRY {
|
|
union {
|
|
ULONG base;
|
|
ULONGLONG base64;
|
|
struct {
|
|
ULONG DBA;
|
|
union {
|
|
ULONG DBAU;
|
|
ULONG baseu;
|
|
};
|
|
};
|
|
};
|
|
ULONG Reserved1;
|
|
|
|
union {
|
|
struct {
|
|
ULONG DBC:22;
|
|
ULONG Reserved2:9;
|
|
ULONG I:1;
|
|
};
|
|
ULONG DBC_ULONG;
|
|
};
|
|
|
|
} IDE_AHCI_PRD_ENTRY, *PIDE_AHCI_PRD_ENTRY;
|
|
|
|
#define ATA_AHCI_DMA_ENTRIES (PAGE_SIZE/2/sizeof(IDE_AHCI_PRD_ENTRY)) /* 128 */
|
|
#define ATA_AHCI_MAX_TAGS 32
|
|
|
|
#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)
|
|
|
|
#define AHCI_DEV_SEL_1 0x00
|
|
#define AHCI_DEV_SEL_2 0x01
|
|
#define AHCI_DEV_SEL_PM 0x0f
|
|
|
|
/* 128-byte aligned */
|
|
typedef struct _IDE_AHCI_CMD {
|
|
UCHAR cfis[64];
|
|
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;
|
|
|
|
|
|
/* cmd_flags */
|
|
#define ATA_AHCI_CMD_ATAPI 0x0020
|
|
#define ATA_AHCI_CMD_WRITE 0x0040
|
|
#define ATA_AHCI_CMD_PREFETCH 0x0080
|
|
#define ATA_AHCI_CMD_RESET 0x0100
|
|
#define ATA_AHCI_CMD_BIST 0x0200
|
|
#define ATA_AHCI_CMD_CLR_BUSY 0x0400
|
|
|
|
/* 128-byte aligned */
|
|
typedef struct _IDE_AHCI_CMD_LIST {
|
|
USHORT cmd_flags;
|
|
USHORT prd_length; /* PRD entries */
|
|
ULONG bytecount;
|
|
ULONGLONG cmd_table_phys; /* points to IDE_AHCI_CMD */
|
|
ULONG Reserved[4];
|
|
} IDE_AHCI_CMD_LIST, *PIDE_AHCI_CMD_LIST;
|
|
|
|
/* 256-byte aligned */
|
|
typedef struct _IDE_AHCI_RCV_FIS {
|
|
UCHAR dsfis[28];
|
|
UCHAR Reserved1[4];
|
|
UCHAR psfis[20];
|
|
UCHAR Reserved2[12];
|
|
UCHAR rfis[20];
|
|
UCHAR Reserved3[4];
|
|
UCHAR SDBFIS[8];
|
|
UCHAR ufis[64];
|
|
UCHAR Reserved4[96];
|
|
} IDE_AHCI_RCV_FIS, *PIDE_AHCI_RCV_FIS;
|
|
|
|
/* 1K-byte aligned */
|
|
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 commands w/o associated AtaReq
|
|
} IDE_AHCI_CHANNEL_CTL_BLOCK, *PIDE_AHCI_CHANNEL_CTL_BLOCK;
|
|
|
|
#pragma pack(pop)
|
|
|
|
#define IsBusMaster(pciData) \
|
|
( ((pciData)->Command & (PCI_ENABLE_BUS_MASTER/* | PCI_ENABLE_IO_SPACE*/)) == \
|
|
(PCI_ENABLE_BUS_MASTER/* | PCI_ENABLE_IO_SPACE*/))
|
|
|
|
#define PCI_IDE_PROGIF_NATIVE_1 0x01
|
|
#define PCI_IDE_PROGIF_NATIVE_2 0x04
|
|
#define PCI_IDE_PROGIF_NATIVE_ALL 0x05
|
|
|
|
#define IsMasterDev(pciData) \
|
|
( ((pciData)->ProgIf & 0x80) && \
|
|
((pciData)->ProgIf & PCI_IDE_PROGIF_NATIVE_ALL) != PCI_IDE_PROGIF_NATIVE_ALL )
|
|
|
|
//#define INT_Q_SIZE 32
|
|
#define MIN_REQ_TTL 4
|
|
|
|
union _ATA_REQ;
|
|
|
|
typedef union _ATA_REQ {
|
|
// ULONG reqId; // serial
|
|
struct {
|
|
|
|
//union {
|
|
|
|
struct {
|
|
union _ATA_REQ* next_req;
|
|
union _ATA_REQ* prev_req;
|
|
|
|
PSCSI_REQUEST_BLOCK Srb; // Current request on controller.
|
|
|
|
PUSHORT DataBuffer; // Data buffer pointer.
|
|
ULONG WordsLeft; // Data words left.
|
|
ULONG TransferLength; // Originally requested transfer length
|
|
LONGLONG lba;
|
|
ULONG WordsTransfered;// Data words already transfered.
|
|
ULONG bcount;
|
|
|
|
UCHAR retry;
|
|
UCHAR ttl;
|
|
// UCHAR tag;
|
|
UCHAR Flags;
|
|
UCHAR ReqState;
|
|
|
|
PSCSI_REQUEST_BLOCK OriginalSrb; // Mechanism Status Srb Data
|
|
|
|
ULONG dma_entries;
|
|
union {
|
|
// for ATA
|
|
struct {
|
|
ULONG dma_base;
|
|
ULONG dma_baseu;
|
|
} ata;
|
|
// for AHCI
|
|
struct {
|
|
ULONGLONG ahci_base64;
|
|
ULONGLONG in_lba;
|
|
PIDE_AHCI_CMD ahci_cmd_ptr;
|
|
ULONG in_bcount;
|
|
ULONG in_status;
|
|
ULONG in_serror;
|
|
USHORT io_cmd_flags; // out
|
|
UCHAR in_error;
|
|
} ahci;
|
|
};
|
|
};
|
|
//UCHAR padding_128b[128]; // Note: we assume, NT allocates block > 4k as PAGE-aligned
|
|
//};
|
|
struct {
|
|
union {
|
|
BM_DMA_ENTRY dma_tab[ATA_DMA_ENTRIES];
|
|
IDE_AHCI_CMD ahci_cmd0; // for AHCI, 128-byte aligned
|
|
};
|
|
};
|
|
};
|
|
|
|
UCHAR padding_4kb[PAGE_SIZE];
|
|
|
|
} ATA_REQ, *PATA_REQ;
|
|
|
|
#define REQ_FLAG_FORCE_DOWNRATE 0x01
|
|
#define REQ_FLAG_DMA_OPERATION 0x02
|
|
#define REQ_FLAG_REORDERABLE_CMD 0x04
|
|
#define REQ_FLAG_RW_MASK 0x08
|
|
#define REQ_FLAG_READ 0x08
|
|
#define REQ_FLAG_WRITE 0x00
|
|
#define REQ_FLAG_FORCE_DOWNRATE_LBA48 0x10
|
|
#define REQ_FLAG_DMA_DBUF 0x20
|
|
#define REQ_FLAG_DMA_DBUF_PRD 0x40
|
|
#define REQ_FLAG_LBA48 0x80
|
|
|
|
// Request states
|
|
#define REQ_STATE_NONE 0x00
|
|
#define REQ_STATE_QUEUED 0x10
|
|
|
|
#define REQ_STATE_PREPARE_TO_TRANSFER 0x20
|
|
#define REQ_STATE_PREPARE_TO_NEXT 0x21
|
|
#define REQ_STATE_READY_TO_TRANSFER 0x30
|
|
|
|
#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_EXPECTING_DATA_INTR2 0x43
|
|
#define REQ_STATE_ATAPI_DO_NOTHING_INTR 0x44
|
|
|
|
#define REQ_STATE_EARLY_INTR 0x48
|
|
|
|
#define REQ_STATE_PROCESSING_INTR 0x50
|
|
|
|
#define REQ_STATE_DPC_INTR_REQ 0x51
|
|
#define REQ_STATE_DPC_RESET_REQ 0x52
|
|
#define REQ_STATE_DPC_COMPLETE_REQ 0x53
|
|
|
|
#define REQ_STATE_DPC_WAIT_BUSY0 0x57
|
|
#define REQ_STATE_DPC_WAIT_BUSY1 0x58
|
|
#define REQ_STATE_DPC_WAIT_BUSY 0x59
|
|
#define REQ_STATE_DPC_WAIT_DRQ 0x5a
|
|
#define REQ_STATE_DPC_WAIT_DRQ0 0x5b
|
|
#define REQ_STATE_DPC_WAIT_DRQ_ERR 0x5c
|
|
|
|
#define REQ_STATE_TRANSFER_COMPLETE 0x7f
|
|
|
|
// Command actions:
|
|
#define CMD_ACTION_PREPARE 0x01
|
|
#define CMD_ACTION_EXEC 0x02
|
|
#define CMD_ACTION_ALL (CMD_ACTION_PREPARE | CMD_ACTION_EXEC)
|
|
|
|
// predefined Reorder costs
|
|
#define REORDER_COST_MAX ((DEF_I64(0x1) << 60) - 1)
|
|
#define REORDER_COST_TTL (REORDER_COST_MAX - 1)
|
|
#define REORDER_COST_INTERSECT (REORDER_COST_MAX - 2)
|
|
#define REORDER_COST_DENIED (REORDER_COST_MAX - 3)
|
|
#define REORDER_COST_RESELECT (REORDER_COST_MAX/4)
|
|
|
|
#define REORDER_COST_SWITCH_RW_CD (REORDER_COST_MAX/8)
|
|
#define REORDER_MCOST_SWITCH_RW_CD (0)
|
|
#define REORDER_MCOST_SEEK_BACK_CD (16)
|
|
|
|
#define REORDER_COST_SWITCH_RW_HDD (0)
|
|
#define REORDER_MCOST_SWITCH_RW_HDD (4)
|
|
#define REORDER_MCOST_SEEK_BACK_HDD (2)
|
|
|
|
/*typedef struct _ATA_QUEUE {
|
|
struct _ATA_REQ* head_req; // index
|
|
struct _ATA_REQ* tail_req; // index
|
|
ULONG req_count;
|
|
ULONG dma_base;
|
|
BM_DMA_ENTRY dma_tab[ATA_DMA_ENTRIES];
|
|
} ATA_QUEUE, *PATA_QUEUE;*/
|
|
|
|
struct _HW_DEVICE_EXTENSION;
|
|
struct _HW_LU_EXTENSION;
|
|
|
|
typedef struct _IORES {
|
|
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 processing via IO_Proc */
|
|
ULONG Reserved:30;
|
|
} IORES, *PIORES;
|
|
|
|
// Channel extension
|
|
typedef struct _HW_CHANNEL {
|
|
|
|
PATA_REQ cur_req;
|
|
ULONG cur_cdev;
|
|
ULONG last_cdev; /* device for which we have configured timings last time */
|
|
ULONG last_devsel; /* device selected during last call to SelectDrive() */
|
|
/* PATA_REQ first_req;
|
|
PATA_REQ last_req;*/
|
|
ULONG queue_depth;
|
|
ULONG ChannelSelectWaitCount;
|
|
|
|
UCHAR DpcState;
|
|
|
|
BOOLEAN ExpectingInterrupt; // Indicates expecting an interrupt
|
|
BOOLEAN RDP; // Indicate last tape command was DSC Restrictive.
|
|
// Indicates whether '0x1f0' is the base address. Used
|
|
// in SMART Ioctl calls.
|
|
BOOLEAN PrimaryAddress;
|
|
// Placeholder for the sub-command value of the last
|
|
// SMART command.
|
|
UCHAR SmartCommand;
|
|
// Reorder anabled
|
|
BOOLEAN UseReorder;
|
|
// Placeholder for status register after a GET_MEDIA_STATUS command
|
|
UCHAR ReturningMediaStatus;
|
|
|
|
BOOLEAN CopyDmaBuffer;
|
|
//BOOLEAN MemIo;
|
|
BOOLEAN AltRegMap;
|
|
BOOLEAN Force80pin;
|
|
|
|
UCHAR Reserved[2];
|
|
|
|
MECHANICAL_STATUS_INFORMATION_HEADER MechStatusData;
|
|
SENSE_DATA MechStatusSense;
|
|
ULONG MechStatusRetryCount;
|
|
SCSI_REQUEST_BLOCK InternalSrb;
|
|
|
|
ULONG MaxTransferMode; // may differ from Controller's value due to 40-pin cable
|
|
|
|
ULONG ChannelCtrlFlags;
|
|
ULONG ResetInProgress; // flag
|
|
LONG DisableIntr;
|
|
LONG CheckIntr;
|
|
|
|
ULONG lChannel;
|
|
|
|
#define CHECK_INTR_ACTIVE 0x03
|
|
#define CHECK_INTR_DETECTED 0x02
|
|
#define CHECK_INTR_CHECK 0x01
|
|
#define CHECK_INTR_IDLE 0x00
|
|
|
|
ULONG NextDpcChan;
|
|
PHW_TIMER HwScsiTimer;
|
|
LONGLONG DpcTime;
|
|
#if 0
|
|
PHW_TIMER HwScsiTimer1;
|
|
PHW_TIMER HwScsiTimer2;
|
|
LONGLONG DpcTime1;
|
|
// PHW_TIMER CurDpc;
|
|
// LARGE_INTEGER ActivationTime;
|
|
|
|
// KDPC Dpc;
|
|
// KTIMER Timer;
|
|
// PHW_TIMER HwScsiTimer;
|
|
// KSPIN_LOCK QueueSpinLock;
|
|
// KIRQL QueueOldIrql;
|
|
#endif
|
|
struct _HW_DEVICE_EXTENSION* DeviceExtension;
|
|
struct _HW_LU_EXTENSION* lun[IDE_MAX_LUN_PER_CHAN];
|
|
|
|
ULONG NumberLuns;
|
|
ULONG PmLunMap;
|
|
|
|
// Double-buffering support
|
|
PVOID DB_PRD;
|
|
ULONG DB_PRD_PhAddr;
|
|
PVOID DB_IO;
|
|
ULONG DB_IO_PhAddr;
|
|
|
|
PUCHAR DmaBuffer;
|
|
|
|
//
|
|
PIDE_AHCI_CHANNEL_CTL_BLOCK AhciCtlBlock0; // unaligned
|
|
PIDE_AHCI_CHANNEL_CTL_BLOCK AhciCtlBlock; // 128-byte aligned
|
|
ULONGLONG AHCI_CTL_PhAddr;
|
|
IORES BaseIoAHCI_Port;
|
|
ULONG AhciPrevCI;
|
|
ULONG AhciCompleteCI;
|
|
ULONG AhciLastIS;
|
|
ULONG AhciLastSError;
|
|
//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];
|
|
LONGLONG ReorderCount;
|
|
LONGLONG IntersectCount;
|
|
LONGLONG TryReorderCount;
|
|
LONGLONG TryReorderHeadCount;
|
|
LONGLONG TryReorderTailCount; /* in-order requests */
|
|
#endif //QUEUE_STATISTICS
|
|
|
|
//ULONG BaseMemAddress;
|
|
//ULONG BaseMemAddressOffset;
|
|
IORES RegTranslation[IDX_MAX_REG];
|
|
|
|
} HW_CHANNEL, *PHW_CHANNEL;
|
|
|
|
#define CTRFLAGS_DMA_ACTIVE 0x0001
|
|
#define CTRFLAGS_DMA_RO 0x0002
|
|
#define CTRFLAGS_DMA_OPERATION 0x0004
|
|
#define CTRFLAGS_INTR_DISABLED 0x0008
|
|
#define CTRFLAGS_DPC_REQ 0x0010
|
|
#define CTRFLAGS_ENABLE_INTR_REQ 0x0020
|
|
#define CTRFLAGS_LBA48 0x0040
|
|
#define CTRFLAGS_DSC_BSY 0x0080
|
|
#define CTRFLAGS_NO_SLAVE 0x0100
|
|
//#define CTRFLAGS_DMA_BEFORE_R 0x0200
|
|
//#define CTRFLAGS_PATA 0x0200
|
|
//#define CTRFLAGS_NOT_PRESENT 0x0200
|
|
#define CTRFLAGS_AHCI_PM 0x0400
|
|
#define CTRFLAGS_AHCI_PM2 0x0800
|
|
|
|
#define CTRFLAGS_PERMANENT (CTRFLAGS_DMA_RO | CTRFLAGS_NO_SLAVE)
|
|
|
|
#define GEOM_AUTO 0xffffffff
|
|
#define GEOM_STD 0x0000
|
|
#define GEOM_UNIATA 0x0001
|
|
#define GEOM_ORIG 0x0002
|
|
#define GEOM_MANUAL 0x0003
|
|
|
|
#define DPC_STATE_NONE 0x00
|
|
#define DPC_STATE_ISR 0x10
|
|
#define DPC_STATE_DPC 0x20
|
|
#define DPC_STATE_TIMER 0x30
|
|
#define DPC_STATE_COMPLETE 0x40
|
|
|
|
// Logical unit extension
|
|
typedef struct _HW_LU_EXTENSION {
|
|
IDENTIFY_DATA2 IdentifyData;
|
|
ULONGLONG NumOfSectors;
|
|
ULONG DeviceFlags; // Flags word for each possible device. DFLAGS_XXX
|
|
ULONG DiscsPresent; // Indicates number of platters on changer-ish devices.
|
|
BOOLEAN DWordIO; // Indicates use of 32-bit PIO
|
|
UCHAR ReturningMediaStatus;
|
|
UCHAR MaximumBlockXfer;
|
|
UCHAR PowerState;
|
|
|
|
UCHAR TransferMode; // current transfer mode
|
|
UCHAR LimitedTransferMode; // user-defined or IDE cable limitation
|
|
UCHAR OrigTransferMode; // transfer mode, returned by device IDENTIFY (can be changed via IOCTL)
|
|
UCHAR PhyTransferMode; // phy transfer mode (actual bus transfer mode for PATA DMA and SATA)
|
|
|
|
ULONG ErrorCount; // Count of errors. Used to turn off features.
|
|
// ATA_QUEUE cmd_queue;
|
|
LONGLONG ReadCmdCost;
|
|
LONGLONG WriteCmdCost;
|
|
LONGLONG OtherCmdCost;
|
|
LONGLONG RwSwitchCost;
|
|
LONGLONG RwSwitchMCost;
|
|
LONGLONG SeekBackMCost;
|
|
//
|
|
PATA_REQ first_req;
|
|
PATA_REQ last_req;
|
|
ULONG queue_depth;
|
|
ULONG last_write;
|
|
|
|
ULONG LunSelectWaitCount;
|
|
ULONG AtapiReadyWaitDelay;
|
|
|
|
// tuning options
|
|
ULONG opt_GeomType;
|
|
ULONG opt_MaxTransferMode;
|
|
ULONG opt_PreferedTransferMode;
|
|
BOOLEAN opt_ReadCacheEnable;
|
|
BOOLEAN opt_WriteCacheEnable;
|
|
UCHAR opt_ReadOnly;
|
|
UCHAR opt_AdvPowerMode;
|
|
UCHAR opt_AcousticMode;
|
|
UCHAR opt_StandbyTimer;
|
|
UCHAR opt_Padding[2]; // padding
|
|
|
|
struct _SBadBlockListItem* bbListDescr;
|
|
struct _SBadBlockRange* arrBadBlocks;
|
|
ULONG nBadBlocks;
|
|
|
|
// Controller-specific LUN options
|
|
union {
|
|
/* for tricky controllers, those can change Logical-to-Physical LUN mapping.
|
|
mainly for mapping SATA ports to compatible PATA registers
|
|
Treated as PHYSICAL port number, regardless of logical mapping.
|
|
*/
|
|
ULONG SATA_lun_map;
|
|
};
|
|
|
|
struct _HW_DEVICE_EXTENSION* DeviceExtension;
|
|
struct _HW_CHANNEL* chan;
|
|
ULONG Lun;
|
|
|
|
ULONGLONG errLastLba;
|
|
ULONG errBCount;
|
|
UCHAR errRetry;
|
|
UCHAR errPadding[3];
|
|
|
|
#ifdef IO_STATISTICS
|
|
|
|
LONGLONG ModeErrorCount[MAX_RETRIES];
|
|
LONGLONG RecoverCount[MAX_RETRIES];
|
|
LONGLONG IoCount;
|
|
LONGLONG BlockIoCount;
|
|
|
|
#endif//IO_STATISTICS
|
|
} HW_LU_EXTENSION, *PHW_LU_EXTENSION;
|
|
|
|
// Device extension
|
|
typedef struct _HW_DEVICE_EXTENSION {
|
|
CHAR Signature[32];
|
|
//PIDE_REGISTERS_1 BaseIoAddress1[IDE_MAX_CHAN]; // Base register locations
|
|
//PIDE_REGISTERS_2 BaseIoAddress2[IDE_MAX_CHAN];
|
|
ULONG BusInterruptLevel; // Interrupt level
|
|
ULONG InterruptMode; // Interrupt Mode (Level or Edge)
|
|
ULONG BusInterruptVector;
|
|
// Number of channels being supported by one instantiation
|
|
// of the device extension. Normally (and correctly) one, but
|
|
// with so many broken PCI IDE controllers being sold, we have
|
|
// to support them.
|
|
ULONG NumberChannels;
|
|
ULONG NumberLuns;
|
|
ULONG FirstChannelToCheck;
|
|
#if 0
|
|
HW_LU_EXTENSION lun[IDE_MAX_LUN];
|
|
HW_CHANNEL chan[AHCI_MAX_PORT/*IDE_MAX_CHAN*/];
|
|
#else
|
|
PHW_LU_EXTENSION lun; // lun array
|
|
PHW_CHANNEL chan; // channel array
|
|
#endif
|
|
UCHAR LastInterruptedChannel;
|
|
// Indicates the number of blocks transferred per int. according to the
|
|
// identify data.
|
|
BOOLEAN DriverMustPoll; // Driver is being used by the crash dump utility or ntldr.
|
|
BOOLEAN BusMaster;
|
|
BOOLEAN UseDpc; // Indicates use of DPC on long waits
|
|
IDENTIFY_DATA FullIdentifyData; // Identify data for device
|
|
// BusMaster specific data
|
|
// PBM_DMA_ENTRY dma_tab_0;
|
|
//KSPIN_LOCK DpcSpinLock;
|
|
|
|
ULONG ActiveDpcChan;
|
|
ULONG FirstDpcChan;
|
|
ULONG ExpectingInterrupt; // Indicates entire controller expecting an interrupt
|
|
/*
|
|
PHW_TIMER HwScsiTimer1;
|
|
PHW_TIMER HwScsiTimer2;
|
|
LONGLONG DpcTime1;
|
|
LONGLONG DpcTime2;
|
|
*/
|
|
ULONG queue_depth;
|
|
|
|
PDEVICE_OBJECT Isr2DevObj;
|
|
|
|
//PIDE_BUSMASTER_REGISTERS BaseIoAddressBM_0;
|
|
IORES BaseIoAddressBM_0;
|
|
//PIDE_BUSMASTER_REGISTERS BaseIoAddressBM[IDE_MAX_CHAN];
|
|
|
|
// Device identification
|
|
ULONG DevID;
|
|
ULONG RevID;
|
|
ULONG slotNumber;
|
|
ULONG SystemIoBusNumber;
|
|
ULONG DevIndex;
|
|
|
|
ULONG InitMethod; // vendor specific
|
|
|
|
ULONG Channel;
|
|
|
|
ULONG HbaCtrlFlags;
|
|
BOOLEAN simplexOnly;
|
|
//BOOLEAN MemIo;
|
|
BOOLEAN AltRegMap;
|
|
BOOLEAN UnknownDev;
|
|
BOOLEAN MasterDev;
|
|
BOOLEAN Host64;
|
|
BOOLEAN DWordIO; // Indicates use of 32-bit PIO
|
|
/* // Indicates, that HW Initialized is already called for this controller
|
|
// 0 bit for Primary, 1 - for Secondary. Is used to manage AltInit under w2k+
|
|
UCHAR Initialized; */
|
|
UCHAR Reserved1[2];
|
|
|
|
LONG ReCheckIntr;
|
|
|
|
ULONG MaxTransferMode; // max transfer mode supported by controller
|
|
ULONG HwFlags;
|
|
INTERFACE_TYPE OrigAdapterInterfaceType;
|
|
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;
|
|
//PIDE_SATA_REGISTERS BaseIoAddressSATA[IDE_MAX_CHAN];
|
|
|
|
IORES BaseIoAHCI_0;
|
|
//PIDE_AHCI_PORT_REGISTERS BaseIoAHCIPort[AHCI_MAX_PORT];
|
|
ULONG AHCI_CAP;
|
|
ULONG AHCI_PI;
|
|
ULONG AHCI_PI_mask; // for port exclusion, usually = AHCI_PI
|
|
PATA_REQ AhciInternalAtaReq0;
|
|
PSCSI_REQUEST_BLOCK AhciInternalSrb0;
|
|
|
|
BOOLEAN opt_AtapiDmaZeroTransfer; // default FALSE
|
|
BOOLEAN opt_AtapiDmaControlCmd; // default FALSE
|
|
BOOLEAN opt_AtapiDmaRawRead; // default TRUE
|
|
BOOLEAN opt_AtapiDmaReadWrite; // default TRUE
|
|
|
|
PCCH FullDevName;
|
|
|
|
// Controller specific state/options
|
|
union {
|
|
ULONG HwCfg;
|
|
};
|
|
|
|
} HW_DEVICE_EXTENSION, *PHW_DEVICE_EXTENSION;
|
|
|
|
typedef struct _ISR2_DEVICE_EXTENSION {
|
|
PHW_DEVICE_EXTENSION HwDeviceExtension;
|
|
ULONG DevIndex;
|
|
} ISR2_DEVICE_EXTENSION, *PISR2_DEVICE_EXTENSION;
|
|
|
|
typedef ISR2_DEVICE_EXTENSION PCIIDE_DEVICE_EXTENSION;
|
|
typedef PISR2_DEVICE_EXTENSION PPCIIDE_DEVICE_EXTENSION;
|
|
|
|
#define HBAFLAGS_DMA_DISABLED 0x01
|
|
#define HBAFLAGS_DMA_DISABLED_LBA48 0x02
|
|
|
|
extern UCHAR pciBuffer[256];
|
|
extern PBUSMASTER_CONTROLLER_INFORMATION BMList;
|
|
extern ULONG BMListLen;
|
|
extern ULONG IsaCount;
|
|
extern ULONG MCACount;
|
|
extern UNICODE_STRING SavedRegPath;
|
|
|
|
//extern const CHAR retry_Wdma[MAX_RETRIES+1];
|
|
//extern const CHAR retry_Udma[MAX_RETRIES+1];
|
|
|
|
extern VOID
|
|
NTAPI
|
|
UniataEnumBusMasterController(
|
|
IN PVOID DriverObject,
|
|
PVOID Argument2
|
|
);
|
|
|
|
extern ULONG NTAPI
|
|
UniataFindCompatBusMasterController1(
|
|
IN PVOID HwDeviceExtension,
|
|
IN PVOID Context,
|
|
IN PVOID BusInformation,
|
|
IN PCHAR ArgumentString,
|
|
IN OUT PPORT_CONFIGURATION_INFORMATION ConfigInfo,
|
|
OUT PBOOLEAN Again
|
|
);
|
|
|
|
extern ULONG NTAPI
|
|
UniataFindCompatBusMasterController2(
|
|
IN PVOID HwDeviceExtension,
|
|
IN PVOID Context,
|
|
IN PVOID BusInformation,
|
|
IN PCHAR ArgumentString,
|
|
IN OUT PPORT_CONFIGURATION_INFORMATION ConfigInfo,
|
|
OUT PBOOLEAN Again
|
|
);
|
|
|
|
#define UNIATA_ALLOCATE_NEW_LUNS 0x00
|
|
|
|
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,
|
|
IN PVOID Context,
|
|
IN PVOID BusInformation,
|
|
IN PCHAR ArgumentString,
|
|
IN OUT PPORT_CONFIGURATION_INFORMATION ConfigInfo,
|
|
OUT PBOOLEAN Again
|
|
);
|
|
|
|
extern NTSTATUS
|
|
NTAPI
|
|
UniataClaimLegacyPCIIDE(
|
|
ULONG i
|
|
);
|
|
|
|
extern NTSTATUS
|
|
NTAPI
|
|
UniataConnectIntr2(
|
|
IN PVOID HwDeviceExtension
|
|
);
|
|
|
|
extern NTSTATUS
|
|
NTAPI
|
|
UniataDisconnectIntr2(
|
|
IN PVOID HwDeviceExtension
|
|
);
|
|
|
|
extern ULONG
|
|
NTAPI
|
|
ScsiPortGetBusDataByOffset(
|
|
IN PVOID HwDeviceExtension,
|
|
IN BUS_DATA_TYPE BusDataType,
|
|
IN ULONG BusNumber,
|
|
IN ULONG SlotNumber,
|
|
IN PVOID Buffer,
|
|
IN ULONG Offset,
|
|
IN ULONG Length
|
|
);
|
|
|
|
#define PCIBUSNUM_NOT_SPECIFIED (0xffffffffL)
|
|
#define PCISLOTNUM_NOT_SPECIFIED (0xffffffffL)
|
|
|
|
extern ULONG
|
|
NTAPI
|
|
AtapiFindListedDev(
|
|
PBUSMASTER_CONTROLLER_INFORMATION_BASE BusMasterAdapters,
|
|
ULONG lim,
|
|
IN PVOID HwDeviceExtension,
|
|
IN ULONG BusNumber,
|
|
IN ULONG SlotNumber,
|
|
OUT PCI_SLOT_NUMBER* _slotData // optional
|
|
);
|
|
|
|
extern ULONG
|
|
NTAPI
|
|
AtapiFindDev(
|
|
IN PVOID HwDeviceExtension,
|
|
IN BUS_DATA_TYPE BusDataType,
|
|
IN ULONG BusNumber,
|
|
IN ULONG SlotNumber,
|
|
IN ULONG dev_id,
|
|
IN ULONG RevID
|
|
);
|
|
|
|
extern VOID
|
|
NTAPI
|
|
AtapiDmaAlloc(
|
|
IN PVOID HwDeviceExtension,
|
|
IN PPORT_CONFIGURATION_INFORMATION ConfigInfo,
|
|
IN ULONG lChannel // logical channel,
|
|
);
|
|
|
|
extern BOOLEAN
|
|
NTAPI
|
|
AtapiDmaSetup(
|
|
IN PVOID HwDeviceExtension,
|
|
IN ULONG DeviceNumber,
|
|
IN ULONG lChannel, // logical channel,
|
|
IN PSCSI_REQUEST_BLOCK Srb,
|
|
IN PUCHAR data,
|
|
IN ULONG count
|
|
);
|
|
|
|
extern BOOLEAN
|
|
NTAPI
|
|
AtapiDmaPioSync(
|
|
PVOID HwDeviceExtension,
|
|
PSCSI_REQUEST_BLOCK Srb,
|
|
PUCHAR data,
|
|
ULONG count
|
|
);
|
|
|
|
extern BOOLEAN
|
|
NTAPI
|
|
AtapiDmaDBSync(
|
|
PHW_CHANNEL chan,
|
|
PSCSI_REQUEST_BLOCK Srb
|
|
);
|
|
|
|
extern BOOLEAN
|
|
NTAPI
|
|
AtapiDmaDBPreSync(
|
|
IN PVOID HwDeviceExtension,
|
|
PHW_CHANNEL chan,
|
|
PSCSI_REQUEST_BLOCK Srb
|
|
);
|
|
|
|
extern VOID
|
|
NTAPI
|
|
AtapiDmaStart(
|
|
IN PVOID HwDeviceExtension,
|
|
IN ULONG DeviceNumber,
|
|
IN ULONG lChannel, // logical channel,
|
|
IN PSCSI_REQUEST_BLOCK Srb
|
|
);
|
|
|
|
extern UCHAR
|
|
NTAPI
|
|
AtapiDmaDone(
|
|
IN PVOID HwDeviceExtension,
|
|
IN ULONG DeviceNumber,
|
|
IN ULONG lChannel, // logical channel,
|
|
IN PSCSI_REQUEST_BLOCK Srb
|
|
);
|
|
|
|
extern VOID
|
|
NTAPI
|
|
AtapiDmaReinit(
|
|
IN PHW_DEVICE_EXTENSION deviceExtension,
|
|
IN PHW_LU_EXTENSION LunExt,
|
|
IN PATA_REQ AtaReq
|
|
);
|
|
|
|
extern VOID
|
|
NTAPI
|
|
AtapiDmaInit__(
|
|
IN PHW_DEVICE_EXTENSION deviceExtension,
|
|
IN PHW_LU_EXTENSION LunExt
|
|
);
|
|
|
|
extern VOID
|
|
NTAPI
|
|
AtapiDmaInit(
|
|
IN PVOID HwDeviceExtension,
|
|
IN ULONG DeviceNumber,
|
|
IN ULONG lChannel, // logical channel,
|
|
// is always 0 except simplex-only and multi-channel controllers
|
|
IN SCHAR apiomode,
|
|
IN SCHAR wdmamode,
|
|
IN SCHAR udmamode
|
|
);
|
|
|
|
extern BOOLEAN NTAPI
|
|
AtapiInterrupt2(
|
|
IN PKINTERRUPT Interrupt,
|
|
IN PVOID HwDeviceExtension
|
|
);
|
|
|
|
extern PDRIVER_OBJECT SavedDriverObject;
|
|
|
|
extern BOOLEAN
|
|
NTAPI
|
|
UniataChipDetectChannels(
|
|
IN PVOID HwDeviceExtension,
|
|
IN PPCI_COMMON_CONFIG pciData, // optional
|
|
IN ULONG DeviceNumber,
|
|
IN PPORT_CONFIGURATION_INFORMATION ConfigInfo
|
|
);
|
|
|
|
extern NTSTATUS
|
|
NTAPI
|
|
UniataChipDetect(
|
|
IN PVOID HwDeviceExtension,
|
|
IN PPCI_COMMON_CONFIG pciData, // optional
|
|
IN ULONG DeviceNumber,
|
|
IN OUT PPORT_CONFIGURATION_INFORMATION ConfigInfo,
|
|
IN BOOLEAN* simplexOnly
|
|
);
|
|
|
|
extern BOOLEAN
|
|
NTAPI
|
|
AtapiChipInit(
|
|
IN PVOID HwDeviceExtension,
|
|
IN ULONG DeviceNumber,
|
|
IN ULONG c
|
|
);
|
|
|
|
extern ULONGIO_PTR
|
|
NTAPI
|
|
AtapiGetIoRange(
|
|
IN PVOID HwDeviceExtension,
|
|
IN PPORT_CONFIGURATION_INFORMATION ConfigInfo,
|
|
IN PPCI_COMMON_CONFIG pciData,
|
|
IN ULONG SystemIoBusNumber,
|
|
IN ULONG rid,
|
|
IN ULONG offset,
|
|
IN ULONG length //range id
|
|
);
|
|
|
|
extern USHORT
|
|
NTAPI
|
|
UniataEnableIoPCI(
|
|
IN ULONG busNumber,
|
|
IN ULONG slotNumber,
|
|
IN OUT PPCI_COMMON_CONFIG pciData
|
|
);
|
|
|
|
/****************** 1 *****************/
|
|
#define GetPciConfig1(offs, op) { \
|
|
ScsiPortGetBusDataByOffset(HwDeviceExtension, \
|
|
PCIConfiguration, \
|
|
SystemIoBusNumber, \
|
|
slotNumber, \
|
|
&op, \
|
|
offs, \
|
|
1); \
|
|
}
|
|
|
|
#define SetPciConfig1(offs, op) { \
|
|
UCHAR _a = op; \
|
|
ScsiPortSetBusDataByOffset(HwDeviceExtension, \
|
|
PCIConfiguration, \
|
|
SystemIoBusNumber, \
|
|
slotNumber, \
|
|
&_a, \
|
|
offs, \
|
|
1); \
|
|
}
|
|
|
|
#define ChangePciConfig1(offs, _op) { \
|
|
UCHAR a = 0; \
|
|
GetPciConfig1(offs, a); \
|
|
a = (UCHAR)(_op); \
|
|
SetPciConfig1(offs, a); \
|
|
}
|
|
|
|
/****************** 2 *****************/
|
|
#define GetPciConfig2(offs, op) { \
|
|
ScsiPortGetBusDataByOffset(HwDeviceExtension, \
|
|
PCIConfiguration, \
|
|
SystemIoBusNumber, \
|
|
slotNumber, \
|
|
&op, \
|
|
offs, \
|
|
2); \
|
|
}
|
|
|
|
#define SetPciConfig2(offs, op) { \
|
|
USHORT _a = op; \
|
|
ScsiPortSetBusDataByOffset(HwDeviceExtension, \
|
|
PCIConfiguration, \
|
|
SystemIoBusNumber, \
|
|
slotNumber, \
|
|
&_a, \
|
|
offs, \
|
|
2); \
|
|
}
|
|
|
|
#define ChangePciConfig2(offs, _op) { \
|
|
USHORT a = 0; \
|
|
GetPciConfig2(offs, a); \
|
|
a = (USHORT)(_op); \
|
|
SetPciConfig2(offs, a); \
|
|
}
|
|
|
|
/****************** 4 *****************/
|
|
#define GetPciConfig4(offs, op) { \
|
|
ScsiPortGetBusDataByOffset(HwDeviceExtension, \
|
|
PCIConfiguration, \
|
|
SystemIoBusNumber, \
|
|
slotNumber, \
|
|
&op, \
|
|
offs, \
|
|
4); \
|
|
}
|
|
|
|
#define SetPciConfig4(offs, op) { \
|
|
ULONG _a = op; \
|
|
ScsiPortSetBusDataByOffset(HwDeviceExtension, \
|
|
PCIConfiguration, \
|
|
SystemIoBusNumber, \
|
|
slotNumber, \
|
|
&_a, \
|
|
offs, \
|
|
4); \
|
|
}
|
|
|
|
#define ChangePciConfig4(offs, _op) { \
|
|
ULONG a = 0; \
|
|
GetPciConfig4(offs, a); \
|
|
a = _op; \
|
|
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 == DMA_MODE_BM) ? AtapiReadPort1(&((de)->chan[c]), IDX_BM_Status) : 0)
|
|
#endif //GetDmaStatus
|
|
|
|
#ifdef USE_OWN_DMA
|
|
#define AtapiVirtToPhysAddr(hwde, srb, phaddr, plen, phaddru) \
|
|
AtapiVirtToPhysAddr_(hwde, srb, phaddr, plen, phaddru);
|
|
#else
|
|
#define AtapiVirtToPhysAddr(hwde, srb, phaddr, plen, phaddru) \
|
|
(ScsiPortConvertPhysicalAddressToUlong/*(ULONG)ScsiPortGetVirtualAddress*/(/*hwde,*/ \
|
|
ScsiPortGetPhysicalAddress(hwde, srb, phaddr, plen)))
|
|
#endif //USE_OWN_DMA
|
|
|
|
VOID
|
|
DDKFASTAPI
|
|
AtapiWritePort4(
|
|
IN PHW_CHANNEL chan,
|
|
IN ULONGIO_PTR port,
|
|
IN ULONG data
|
|
);
|
|
|
|
VOID
|
|
DDKFASTAPI
|
|
AtapiWritePort2(
|
|
IN PHW_CHANNEL chan,
|
|
IN ULONGIO_PTR port,
|
|
IN USHORT data
|
|
);
|
|
|
|
VOID
|
|
DDKFASTAPI
|
|
AtapiWritePort1(
|
|
IN PHW_CHANNEL chan,
|
|
IN ULONGIO_PTR port,
|
|
IN UCHAR data
|
|
);
|
|
|
|
VOID
|
|
DDKFASTAPI
|
|
AtapiWritePortEx4(
|
|
IN PHW_CHANNEL chan,
|
|
IN ULONGIO_PTR port,
|
|
IN ULONG offs,
|
|
IN ULONG data
|
|
);
|
|
|
|
VOID
|
|
DDKFASTAPI
|
|
AtapiWritePortEx1(
|
|
IN PHW_CHANNEL chan,
|
|
IN ULONGIO_PTR port,
|
|
IN ULONG offs,
|
|
IN UCHAR data
|
|
);
|
|
|
|
ULONG
|
|
DDKFASTAPI
|
|
AtapiReadPort4(
|
|
IN PHW_CHANNEL chan,
|
|
IN ULONGIO_PTR port
|
|
);
|
|
|
|
USHORT
|
|
DDKFASTAPI
|
|
AtapiReadPort2(
|
|
IN PHW_CHANNEL chan,
|
|
IN ULONGIO_PTR port
|
|
);
|
|
|
|
UCHAR
|
|
DDKFASTAPI
|
|
AtapiReadPort1(
|
|
IN PHW_CHANNEL chan,
|
|
IN ULONGIO_PTR port
|
|
);
|
|
|
|
ULONG
|
|
DDKFASTAPI
|
|
AtapiReadPortEx4(
|
|
IN PHW_CHANNEL chan,
|
|
IN ULONGIO_PTR port,
|
|
IN ULONG offs
|
|
);
|
|
|
|
UCHAR
|
|
DDKFASTAPI
|
|
AtapiReadPortEx1(
|
|
IN PHW_CHANNEL chan,
|
|
IN ULONGIO_PTR port,
|
|
IN ULONG offs
|
|
);
|
|
|
|
VOID
|
|
DDKFASTAPI
|
|
AtapiWriteBuffer4(
|
|
IN PHW_CHANNEL chan,
|
|
IN ULONGIO_PTR _port,
|
|
IN PVOID Buffer,
|
|
IN ULONG Count,
|
|
IN ULONG Timing
|
|
);
|
|
|
|
VOID
|
|
DDKFASTAPI
|
|
AtapiWriteBuffer2(
|
|
IN PHW_CHANNEL chan,
|
|
IN ULONGIO_PTR _port,
|
|
IN PVOID Buffer,
|
|
IN ULONG Count,
|
|
IN ULONG Timing
|
|
);
|
|
|
|
VOID
|
|
DDKFASTAPI
|
|
AtapiReadBuffer4(
|
|
IN PHW_CHANNEL chan,
|
|
IN ULONGIO_PTR _port,
|
|
IN PVOID Buffer,
|
|
IN ULONG Count,
|
|
IN ULONG Timing
|
|
);
|
|
|
|
VOID
|
|
DDKFASTAPI
|
|
AtapiReadBuffer2(
|
|
IN PHW_CHANNEL chan,
|
|
IN ULONGIO_PTR _port,
|
|
IN PVOID Buffer,
|
|
IN ULONG Count,
|
|
IN ULONG Timing
|
|
);
|
|
|
|
/*#define GET_CHANNEL(Srb) (Srb->TargetId >> 1)
|
|
#define GET_LDEV(Srb) (Srb->TargetId)
|
|
#define GET_LDEV2(P, T, L) (T)*/
|
|
|
|
#define GET_CHANNEL(Srb) (Srb->PathId)
|
|
//#define GET_LDEV(Srb) (Srb->TargetId | (Srb->PathId << 1))
|
|
//#define GET_LDEV2(P, T, L) (T | ((P)<<1))
|
|
#define GET_CDEV(Srb) (Srb->TargetId)
|
|
|
|
VOID
|
|
NTAPI
|
|
AtapiSetupLunPtrs(
|
|
IN PHW_CHANNEL chan,
|
|
IN PHW_DEVICE_EXTENSION deviceExtension,
|
|
IN ULONG c
|
|
);
|
|
/*
|
|
#define AtapiSetupLunPtrs(chan, deviceExtension, c) \
|
|
{ \
|
|
chan->DeviceExtension = deviceExtension; \
|
|
chan->lChannel = c; \
|
|
chan->lun[0] = &(deviceExtension->lun[c*2+0]); \
|
|
chan->lun[1] = &(deviceExtension->lun[c*2+1]); \
|
|
chan->AltRegMap = deviceExtension->AltRegMap; \
|
|
chan->NextDpcChan = -1; \
|
|
chan->lun[0]->DeviceExtension = deviceExtension; \
|
|
chan->lun[1]->DeviceExtension = deviceExtension; \
|
|
}
|
|
*/
|
|
BOOLEAN
|
|
NTAPI
|
|
AtapiReadChipConfig(
|
|
IN PVOID HwDeviceExtension,
|
|
IN ULONG DeviceNumber,
|
|
IN ULONG channel // physical channel
|
|
);
|
|
|
|
VOID
|
|
NTAPI
|
|
UniataForgetDevice(
|
|
PHW_LU_EXTENSION LunExt
|
|
);
|
|
|
|
extern ULONG SkipRaids;
|
|
extern ULONG ForceSimplex;
|
|
extern BOOLEAN g_opt_AtapiDmaRawRead;
|
|
extern BOOLEAN hasPCI;
|
|
|
|
extern BOOLEAN InDriverEntry;
|
|
extern BOOLEAN g_Dump;
|
|
|
|
extern BOOLEAN g_opt_Verbose;
|
|
extern ULONG g_opt_VirtualMachine;
|
|
|
|
extern ULONG g_opt_WaitBusyResetCount;
|
|
|
|
extern ULONG CPU_num;
|
|
|
|
#define VM_AUTO 0x00
|
|
#define VM_NONE 0x01
|
|
#define VM_VBOX 0x02
|
|
#define VM_VMWARE 0x03
|
|
#define VM_QEMU 0x04
|
|
#define VM_BOCHS 0x05
|
|
#define VM_PCEM 0x06
|
|
|
|
#define VM_MAX_KNOWN VM_PCEM
|
|
|
|
extern BOOLEAN WinVer_WDM_Model;
|
|
|
|
#pragma pack(pop)
|
|
|
|
#endif //__IDE_BUSMASTER_H__
|