#include <sys/mutex.h>
#include <sys/timeout.h>
#include <dev/ata/atascsi.h>
#include <dev/ata/pmreg.h>
#define NO_AHCI_DEBUG
struct ahci_dmamem {
bus_dmamap_t adm_map;
bus_dma_segment_t adm_seg;
size_t adm_size;
caddr_t adm_kva;
};
#define AHCI_DMA_MAP(_adm) ((_adm)->adm_map)
#define AHCI_DMA_DVA(_adm) ((u_int64_t)(_adm)->adm_map->dm_segs[0].ds_addr)
#define AHCI_DMA_KVA(_adm) ((void *)(_adm)->adm_kva)
struct ahci_softc;
struct ahci_port;
struct ahci_ccb {
struct ata_xfer ccb_xa;
int ccb_slot;
struct ahci_port *ccb_port;
bus_dmamap_t ccb_dmamap;
struct ahci_cmd_hdr *ccb_cmd_hdr;
struct ahci_cmd_table *ccb_cmd_table;
void (*ccb_done)(struct ahci_ccb *);
TAILQ_ENTRY(ahci_ccb) ccb_entry;
};
struct ahci_port {
struct ahci_softc *ap_sc;
bus_space_handle_t ap_ioh;
#ifdef AHCI_COALESCE
int ap_num;
#endif
struct ahci_rfis *ap_rfis;
struct ahci_dmamem *ap_dmamem_rfis;
struct ahci_dmamem *ap_dmamem_cmd_list;
struct ahci_dmamem *ap_dmamem_cmd_table;
volatile u_int32_t ap_active;
volatile u_int32_t ap_active_cnt;
volatile u_int32_t ap_sactive;
volatile u_int32_t ap_pmp_ncq_port;
struct ahci_ccb *ap_ccbs;
TAILQ_HEAD(, ahci_ccb) ap_ccb_free;
TAILQ_HEAD(, ahci_ccb) ap_ccb_pending;
struct mutex ap_ccb_mtx;
struct ahci_ccb *ap_ccb_err;
u_int32_t ap_state;
#define AP_S_NORMAL 0
#define AP_S_PMP_PROBE 1
#define AP_S_PMP_PORT_PROBE 2
#define AP_S_ERROR_RECOVERY 3
#define AP_S_FATAL_ERROR 4
int ap_pmp_ports;
int ap_port;
int ap_pmp_ignore_ifs;
#ifdef DIAGNOSTIC
int ap_err_busy;
#endif
u_int32_t ap_err_saved_sactive;
u_int32_t ap_err_saved_active;
u_int32_t ap_err_saved_active_cnt;
u_int32_t ap_saved_cmd;
u_int8_t *ap_err_scratch;
#ifdef AHCI_DEBUG
char ap_name[16];
#define PORTNAME(_ap) ((_ap)->ap_name)
#else
#define PORTNAME(_ap) DEVNAME((_ap)->ap_sc)
#endif
};
struct ahci_softc {
struct device sc_dev;
void *sc_ih;
bus_space_tag_t sc_iot;
bus_space_handle_t sc_ioh;
bus_size_t sc_ios;
bus_dma_tag_t sc_dmat;
int sc_flags;
#define AHCI_F_NO_NCQ (1<<0)
#define AHCI_F_IPMS_PROBE (1<<1)
#define AHCI_F_NO_PMP (1<<2)
#define AHCI_F_NO_MSI (1<<3)
u_int sc_ncmds;
struct ahci_port *sc_ports[AHCI_MAX_PORTS];
struct atascsi *sc_atascsi;
u_int32_t sc_cap;
#ifdef AHCI_COALESCE
u_int32_t sc_ccc_mask;
u_int32_t sc_ccc_ports;
u_int32_t sc_ccc_ports_cur;
#endif
int (*sc_port_start)(struct ahci_port *, int);
};
#define DEVNAME(_s) ((_s)->sc_dev.dv_xname)
#define ahci_port_start(_p, _f) ((_p)->ap_sc->sc_port_start((_p), (_f)))
int ahci_attach(struct ahci_softc *);
int ahci_detach(struct ahci_softc *, int);
int ahci_activate(struct device *, int);
int ahci_intr(void *);