#ifndef _DEV_ATA_ATASCSI_H_
#define _DEV_ATA_ATASCSI_H_
#include <sys/task.h>
struct atascsi;
struct scsi_link;
#define ATA_C_READDMA_EXT 0x25
#define ATA_C_READ_LOG_EXT 0x2f
#define ATA_C_WRITEDMA_EXT 0x35
#define ATA_C_READ_FPDMA 0x60
#define ATA_C_WRITE_FPDMA 0x61
#define ATA_C_PACKET 0xa0
#define ATA_C_IDENTIFY_PACKET 0xa1
#define ATA_C_READDMA 0xc8
#define ATA_C_WRITEDMA 0xca
#define ATA_C_STANDBY_IMMED 0xe0
#define ATA_C_READ_PM 0xe4
#define ATA_C_WRITE_PM 0xe8
#define ATA_C_FLUSH_CACHE 0xe7
#define ATA_C_FLUSH_CACHE_EXT 0xea
#define ATA_C_IDENTIFY 0xec
#define ATA_C_SET_FEATURES 0xef
#define ATA_C_SEC_FREEZE_LOCK 0xf5
#define ATA_C_DSM 0x06
#define ATA_SF_WRITECACHE_EN 0x02
#define ATA_SF_XFERMODE 0x03
#define ATA_SF_SATA_FEATURE_EN 0x10
#define ATA_SF_XFERMODE_UDMA 0x40
#define ATA_SF_SATA_FEATURE_DIS 0x90
#define ATA_SF_LOOKAHEAD_EN 0xaa
#define ATA_SF_SATA_DEVIPS 0x03
#define ATA_SF_SATA_DEVAPS 0x07
#define ATA_SF_SATA_DEVSLEEP 0x09
struct ata_identify {
u_int16_t config;
u_int16_t ncyls;
u_int16_t reserved1;
u_int16_t nheads;
u_int16_t track_size;
u_int16_t sector_size;
u_int16_t nsectors;
u_int16_t reserved2[3];
u_int8_t serial[20];
u_int16_t buffer_type;
u_int16_t buffer_size;
u_int16_t ecc;
u_int8_t firmware[8];
u_int8_t model[40];
u_int16_t multi;
u_int16_t dwcap;
u_int16_t cap;
u_int16_t reserved3;
u_int16_t piomode;
u_int16_t dmamode;
u_int16_t validinfo;
#define ATA_ID_VALIDINFO_ULTRADMA 0x0004
u_int16_t curcyls;
u_int16_t curheads;
u_int16_t cursectrk;
u_int16_t curseccp[2];
u_int16_t mult2;
u_int16_t addrsec[2];
u_int16_t worddma;
u_int16_t dworddma;
u_int16_t advpiomode;
u_int16_t minmwdma;
u_int16_t recmwdma;
u_int16_t minpio;
u_int16_t minpioflow;
u_int16_t add_support;
#define ATA_ID_ADD_SUPPORT_DRT 0x4000
u_int16_t reserved4;
u_int16_t typtime[2];
u_int16_t reserved5[2];
u_int16_t qdepth;
#define ATA_QDEPTH(_q) (((_q) & 0x1f) + 1)
u_int16_t satacap;
#define ATA_SATACAP_GEN1 0x0002
#define ATA_SATACAP_GEN2 0x0004
#define ATA_SATACAP_GEN3 0x0008
#define ATA_SATACAP_NCQ 0x0100
#define ATA_SATACAP_HIPM 0x0200
#define ATA_SATACAP_HOSTAPS 0x2000
#define ATA_SATACAP_DEVAPS 0x4000
u_int16_t reserved6;
u_int16_t satafsup;
#define ATA_SATAFSUP_DIPM 0x0008
#define ATA_SATAFSUP_DEVSLP 0x0100
u_int16_t satafen;
#define ATA_SATAFEN_DIPM 0x0008
#define ATA_SATAFEN_DEVSLP 0x0100
u_int16_t majver;
u_int16_t minver;
u_int16_t cmdset82;
u_int16_t cmdset83;
u_int16_t cmdset84;
u_int16_t features85;
u_int16_t features86;
u_int16_t features87;
#define ATA_ID_F87_WWN (1<<8)
u_int16_t ultradma;
u_int16_t erasetime;
u_int16_t erasetimex;
u_int16_t apm;
u_int16_t masterpw;
u_int16_t hwreset;
u_int16_t acoustic;
u_int16_t stream_min;
u_int16_t stream_xfer_d;
u_int16_t stream_lat;
u_int16_t streamperf[2];
u_int16_t addrsecxt[4];
u_int16_t stream_xfer_p;
u_int16_t padding1;
u_int16_t p2l_sect;
#define ATA_ID_P2L_SECT_MASK 0xc000
#define ATA_ID_P2L_SECT_VALID 0x4000
#define ATA_ID_P2L_SECT_SET 0x2000
#define ATA_ID_P2L_SECT_SIZESET 0x1000
#define ATA_ID_P2L_SECT_SIZE 0x000f
u_int16_t seek_delay;
u_int16_t naa_ieee_oui;
u_int16_t ieee_oui_uid;
u_int16_t uid_mid;
u_int16_t uid_low;
u_int16_t resv_wwn[4];
u_int16_t incits;
u_int16_t words_lsec[2];
u_int16_t cmdset119;
u_int16_t features120;
u_int16_t padding2[6];
u_int16_t rmsn;
u_int16_t securestatus;
u_int16_t vendor[31];
u_int16_t padding3[8];
u_int16_t form;
#define ATA_ID_FORM_MASK 0x000f
u_int16_t data_set_mgmt;
#define ATA_ID_DATA_SET_MGMT_TRIM 0x0001
u_int16_t padding4[6];
u_int16_t curmedser[30];
u_int16_t sctsupport;
u_int16_t rpm;
u_int16_t padding5[1];
u_int16_t logical_align;
#define ATA_ID_LALIGN_MASK 0xc000
#define ATA_ID_LALIGN_VALID 0x4000
#define ATA_ID_LALIGN 0x3fff
u_int16_t padding6[45];
u_int16_t integrity;
} __packed;
#define ATA_IDENTIFY_WRITECACHE (1 << 5)
#define ATA_IDENTIFY_LOOKAHEAD (1 << 6)
#define ATA_DSM_TRIM 0x01
#define ATA_DSM_TRIM_DESC(_lba, _len) ((_lba) | ((u_int64_t)(_len) << 48))
#define ATA_DSM_TRIM_MAX_LEN 0xffff
#define ATA_FIS_LENGTH 20
struct ata_fis_h2d {
u_int8_t type;
#define ATA_FIS_TYPE_H2D 0x27
u_int8_t flags;
#define ATA_H2D_FLAGS_CMD (1<<7)
u_int8_t command;
u_int8_t features;
#define ATA_H2D_FEATURES_DMA (1<<0)
#define ATA_H2D_FEATURES_DIR (1<<2)
#define ATA_H2D_FEATURES_DIR_READ (1<<2)
#define ATA_H2D_FEATURES_DIR_WRITE (0<<2)
u_int8_t lba_low;
u_int8_t lba_mid;
u_int8_t lba_high;
u_int8_t device;
#define ATA_H2D_DEVICE_LBA 0x40
u_int8_t lba_low_exp;
u_int8_t lba_mid_exp;
u_int8_t lba_high_exp;
u_int8_t features_exp;
u_int8_t sector_count;
u_int8_t sector_count_exp;
u_int8_t reserved0;
u_int8_t control;
#define ATA_FIS_CONTROL_SRST 0x04
#define ATA_FIS_CONTROL_4BIT 0x08
u_int8_t reserved1;
u_int8_t reserved2;
u_int8_t reserved3;
u_int8_t reserved4;
} __packed;
struct ata_fis_d2h {
u_int8_t type;
#define ATA_FIS_TYPE_D2H 0x34
u_int8_t flags;
#define ATA_D2H_FLAGS_INTR (1<<6)
u_int8_t status;
u_int8_t error;
u_int8_t lba_low;
u_int8_t lba_mid;
u_int8_t lba_high;
u_int8_t device;
u_int8_t lba_low_exp;
u_int8_t lba_mid_exp;
u_int8_t lba_high_exp;
u_int8_t reserved0;
u_int8_t sector_count;
u_int8_t sector_count_exp;
u_int8_t reserved1;
u_int8_t reserved2;
u_int8_t reserved3;
u_int8_t reserved4;
u_int8_t reserved5;
u_int8_t reserved6;
} __packed;
struct ata_log_page_10h {
struct ata_fis_d2h err_regs;
#define ATA_LOG_10H_TYPE_NOTQUEUED 0x80
#define ATA_LOG_10H_TYPE_TAG_MASK 0x1f
u_int8_t reserved[256 - sizeof(struct ata_fis_d2h)];
u_int8_t vendor_specific[255];
u_int8_t checksum;
} __packed;
#define SATA_SStatus_DET 0x00f
#define SATA_SStatus_DET_NODEV 0x000
#define SATA_SStatus_DET_NOPHY 0x001
#define SATA_SStatus_DET_DEV 0x003
#define SATA_SStatus_DET_OFFLINE 0x004
#define SATA_SStatus_SPD 0x0f0
#define SATA_SStatus_SPD_NONE 0x000
#define SATA_SStatus_SPD_1_5 0x010
#define SATA_SStatus_SPD_3_0 0x020
#define SATA_SStatus_SPD_6_0 0x030
#define SATA_SStatus_IPM 0xf00
#define SATA_SStatus_IPM_NODEV 0x000
#define SATA_SStatus_IPM_ACTIVE 0x100
#define SATA_SStatus_IPM_PARTIAL 0x200
#define SATA_SStatus_IPM_SLUMBER 0x600
#define SATA_SStatus_IPM_DEVSLEEP 0x800
#define SATA_SIGNATURE_PORT_MULTIPLIER 0x96690101
#define SATA_SIGNATURE_ATAPI 0xeb140101
#define SATA_SIGNATURE_DISK 0x00000101
struct ata_xfer {
struct ata_fis_h2d *fis;
struct ata_fis_d2h rfis;
u_int8_t *packetcmd;
u_int8_t tag;
void *data;
size_t datalen;
size_t resid;
void (*complete)(struct ata_xfer *);
struct task task;
struct timeout stimeout;
u_int timeout;
int flags;
#define ATA_F_READ (1<<0)
#define ATA_F_WRITE (1<<1)
#define ATA_F_NOWAIT (1<<2)
#define ATA_F_POLL (1<<3)
#define ATA_F_PIO (1<<4)
#define ATA_F_PACKET (1<<5)
#define ATA_F_NCQ (1<<6)
#define ATA_F_DONE (1<<7)
#define ATA_F_GET_RFIS (1<<8)
#define ATA_FMT_FLAGS "\020" "\011GET_RFIS" "\010DONE" \
"\007NCQ" "\006PACKET" "\005PIO" \
"\004POLL" "\003NOWAIT" "\002WRITE" \
"\001READ"
volatile int state;
#define ATA_S_SETUP 0
#define ATA_S_PENDING 1
#define ATA_S_COMPLETE 2
#define ATA_S_ERROR 3
#define ATA_S_TIMEOUT 4
#define ATA_S_ONCHIP 5
#define ATA_S_PUT 6
#define ATA_S_DONE 7
void *atascsi_private;
int pmp_port;
};
struct atascsi_methods {
int (*ata_probe)(void *, int, int);
void (*ata_free)(void *, int, int);
struct ata_xfer * (*ata_get_xfer)(void *, int);
void (*ata_put_xfer)(struct ata_xfer *);
void (*ata_cmd)(struct ata_xfer *);
};
struct atascsi_attach_args {
void *aaa_cookie;
const struct atascsi_methods *aaa_methods;
void (*aaa_minphys)(struct buf *,
struct scsi_link *);
int aaa_nports;
int aaa_ncmds;
int aaa_capability;
#define ASAA_CAP_NCQ (1 << 0)
#define ASAA_CAP_NEEDS_RESERVED (1 << 1)
#define ASAA_CAP_PMP_NCQ (1 << 2)
};
#define ATA_PORT_T_NONE 0
#define ATA_PORT_T_DISK 1
#define ATA_PORT_T_ATAPI 2
#define ATA_PORT_T_PM 3
struct atascsi *atascsi_attach(struct device *, struct atascsi_attach_args *);
int atascsi_detach(struct atascsi *, int);
void ata_complete(struct ata_xfer *);
#endif