ATA_QCFLAG_RESULT_TF = (1 << 4), /* result TF requested */
ATA_QCFLAG_CLEAR_EXCL = (1 << 5), /* clear excl_link on completion */
ATA_QCFLAG_QUIET = (1 << 6), /* don't report device error */
+ ATA_QCFLAG_RETRY = (1 << 7), /* retry after failure */
ATA_QCFLAG_FAILED = (1 << 16), /* cmd failed and is owned by EH */
ATA_QCFLAG_SENSE_VALID = (1 << 17), /* sense data valid */
*/
ATA_TMOUT_FF_WAIT = 4 * HZ / 5,
+ /* Spec mandates to wait for ">= 2ms" before checking status
+ * after reset. We wait 150ms, because that was the magic
+ * delay used for ATAPI devices in Hale Landis's ATADRVR, for
+ * the period of time between when the ATA command register is
+ * written, and then status is checked. Because waiting for
+ * "a while" before checking status is fine, post SRST, we
+ * perform this magic delay here as well.
+ *
+ * Old drivers/ide uses the 2mS rule and then waits for ready.
+ */
+ ATA_WAIT_AFTER_RESET_MSECS = 150,
+
+ /* If PMP is supported, we have to do follow-up SRST. As some
+ * PMPs don't send D2H Reg FIS after hardreset, LLDs are
+ * advised to wait only for the following duration before
+ * doing SRST.
+ */
+ ATA_TMOUT_PMP_SRST_WAIT = 1 * HZ,
+
/* ATA bus states */
BUS_UNKNOWN = 0,
BUS_DMA = 1,
MAX_PERFORMANCE,
MEDIUM_POWER,
};
-extern struct class_device_attribute class_device_attr_link_power_management_policy;
+extern struct device_attribute dev_attr_link_power_management_policy;
+#ifdef CONFIG_ATA_SFF
struct ata_ioports {
void __iomem *cmd_addr;
void __iomem *data_addr;
void __iomem *bmdma_addr;
void __iomem *scr_addr;
};
+#endif /* CONFIG_ATA_SFF */
struct ata_host {
spinlock_t lock;
struct ata_prd *prd; /* our SG list */
dma_addr_t prd_dma; /* and its DMA mapping */
+#ifdef CONFIG_ATA_SFF
struct ata_ioports ioaddr; /* ATA cmd/ctl/dma register blocks */
+#endif /* CONFIG_ATA_SFF */
u8 ctl; /* cache of ATA control register */
u8 last_ctl; /* Cache last written value */
int (*check_atapi_dma)(struct ata_queued_cmd *qc);
void (*qc_prep)(struct ata_queued_cmd *qc);
unsigned int (*qc_issue)(struct ata_queued_cmd *qc);
+ bool (*qc_fill_rtf)(struct ata_queued_cmd *qc);
/*
* Configuration and exception handling
void (*port_stop)(struct ata_port *ap);
void (*host_stop)(struct ata_host *host);
+#ifdef CONFIG_ATA_SFF
/*
* SFF / taskfile oriented ops
*/
- void (*dev_select)(struct ata_port *ap, unsigned int device);
- u8 (*check_status)(struct ata_port *ap);
- u8 (*check_altstatus)(struct ata_port *ap);
- void (*tf_load)(struct ata_port *ap, const struct ata_taskfile *tf);
- void (*tf_read)(struct ata_port *ap, struct ata_taskfile *tf);
- void (*exec_command)(struct ata_port *ap, const struct ata_taskfile *tf);
- unsigned int (*data_xfer)(struct ata_device *dev, unsigned char *buf,
- unsigned int buflen, int rw);
- u8 (*irq_on)(struct ata_port *);
-
- void (*irq_clear)(struct ata_port *);
+ void (*sff_dev_select)(struct ata_port *ap, unsigned int device);
+ u8 (*sff_check_status)(struct ata_port *ap);
+ u8 (*sff_check_altstatus)(struct ata_port *ap);
+ void (*sff_tf_load)(struct ata_port *ap, const struct ata_taskfile *tf);
+ void (*sff_tf_read)(struct ata_port *ap, struct ata_taskfile *tf);
+ void (*sff_exec_command)(struct ata_port *ap,
+ const struct ata_taskfile *tf);
+ unsigned int (*sff_data_xfer)(struct ata_device *dev,
+ unsigned char *buf, unsigned int buflen, int rw);
+ u8 (*sff_irq_on)(struct ata_port *);
+ void (*sff_irq_clear)(struct ata_port *);
+
void (*bmdma_setup)(struct ata_queued_cmd *qc);
void (*bmdma_start)(struct ata_queued_cmd *qc);
void (*bmdma_stop)(struct ata_queued_cmd *qc);
u8 (*bmdma_status)(struct ata_port *ap);
+#endif /* CONFIG_ATA_SFF */
/*
* Obsolete
return ap->ops == &ata_dummy_port_ops;
}
-extern void sata_print_link_status(struct ata_link *link);
extern void ata_port_probe(struct ata_port *);
extern int sata_set_spd(struct ata_link *link);
+extern int ata_std_prereset(struct ata_link *link, unsigned long deadline);
+extern int ata_wait_after_reset(struct ata_link *link, unsigned long deadline,
+ int (*check_ready)(struct ata_link *link));
extern int sata_link_debounce(struct ata_link *link,
const unsigned long *params, unsigned long deadline);
extern int sata_link_resume(struct ata_link *link, const unsigned long *params,
unsigned long deadline);
extern int sata_link_hardreset(struct ata_link *link,
- const unsigned long *timing, unsigned long deadline);
+ const unsigned long *timing, unsigned long deadline,
+ bool *online, int (*check_ready)(struct ata_link *));
+extern int sata_std_hardreset(struct ata_link *link, unsigned int *class,
+ unsigned long deadline);
+extern void ata_std_postreset(struct ata_link *link, unsigned int *classes);
extern void ata_port_disable(struct ata_port *);
extern struct ata_host *ata_host_alloc(struct device *dev, int max_ports);
extern int ata_xfer_mode2shift(unsigned long xfer_mode);
extern const char *ata_mode_string(unsigned long xfer_mask);
extern unsigned long ata_id_xfermask(const u16 *id);
-extern void ata_noop_dev_select(struct ata_port *ap, unsigned int device);
extern int ata_port_start(struct ata_port *ap);
extern int ata_std_qc_defer(struct ata_queued_cmd *qc);
extern void ata_noop_qc_prep(struct ata_queued_cmd *qc);
unsigned int ofs, unsigned int len);
extern void ata_id_c_string(const u16 *id, unsigned char *s,
unsigned int ofs, unsigned int len);
-extern void ata_noop_irq_clear(struct ata_port *ap);
extern void ata_qc_complete(struct ata_queued_cmd *qc);
-extern int ata_qc_complete_multiple(struct ata_port *ap, u32 qc_active,
- void (*finish_qc)(struct ata_queued_cmd *));
+extern int ata_qc_complete_multiple(struct ata_port *ap, u32 qc_active);
extern void ata_scsi_simulate(struct ata_device *dev, struct scsi_cmnd *cmd,
void (*done)(struct scsi_cmnd *));
extern int ata_std_bios_param(struct scsi_device *sdev,
}
#endif
-/*
- * PMP - drivers/ata/libata-pmp.c
- */
-extern int sata_pmp_qc_defer_cmd_switch(struct ata_queued_cmd *qc);
-extern int sata_pmp_std_prereset(struct ata_link *link, unsigned long deadline);
-extern int sata_pmp_std_hardreset(struct ata_link *link, unsigned int *class,
- unsigned long deadline);
-extern void sata_pmp_std_postreset(struct ata_link *link, unsigned int *class);
-extern void sata_pmp_error_handler(struct ata_port *ap);
-
/*
* EH - drivers/ata/libata-eh.c
*/
*/
extern const struct ata_port_operations ata_base_port_ops;
extern const struct ata_port_operations sata_port_ops;
-extern const struct ata_port_operations sata_pmp_port_ops;
#define ATA_BASE_SHT(drv_name) \
.module = THIS_MODULE, \
ATA_BASE_SHT(drv_name), \
.change_queue_depth = ata_scsi_change_queue_depth
+/*
+ * PMP helpers
+ */
+#ifdef CONFIG_SATA_PMP
+static inline bool sata_pmp_supported(struct ata_port *ap)
+{
+ return ap->flags & ATA_FLAG_PMP;
+}
+
+static inline bool sata_pmp_attached(struct ata_port *ap)
+{
+ return ap->nr_pmp_links != 0;
+}
+
+static inline int ata_is_host_link(const struct ata_link *link)
+{
+ return link == &link->ap->link;
+}
+#else /* CONFIG_SATA_PMP */
+static inline bool sata_pmp_supported(struct ata_port *ap)
+{
+ return false;
+}
+
+static inline bool sata_pmp_attached(struct ata_port *ap)
+{
+ return false;
+}
+
+static inline int ata_is_host_link(const struct ata_link *link)
+{
+ return 1;
+}
+#endif /* CONFIG_SATA_PMP */
+
+static inline int sata_srst_pmp(struct ata_link *link)
+{
+ if (sata_pmp_supported(link->ap) && ata_is_host_link(link))
+ return SATA_PMP_CTRL_PORT;
+ return link->pmp;
+}
+
/*
* printk helpers
*/
printk("%sata%u: "fmt, lv, (ap)->print_id , ##args)
#define ata_link_printk(link, lv, fmt, args...) do { \
- if ((link)->ap->nr_pmp_links) \
+ if (sata_pmp_attached((link)->ap)) \
printk("%sata%u.%02u: "fmt, lv, (link)->ap->print_id, \
(link)->pmp , ##args); \
else \
static inline unsigned int ata_tag_internal(unsigned int tag)
{
- return tag == ATA_MAX_QUEUE - 1;
+ return tag == ATA_TAG_INTERNAL;
}
/*
/*
* link helpers
*/
-static inline int ata_is_host_link(const struct ata_link *link)
-{
- return link == &link->ap->link;
-}
-
static inline int ata_link_max_devices(const struct ata_link *link)
{
if (ata_is_host_link(link) && link->ap->flags & ATA_FLAG_SLAVE_POSS)
static inline struct ata_link *ata_port_first_link(struct ata_port *ap)
{
- if (ap->nr_pmp_links)
+ if (sata_pmp_attached(ap))
return ap->pmp_link;
return &ap->link;
}
{
struct ata_port *ap = link->ap;
- if (link == &ap->link) {
- if (!ap->nr_pmp_links)
+ if (ata_is_host_link(link)) {
+ if (!sata_pmp_attached(ap))
return NULL;
return ap->pmp_link;
}
return *(struct ata_port **)&host->hostdata[0];
}
+
+/**************************************************************************
+ * PMP - drivers/ata/libata-pmp.c
+ */
+#ifdef CONFIG_SATA_PMP
+
+extern const struct ata_port_operations sata_pmp_port_ops;
+
+extern int sata_pmp_qc_defer_cmd_switch(struct ata_queued_cmd *qc);
+extern void sata_pmp_error_handler(struct ata_port *ap);
+
+#else /* CONFIG_SATA_PMP */
+
+#define sata_pmp_port_ops sata_port_ops
+#define sata_pmp_qc_defer_cmd_switch ata_std_qc_defer
+#define sata_pmp_error_handler ata_std_error_handler
+
+#endif /* CONFIG_SATA_PMP */
+
+
/**************************************************************************
* SFF - drivers/ata/libata-sff.c
*/
+#ifdef CONFIG_ATA_SFF
+
extern const struct ata_port_operations ata_sff_port_ops;
extern const struct ata_port_operations ata_bmdma_port_ops;
.sg_tablesize = LIBATA_MAX_PRD, \
.dma_boundary = ATA_DMA_BOUNDARY
-extern void ata_qc_prep(struct ata_queued_cmd *qc);
-extern void ata_dumb_qc_prep(struct ata_queued_cmd *qc);
-extern void ata_std_dev_select(struct ata_port *ap, unsigned int device);
-extern u8 ata_check_status(struct ata_port *ap);
-extern u8 ata_altstatus(struct ata_port *ap);
-extern int ata_busy_sleep(struct ata_port *ap,
- unsigned long timeout_pat, unsigned long timeout);
-extern int ata_wait_ready(struct ata_port *ap, unsigned long deadline);
-extern void ata_tf_load(struct ata_port *ap, const struct ata_taskfile *tf);
-extern void ata_tf_read(struct ata_port *ap, struct ata_taskfile *tf);
-extern void ata_exec_command(struct ata_port *ap, const struct ata_taskfile *tf);
-extern unsigned int ata_data_xfer(struct ata_device *dev,
+extern void ata_sff_qc_prep(struct ata_queued_cmd *qc);
+extern void ata_sff_dumb_qc_prep(struct ata_queued_cmd *qc);
+extern void ata_sff_dev_select(struct ata_port *ap, unsigned int device);
+extern u8 ata_sff_check_status(struct ata_port *ap);
+extern u8 ata_sff_altstatus(struct ata_port *ap);
+extern int ata_sff_busy_sleep(struct ata_port *ap,
+ unsigned long timeout_pat, unsigned long timeout);
+extern int ata_sff_wait_ready(struct ata_link *link, unsigned long deadline);
+extern void ata_sff_tf_load(struct ata_port *ap, const struct ata_taskfile *tf);
+extern void ata_sff_tf_read(struct ata_port *ap, struct ata_taskfile *tf);
+extern void ata_sff_exec_command(struct ata_port *ap,
+ const struct ata_taskfile *tf);
+extern unsigned int ata_sff_data_xfer(struct ata_device *dev,
unsigned char *buf, unsigned int buflen, int rw);
-extern unsigned int ata_data_xfer_noirq(struct ata_device *dev,
+extern unsigned int ata_sff_data_xfer_noirq(struct ata_device *dev,
unsigned char *buf, unsigned int buflen, int rw);
-extern u8 ata_irq_on(struct ata_port *ap);
-extern void ata_bmdma_irq_clear(struct ata_port *ap);
-extern int ata_hsm_move(struct ata_port *ap, struct ata_queued_cmd *qc,
- u8 status, int in_wq);
-extern unsigned int ata_qc_issue_prot(struct ata_queued_cmd *qc);
-extern unsigned int ata_host_intr(struct ata_port *ap, struct ata_queued_cmd *qc);
-extern irqreturn_t ata_interrupt(int irq, void *dev_instance);
-extern void ata_bmdma_freeze(struct ata_port *ap);
-extern void ata_bmdma_thaw(struct ata_port *ap);
-extern int ata_std_prereset(struct ata_link *link, unsigned long deadline);
-extern unsigned int ata_dev_try_classify(struct ata_device *dev, int present,
- u8 *r_err);
-extern void ata_wait_after_reset(struct ata_port *ap, unsigned long deadline);
-extern int ata_std_softreset(struct ata_link *link, unsigned int *classes,
+extern u8 ata_sff_irq_on(struct ata_port *ap);
+extern void ata_sff_irq_clear(struct ata_port *ap);
+extern int ata_sff_hsm_move(struct ata_port *ap, struct ata_queued_cmd *qc,
+ u8 status, int in_wq);
+extern unsigned int ata_sff_qc_issue(struct ata_queued_cmd *qc);
+extern bool ata_sff_qc_fill_rtf(struct ata_queued_cmd *qc);
+extern unsigned int ata_sff_host_intr(struct ata_port *ap,
+ struct ata_queued_cmd *qc);
+extern irqreturn_t ata_sff_interrupt(int irq, void *dev_instance);
+extern void ata_sff_freeze(struct ata_port *ap);
+extern void ata_sff_thaw(struct ata_port *ap);
+extern int ata_sff_prereset(struct ata_link *link, unsigned long deadline);
+extern unsigned int ata_sff_dev_classify(struct ata_device *dev, int present,
+ u8 *r_err);
+extern int ata_sff_wait_after_reset(struct ata_link *link, unsigned int devmask,
+ unsigned long deadline);
+extern int ata_sff_softreset(struct ata_link *link, unsigned int *classes,
unsigned long deadline);
-extern int sata_std_hardreset(struct ata_link *link, unsigned int *class,
- unsigned long deadline);
-extern void ata_std_postreset(struct ata_link *link, unsigned int *classes);
-extern void ata_bmdma_error_handler(struct ata_port *ap);
-extern void ata_bmdma_post_internal_cmd(struct ata_queued_cmd *qc);
+extern int sata_sff_hardreset(struct ata_link *link, unsigned int *class,
+ unsigned long deadline);
+extern void ata_sff_postreset(struct ata_link *link, unsigned int *classes);
+extern void ata_sff_error_handler(struct ata_port *ap);
+extern void ata_sff_post_internal_cmd(struct ata_queued_cmd *qc);
extern int ata_sff_port_start(struct ata_port *ap);
-extern void ata_std_ports(struct ata_ioports *ioaddr);
-extern unsigned long ata_pci_default_filter(struct ata_device *dev,
- unsigned long xfer_mask);
+extern void ata_sff_std_ports(struct ata_ioports *ioaddr);
+extern unsigned long ata_bmdma_mode_filter(struct ata_device *dev,
+ unsigned long xfer_mask);
extern void ata_bmdma_setup(struct ata_queued_cmd *qc);
extern void ata_bmdma_start(struct ata_queued_cmd *qc);
extern void ata_bmdma_stop(struct ata_queued_cmd *qc);
extern void ata_bus_reset(struct ata_port *ap);
#ifdef CONFIG_PCI
-extern int ata_pci_clear_simplex(struct pci_dev *pdev);
-extern int ata_pci_init_bmdma(struct ata_host *host);
-extern int ata_pci_init_sff_host(struct ata_host *host);
-extern int ata_pci_prepare_sff_host(struct pci_dev *pdev,
+extern int ata_pci_bmdma_clear_simplex(struct pci_dev *pdev);
+extern int ata_pci_bmdma_init(struct ata_host *host);
+extern int ata_pci_sff_init_host(struct ata_host *host);
+extern int ata_pci_sff_prepare_host(struct pci_dev *pdev,
const struct ata_port_info * const * ppi,
struct ata_host **r_host);
-extern int ata_pci_activate_sff_host(struct ata_host *host,
+extern int ata_pci_sff_activate_host(struct ata_host *host,
irq_handler_t irq_handler,
struct scsi_host_template *sht);
-extern int ata_pci_init_one(struct pci_dev *pdev,
- const struct ata_port_info * const * ppi,
- struct scsi_host_template *sht, void *host_priv);
+extern int ata_pci_sff_init_one(struct pci_dev *pdev,
+ const struct ata_port_info * const * ppi,
+ struct scsi_host_template *sht, void *host_priv);
#endif /* CONFIG_PCI */
-static inline u8 ata_chk_status(struct ata_port *ap)
-{
- return ap->ops->check_status(ap);
-}
-
/**
- * ata_pause - Flush writes and pause 400 nanoseconds.
+ * ata_sff_pause - Flush writes and pause 400 nanoseconds.
* @ap: Port to wait for.
*
* LOCKING:
* Inherited from caller.
*/
-static inline void ata_pause(struct ata_port *ap)
+static inline void ata_sff_pause(struct ata_port *ap)
{
- ata_altstatus(ap);
+ ata_sff_altstatus(ap);
ndelay(400);
}
/**
- * ata_busy_wait - Wait for a port status register
+ * ata_sff_busy_wait - Wait for a port status register
* @ap: Port to wait for.
* @bits: bits that must be clear
* @max: number of 10uS waits to perform
* LOCKING:
* Inherited from caller.
*/
-static inline u8 ata_busy_wait(struct ata_port *ap, unsigned int bits,
- unsigned int max)
+static inline u8 ata_sff_busy_wait(struct ata_port *ap, unsigned int bits,
+ unsigned int max)
{
u8 status;
do {
udelay(10);
- status = ata_chk_status(ap);
+ status = ap->ops->sff_check_status(ap);
max--;
} while (status != 0xff && (status & bits) && (max > 0));
*/
static inline u8 ata_wait_idle(struct ata_port *ap)
{
- u8 status = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 1000);
+ u8 status = ata_sff_busy_wait(ap, ATA_BUSY | ATA_DRQ, 1000);
#ifdef ATA_DEBUG
if (status != 0xff && (status & (ATA_BUSY | ATA_DRQ)))
return status;
}
+#endif /* CONFIG_ATA_SFF */
#endif /* __LINUX_LIBATA_H__ */