#ifndef _DEV_ATA_ATAVAR_H_
#define _DEV_ATA_ATAVAR_H_
#include <sys/lock.h>
#include <sys/queue.h>
#include <dev/ata/ataconf.h>
#include <dev/scsipi/scsipi_all.h>
#include <dev/scsipi/atapiconf.h>
struct ata_bio {
volatile uint16_t flags;
#define ATA_POLL 0x0002
#define ATA_ITSDONE 0x0004
#define ATA_SINGLE 0x0008
#define ATA_LBA 0x0010
#define ATA_READ 0x0020
#define ATA_CORR 0x0040
#define ATA_LBA48 0x0080
#define ATA_FUA 0x0100
#define ATA_PRIO_HIGH 0x0200
daddr_t blkno;
daddr_t blkdone;
daddr_t nblks;
int nbytes;
long bcount;
char *databuf;
volatile int error;
#define NOERROR 0
#define ERROR 1
#define ERR_DF 2
#define ERR_DMA 3
#define TIMEOUT 4
#define ERR_NODEV 5
#define ERR_RESET 6
#define REQUEUE 7
uint8_t r_error;
struct buf *bp;
};
struct ata_command {
uint64_t r_lba;
uint16_t r_count;
union {
uint16_t r_features;
uint8_t r_error;
};
union {
uint8_t r_command;
uint8_t r_status;
};
uint8_t r_device;
uint8_t r_st_bmask;
uint8_t r_st_pmask;
volatile uint16_t flags;
#define AT_READ 0x0001
#define AT_WRITE 0x0002
#define AT_WAIT 0x0008
#define AT_POLL 0x0010
#define AT_DONE 0x0020
#define AT_XFDONE 0x0040
#define AT_ERROR 0x0080
#define AT_TIMEOU 0x0100
#define AT_DF 0x0200
#define AT_RESET 0x0400
#define AT_GONE 0x0800
#define AT_READREG 0x1000
#define AT_LBA 0x2000
#define AT_LBA48 0x4000
int timeout;
void *data;
int bcount;
};
struct scsipi_xfer;
struct ata_xfer_ops;
struct ata_xfer {
int8_t c_slot;
struct ata_channel *c_chp;
uint16_t c_drive;
uint16_t c_retries;
volatile u_int c_flags;
void *c_databuf;
int c_bcount;
int c_skip;
#define ATACH_ERR_ST(error, status) ((error) << 8 | (status))
#define ATACH_ERR(val) (((val) >> 8) & 0xff)
#define ATACH_ST(val) (((val) >> 0) & 0xff)
union {
struct ata_bio c_bio;
struct ata_command c_ata_c;
struct {
struct scsipi_xfer *c_scsipi;
int c_dscpoll;
int c_lenoff;
} atapi;
} u;
#define c_bio u.c_bio
#define c_ata_c u.c_ata_c
#define c_atapi u.atapi
#define c_scsipi c_atapi.c_scsipi
SIMPLEQ_ENTRY(ata_xfer) c_xferchain;
TAILQ_ENTRY(ata_xfer) c_activechain;
SLIST_ENTRY(ata_xfer) c_retrychain;
const struct ata_xfer_ops *ops;
};
struct ata_xfer_ops {
int (*c_start)(struct ata_channel *, struct ata_xfer *);
#define ATASTART_STARTED 0
#define ATASTART_TH 1
#define ATASTART_POLL 2
#define ATASTART_ABORT 3
int (*c_poll)(struct ata_channel *, struct ata_xfer *);
#define ATAPOLL_DONE 0
#define ATAPOLL_AGAIN 1
void (*c_abort)(struct ata_channel *, struct ata_xfer *);
int (*c_intr)(struct ata_channel *, struct ata_xfer *, int);
void (*c_kill_xfer)(struct ata_channel *, struct ata_xfer *, int);
};
#define C_ATAPI 0x0001
#define C_TIMEOU 0x0002
#define C_POLL 0x0004
#define C_DMA 0x0008
#define C_WAIT 0x0010
#define C_WAITACT 0x0020
#define C_FREE 0x0040
#define C_PIOBM 0x0080
#define C_NCQ 0x0100
#define C_SKIP_QUEUE 0x0200
#define C_WAITTIMO 0x0400
#define C_CHAOS 0x0800
#define C_RECOVERED 0x1000
#define C_PRIVATE_ALLOC 0x2000
#define KILL_GONE 1
#define KILL_RESET 2
#define KILL_GONE_INACTIVE 3
#define KILL_REQUEUE 4
#define ATA_MAX_OPENINGS 32
#define ATA_REAL_OPENINGS(op) ((op) > 1 ? (op) - 1 : 1)
#define ATA_BSIZE 512
#ifndef ATABUS_PRIVATE
struct ata_queue;
#else
struct ata_queue {
int8_t queue_flags;
#define QF_IDLE_WAIT 0x01
#define QF_NEED_XFER 0x02
int8_t queue_active;
uint8_t queue_openings;
SIMPLEQ_HEAD(, ata_xfer) queue_xfer;
int queue_freeze;
kcondvar_t queue_drain;
kcondvar_t queue_idle;
TAILQ_HEAD(, ata_xfer) active_xfers;
uint32_t active_xfers_used;
uint32_t queue_xfers_avail;
uint32_t queue_hold;
kcondvar_t c_active;
kcondvar_t c_cmd_finish;
};
#endif
struct atabus_softc {
device_t sc_dev;
struct ata_channel *sc_chan;
int sc_flags;
#define ATABUSCF_OPEN 0x01
};
struct atabus_initq {
TAILQ_ENTRY(atabus_initq) atabus_initq;
struct atabus_softc *atabus_sc;
};
struct ataparams;
struct ata_drive_datas {
uint8_t drive;
int8_t ata_vers;
uint16_t drive_flags;
#define ATA_DRIVE_CAP32 0x0001
#define ATA_DRIVE_DMA 0x0002
#define ATA_DRIVE_UDMA 0x0004
#define ATA_DRIVE_MODE 0x0008
#define ATA_DRIVE_RESET 0x0010
#define ATA_DRIVE_WAITDRAIN 0x0020
#define ATA_DRIVE_NOSTREAM 0x0040
#define ATA_DRIVE_ATAPIDSCW 0x0080
#define ATA_DRIVE_WFUA 0x0100
#define ATA_DRIVE_NCQ 0x0200
#define ATA_DRIVE_NCQ_PRIO 0x0400
#define ATA_DRIVE_TH_RESET 0x0800
uint8_t drive_type;
#define ATA_DRIVET_NONE 0
#define ATA_DRIVET_ATA 1
#define ATA_DRIVET_ATAPI 2
#define ATA_DRIVET_OLD 3
#define ATA_DRIVET_PM 4
uint8_t PIO_mode;
#if NATA_DMA
uint8_t DMA_mode;
#if NATA_UDMA
uint8_t UDMA_mode;
#endif
#endif
uint8_t PIO_cap;
#if NATA_DMA
uint8_t DMA_cap;
#if NATA_UDMA
uint8_t UDMA_cap;
#endif
#endif
uint8_t state;
#define RESET 0
#define READY 1
uint8_t drv_openings;
#if NATA_DMA
uint8_t n_dmaerrs;
uint32_t n_xfers;
#define NERRS_MAX 4
#define NXFER 4000
#endif
void (*drv_done)(device_t, struct ata_xfer *);
device_t drv_softc;
struct ata_channel *chnl_softc;
struct disklabel *lp;
uint8_t multi;
struct bad144_context *bad144;
};
#define ATA_CONFIG_PIO_MODES 0x0007
#define ATA_CONFIG_PIO_SET 0x0008
#define ATA_CONFIG_PIO_OFF 0
#define ATA_CONFIG_DMA_MODES 0x0070
#define ATA_CONFIG_DMA_SET 0x0080
#define ATA_CONFIG_DMA_DISABLE 0x0070
#define ATA_CONFIG_DMA_OFF 4
#define ATA_CONFIG_UDMA_MODES 0x0700
#define ATA_CONFIG_UDMA_SET 0x0800
#define ATA_CONFIG_UDMA_DISABLE 0x0700
#define ATA_CONFIG_UDMA_OFF 8
struct ata_bustype {
int bustype_type;
void (*ata_bio)(struct ata_drive_datas *, struct ata_xfer *);
void (*ata_reset_drive)(struct ata_drive_datas *, int, uint32_t *);
void (*ata_reset_channel)(struct ata_channel *, int);
void (*ata_exec_command)(struct ata_drive_datas *,
struct ata_xfer *);
#define ATACMD_COMPLETE 0x01
#define ATACMD_QUEUED 0x02
#define ATACMD_TRY_AGAIN 0x03
int (*ata_get_params)(struct ata_drive_datas *, uint8_t,
struct ataparams *);
int (*ata_addref)(struct ata_drive_datas *);
void (*ata_delref)(struct ata_drive_datas *);
void (*ata_killpending)(struct ata_drive_datas *);
void (*ata_recovery)(struct ata_channel *, int, uint32_t);
};
#define SCSIPI_BUSTYPE_ATA 2
struct ata_device {
const struct ata_bustype *adev_bustype;
int adev_channel;
struct ata_drive_datas *adev_drv_data;
};
struct ata_channel {
int ch_channel;
struct atac_softc *ch_atac;
kmutex_t ch_lock;
volatile int ch_flags;
#define ATACH_SHUTDOWN 0x02
#define ATACH_IRQ_WAIT 0x10
#define ATACH_DMA_WAIT 0x20
#define ATACH_PIOBM_WAIT 0x40
#define ATACH_DISABLED 0x80
#define ATACH_TH_RESET 0x200
#define ATACH_TH_RESCAN 0x400
#define ATACH_NCQ 0x800
#define ATACH_DMA_BEFORE_CMD 0x01000
#define ATACH_TH_DRIVE_RESET 0x02000
#define ATACH_RECOVERING 0x04000
#define ATACH_TH_RECOVERY 0x08000
#define ATACH_DETACHED 0x10000
#define ATACH_NODRIVE 0xff
struct callout c_timo_callout;
int ch_ndrives;
struct ata_drive_datas *ch_drive;
device_t atabus;
device_t atapibus;
struct scsipi_channel ch_atapi_channel;
struct ata_queue *ch_queue;
struct lwp *ch_thread;
kcondvar_t ch_thr_idle;
int ch_satapmp_nports;
struct ata_xfer recovery_xfer;
uint8_t recovery_blk[ATA_BSIZE];
uint32_t recovery_tfd;
};
struct atac_softc {
device_t atac_dev;
int atac_cap;
#define ATAC_CAP_DATA16 0x0001
#define ATAC_CAP_DATA32 0x0002
#define ATAC_CAP_DMA 0x0008
#define ATAC_CAP_UDMA 0x0010
#define ATAC_CAP_PIOBM 0x0020
#define ATAC_CAP_ATA_NOSTREAM 0x0040
#define ATAC_CAP_ATAPI_NOSTREAM 0x0080
#define ATAC_CAP_NOIRQ 0x1000
#define ATAC_CAP_RAID 0x4000
#define ATAC_CAP_NCQ 0x8000
uint8_t atac_pio_cap;
#if NATA_DMA
uint8_t atac_dma_cap;
#if NATA_UDMA
uint8_t atac_udma_cap;
#endif
#endif
struct ata_channel **atac_channels;
int atac_nchannels;
const struct ata_bustype *atac_bustype_ata;
struct atapi_adapter atac_atapi_adapter;
void (*atac_atapibus_attach)(struct atabus_softc *);
void (*atac_probe)(struct ata_channel *);
int (*atac_claim_hw)(struct ata_channel *, int);
void (*atac_free_hw)(struct ata_channel *);
void (*atac_set_modes)(struct ata_channel *);
};
#ifdef _KERNEL
void ata_channel_attach(struct ata_channel *);
void ata_channel_init(struct ata_channel *);
void ata_channel_detach(struct ata_channel *);
void ata_channel_destroy(struct ata_channel *);
int atabusprint(void *aux, const char *);
int ataprint(void *aux, const char *);
int atabus_alloc_drives(struct ata_channel *, int);
void atabus_free_drives(struct ata_channel *);
struct ataparams;
int ata_get_params(struct ata_drive_datas *, uint8_t, struct ataparams *);
int ata_set_pio8(struct ata_drive_datas *, uint8_t);
int ata_set_mode(struct ata_drive_datas *, uint8_t, uint8_t);
int ata_read_log_ext_ncq(struct ata_drive_datas *, uint8_t, uint8_t *,
uint8_t *, uint8_t *);
void ata_recovery_resume(struct ata_channel *, int, int, int);
#define CMD_OK 0
#define CMD_ERR 1
#define CMD_AGAIN 2
struct ata_xfer *ata_get_xfer(struct ata_channel *, bool);
void ata_free_xfer(struct ata_channel *, struct ata_xfer *);
void ata_deactivate_xfer(struct ata_channel *, struct ata_xfer *);
void ata_exec_xfer(struct ata_channel *, struct ata_xfer *);
int ata_xfer_start(struct ata_xfer *xfer);
void ata_wait_cmd(struct ata_channel *, struct ata_xfer *xfer);
void ata_timeout(void *);
bool ata_timo_xfer_check(struct ata_xfer *);
void ata_kill_pending(struct ata_drive_datas *);
void ata_kill_active(struct ata_channel *, int, int);
void ata_thread_run(struct ata_channel *, int, int, int);
bool ata_is_thread_run(struct ata_channel *);
void ata_channel_freeze(struct ata_channel *);
void ata_channel_thaw_locked(struct ata_channel *);
void ata_channel_lock(struct ata_channel *);
void ata_channel_unlock(struct ata_channel *);
void ata_channel_lock_owned(struct ata_channel *);
int ata_addref(struct ata_channel *);
void ata_delref(struct ata_channel *);
void atastart(struct ata_channel *);
void ata_print_modes(struct ata_channel *);
void ata_probe_caps(struct ata_drive_datas *);
#if NATA_DMA
void ata_dmaerr(struct ata_drive_datas *, int);
#endif
struct ata_queue *
ata_queue_alloc(uint8_t openings);
void ata_queue_free(struct ata_queue *);
struct ata_xfer *
ata_queue_hwslot_to_xfer(struct ata_channel *, int);
struct ata_xfer *
ata_queue_get_active_xfer(struct ata_channel *);
struct ata_xfer *
ata_queue_get_active_xfer_locked(struct ata_channel *);
struct ata_xfer *
ata_queue_drive_active_xfer(struct ata_channel *, int);
bool ata_queue_alloc_slot(struct ata_channel *, uint8_t *, uint8_t);
void ata_queue_free_slot(struct ata_channel *, uint8_t);
uint32_t ata_queue_active(struct ata_channel *);
uint8_t ata_queue_openings(struct ata_channel *);
void ata_queue_hold(struct ata_channel *);
void ata_queue_unhold(struct ata_channel *);
void ata_delay(struct ata_channel *, int, const char *, int);
bool ata_waitdrain_xfer_check(struct ata_channel *, struct ata_xfer *);
void atacmd_toncq(struct ata_xfer *, uint8_t *, uint16_t *, uint16_t *,
uint8_t *);
#ifdef ATADEBUG
void atachannel_debug(struct ata_channel *);
#endif
#endif
#endif