mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-11-25 23:20:51 +07:00
Merge branch 'upstream-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jgarzik/libata-dev
* 'upstream-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jgarzik/libata-dev: (67 commits) fix drivers/ata/sata_fsl.c double-decl [libata] Prefer SCSI_SENSE_BUFFERSIZE to sizeof() pata_legacy: Merge winbond support ata_generic: Cenatek support pata_winbond: error return pata_serverworks: Fix cable types and cosmetics pata_mpc52xx: remove un-needed assignment libata: fix off-by-one in error categorization ahci: factor out AHCI enabling and enable AHCI before reading CAP ata_piix: implement SIDPR SCR access ata_piix: convert to prepare - activate initialization libata: factor out ata_pci_activate_sff_host() from ata_pci_one() [libata] Prefer SCSI_SENSE_BUFFERSIZE to sizeof() pata_legacy: resychronize with upstream changes and resubmit [libata] pata_legacy: typo fix [libata] pata_winbond: update for new ->data_xfer hook pata_pcmcia: convert to new data_xfer prototype libata annotations and fixes libata: use dev_driver_string() instead of "libata" in libata-sff.c ata_piix: kill unused constants and flags ...
This commit is contained in:
commit
2ba14a017a
@ -459,6 +459,15 @@ config PATA_NETCELL
|
|||||||
|
|
||||||
If unsure, say N.
|
If unsure, say N.
|
||||||
|
|
||||||
|
config PATA_NINJA32
|
||||||
|
tristate "Ninja32/Delkin Cardbus ATA support (Experimental)"
|
||||||
|
depends on PCI && EXPERIMENTAL
|
||||||
|
help
|
||||||
|
This option enables support for the Ninja32, Delkin and
|
||||||
|
possibly other brands of Cardbus ATA adapter
|
||||||
|
|
||||||
|
If unsure, say N.
|
||||||
|
|
||||||
config PATA_NS87410
|
config PATA_NS87410
|
||||||
tristate "Nat Semi NS87410 PATA support (Experimental)"
|
tristate "Nat Semi NS87410 PATA support (Experimental)"
|
||||||
depends on PCI && EXPERIMENTAL
|
depends on PCI && EXPERIMENTAL
|
||||||
|
@ -41,6 +41,7 @@ obj-$(CONFIG_PATA_IT821X) += pata_it821x.o
|
|||||||
obj-$(CONFIG_PATA_IT8213) += pata_it8213.o
|
obj-$(CONFIG_PATA_IT8213) += pata_it8213.o
|
||||||
obj-$(CONFIG_PATA_JMICRON) += pata_jmicron.o
|
obj-$(CONFIG_PATA_JMICRON) += pata_jmicron.o
|
||||||
obj-$(CONFIG_PATA_NETCELL) += pata_netcell.o
|
obj-$(CONFIG_PATA_NETCELL) += pata_netcell.o
|
||||||
|
obj-$(CONFIG_PATA_NINJA32) += pata_ninja32.o
|
||||||
obj-$(CONFIG_PATA_NS87410) += pata_ns87410.o
|
obj-$(CONFIG_PATA_NS87410) += pata_ns87410.o
|
||||||
obj-$(CONFIG_PATA_NS87415) += pata_ns87415.o
|
obj-$(CONFIG_PATA_NS87415) += pata_ns87415.o
|
||||||
obj-$(CONFIG_PATA_OPTI) += pata_opti.o
|
obj-$(CONFIG_PATA_OPTI) += pata_opti.o
|
||||||
|
@ -198,18 +198,18 @@ enum {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct ahci_cmd_hdr {
|
struct ahci_cmd_hdr {
|
||||||
u32 opts;
|
__le32 opts;
|
||||||
u32 status;
|
__le32 status;
|
||||||
u32 tbl_addr;
|
__le32 tbl_addr;
|
||||||
u32 tbl_addr_hi;
|
__le32 tbl_addr_hi;
|
||||||
u32 reserved[4];
|
__le32 reserved[4];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ahci_sg {
|
struct ahci_sg {
|
||||||
u32 addr;
|
__le32 addr;
|
||||||
u32 addr_hi;
|
__le32 addr_hi;
|
||||||
u32 reserved;
|
__le32 reserved;
|
||||||
u32 flags_size;
|
__le32 flags_size;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ahci_host_priv {
|
struct ahci_host_priv {
|
||||||
@ -597,6 +597,20 @@ static inline void __iomem *ahci_port_base(struct ata_port *ap)
|
|||||||
return __ahci_port_base(ap->host, ap->port_no);
|
return __ahci_port_base(ap->host, ap->port_no);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void ahci_enable_ahci(void __iomem *mmio)
|
||||||
|
{
|
||||||
|
u32 tmp;
|
||||||
|
|
||||||
|
/* turn on AHCI_EN */
|
||||||
|
tmp = readl(mmio + HOST_CTL);
|
||||||
|
if (!(tmp & HOST_AHCI_EN)) {
|
||||||
|
tmp |= HOST_AHCI_EN;
|
||||||
|
writel(tmp, mmio + HOST_CTL);
|
||||||
|
tmp = readl(mmio + HOST_CTL); /* flush && sanity check */
|
||||||
|
WARN_ON(!(tmp & HOST_AHCI_EN));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ahci_save_initial_config - Save and fixup initial config values
|
* ahci_save_initial_config - Save and fixup initial config values
|
||||||
* @pdev: target PCI device
|
* @pdev: target PCI device
|
||||||
@ -619,6 +633,9 @@ static void ahci_save_initial_config(struct pci_dev *pdev,
|
|||||||
u32 cap, port_map;
|
u32 cap, port_map;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
/* make sure AHCI mode is enabled before accessing CAP */
|
||||||
|
ahci_enable_ahci(mmio);
|
||||||
|
|
||||||
/* Values prefixed with saved_ are written back to host after
|
/* Values prefixed with saved_ are written back to host after
|
||||||
* reset. Values without are used for driver operation.
|
* reset. Values without are used for driver operation.
|
||||||
*/
|
*/
|
||||||
@ -1036,19 +1053,17 @@ static int ahci_deinit_port(struct ata_port *ap, const char **emsg)
|
|||||||
static int ahci_reset_controller(struct ata_host *host)
|
static int ahci_reset_controller(struct ata_host *host)
|
||||||
{
|
{
|
||||||
struct pci_dev *pdev = to_pci_dev(host->dev);
|
struct pci_dev *pdev = to_pci_dev(host->dev);
|
||||||
|
struct ahci_host_priv *hpriv = host->private_data;
|
||||||
void __iomem *mmio = host->iomap[AHCI_PCI_BAR];
|
void __iomem *mmio = host->iomap[AHCI_PCI_BAR];
|
||||||
u32 tmp;
|
u32 tmp;
|
||||||
|
|
||||||
/* we must be in AHCI mode, before using anything
|
/* we must be in AHCI mode, before using anything
|
||||||
* AHCI-specific, such as HOST_RESET.
|
* AHCI-specific, such as HOST_RESET.
|
||||||
*/
|
*/
|
||||||
tmp = readl(mmio + HOST_CTL);
|
ahci_enable_ahci(mmio);
|
||||||
if (!(tmp & HOST_AHCI_EN)) {
|
|
||||||
tmp |= HOST_AHCI_EN;
|
|
||||||
writel(tmp, mmio + HOST_CTL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* global controller reset */
|
/* global controller reset */
|
||||||
|
tmp = readl(mmio + HOST_CTL);
|
||||||
if ((tmp & HOST_RESET) == 0) {
|
if ((tmp & HOST_RESET) == 0) {
|
||||||
writel(tmp | HOST_RESET, mmio + HOST_CTL);
|
writel(tmp | HOST_RESET, mmio + HOST_CTL);
|
||||||
readl(mmio + HOST_CTL); /* flush */
|
readl(mmio + HOST_CTL); /* flush */
|
||||||
@ -1067,8 +1082,7 @@ static int ahci_reset_controller(struct ata_host *host)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* turn on AHCI mode */
|
/* turn on AHCI mode */
|
||||||
writel(HOST_AHCI_EN, mmio + HOST_CTL);
|
ahci_enable_ahci(mmio);
|
||||||
(void) readl(mmio + HOST_CTL); /* flush */
|
|
||||||
|
|
||||||
/* some registers might be cleared on reset. restore initial values */
|
/* some registers might be cleared on reset. restore initial values */
|
||||||
ahci_restore_initial_config(host);
|
ahci_restore_initial_config(host);
|
||||||
@ -1078,8 +1092,10 @@ static int ahci_reset_controller(struct ata_host *host)
|
|||||||
|
|
||||||
/* configure PCS */
|
/* configure PCS */
|
||||||
pci_read_config_word(pdev, 0x92, &tmp16);
|
pci_read_config_word(pdev, 0x92, &tmp16);
|
||||||
tmp16 |= 0xf;
|
if ((tmp16 & hpriv->port_map) != hpriv->port_map) {
|
||||||
pci_write_config_word(pdev, 0x92, tmp16);
|
tmp16 |= hpriv->port_map;
|
||||||
|
pci_write_config_word(pdev, 0x92, tmp16);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -1480,35 +1496,31 @@ static void ahci_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
|
|||||||
static unsigned int ahci_fill_sg(struct ata_queued_cmd *qc, void *cmd_tbl)
|
static unsigned int ahci_fill_sg(struct ata_queued_cmd *qc, void *cmd_tbl)
|
||||||
{
|
{
|
||||||
struct scatterlist *sg;
|
struct scatterlist *sg;
|
||||||
struct ahci_sg *ahci_sg;
|
struct ahci_sg *ahci_sg = cmd_tbl + AHCI_CMD_TBL_HDR_SZ;
|
||||||
unsigned int n_sg = 0;
|
unsigned int si;
|
||||||
|
|
||||||
VPRINTK("ENTER\n");
|
VPRINTK("ENTER\n");
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Next, the S/G list.
|
* Next, the S/G list.
|
||||||
*/
|
*/
|
||||||
ahci_sg = cmd_tbl + AHCI_CMD_TBL_HDR_SZ;
|
for_each_sg(qc->sg, sg, qc->n_elem, si) {
|
||||||
ata_for_each_sg(sg, qc) {
|
|
||||||
dma_addr_t addr = sg_dma_address(sg);
|
dma_addr_t addr = sg_dma_address(sg);
|
||||||
u32 sg_len = sg_dma_len(sg);
|
u32 sg_len = sg_dma_len(sg);
|
||||||
|
|
||||||
ahci_sg->addr = cpu_to_le32(addr & 0xffffffff);
|
ahci_sg[si].addr = cpu_to_le32(addr & 0xffffffff);
|
||||||
ahci_sg->addr_hi = cpu_to_le32((addr >> 16) >> 16);
|
ahci_sg[si].addr_hi = cpu_to_le32((addr >> 16) >> 16);
|
||||||
ahci_sg->flags_size = cpu_to_le32(sg_len - 1);
|
ahci_sg[si].flags_size = cpu_to_le32(sg_len - 1);
|
||||||
|
|
||||||
ahci_sg++;
|
|
||||||
n_sg++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return n_sg;
|
return si;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ahci_qc_prep(struct ata_queued_cmd *qc)
|
static void ahci_qc_prep(struct ata_queued_cmd *qc)
|
||||||
{
|
{
|
||||||
struct ata_port *ap = qc->ap;
|
struct ata_port *ap = qc->ap;
|
||||||
struct ahci_port_priv *pp = ap->private_data;
|
struct ahci_port_priv *pp = ap->private_data;
|
||||||
int is_atapi = is_atapi_taskfile(&qc->tf);
|
int is_atapi = ata_is_atapi(qc->tf.protocol);
|
||||||
void *cmd_tbl;
|
void *cmd_tbl;
|
||||||
u32 opts;
|
u32 opts;
|
||||||
const u32 cmd_fis_len = 5; /* five dwords */
|
const u32 cmd_fis_len = 5; /* five dwords */
|
||||||
|
@ -26,7 +26,7 @@
|
|||||||
#include <linux/libata.h>
|
#include <linux/libata.h>
|
||||||
|
|
||||||
#define DRV_NAME "ata_generic"
|
#define DRV_NAME "ata_generic"
|
||||||
#define DRV_VERSION "0.2.13"
|
#define DRV_VERSION "0.2.15"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* A generic parallel ATA driver using libata
|
* A generic parallel ATA driver using libata
|
||||||
@ -48,27 +48,47 @@ static int generic_set_mode(struct ata_link *link, struct ata_device **unused)
|
|||||||
struct ata_port *ap = link->ap;
|
struct ata_port *ap = link->ap;
|
||||||
int dma_enabled = 0;
|
int dma_enabled = 0;
|
||||||
struct ata_device *dev;
|
struct ata_device *dev;
|
||||||
|
struct pci_dev *pdev = to_pci_dev(ap->host->dev);
|
||||||
|
|
||||||
/* Bits 5 and 6 indicate if DMA is active on master/slave */
|
/* Bits 5 and 6 indicate if DMA is active on master/slave */
|
||||||
if (ap->ioaddr.bmdma_addr)
|
if (ap->ioaddr.bmdma_addr)
|
||||||
dma_enabled = ioread8(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS);
|
dma_enabled = ioread8(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS);
|
||||||
|
|
||||||
|
if (pdev->vendor == PCI_VENDOR_ID_CENATEK)
|
||||||
|
dma_enabled = 0xFF;
|
||||||
|
|
||||||
ata_link_for_each_dev(dev, link) {
|
ata_link_for_each_dev(dev, link) {
|
||||||
if (ata_dev_enabled(dev)) {
|
if (!ata_dev_enabled(dev))
|
||||||
/* We don't really care */
|
continue;
|
||||||
dev->pio_mode = XFER_PIO_0;
|
|
||||||
dev->dma_mode = XFER_MW_DMA_0;
|
/* We don't really care */
|
||||||
/* We do need the right mode information for DMA or PIO
|
dev->pio_mode = XFER_PIO_0;
|
||||||
and this comes from the current configuration flags */
|
dev->dma_mode = XFER_MW_DMA_0;
|
||||||
if (dma_enabled & (1 << (5 + dev->devno))) {
|
/* We do need the right mode information for DMA or PIO
|
||||||
ata_id_to_dma_mode(dev, XFER_MW_DMA_0);
|
and this comes from the current configuration flags */
|
||||||
dev->flags &= ~ATA_DFLAG_PIO;
|
if (dma_enabled & (1 << (5 + dev->devno))) {
|
||||||
} else {
|
unsigned int xfer_mask = ata_id_xfermask(dev->id);
|
||||||
ata_dev_printk(dev, KERN_INFO, "configured for PIO\n");
|
const char *name;
|
||||||
dev->xfer_mode = XFER_PIO_0;
|
|
||||||
dev->xfer_shift = ATA_SHIFT_PIO;
|
if (xfer_mask & (ATA_MASK_MWDMA | ATA_MASK_UDMA))
|
||||||
dev->flags |= ATA_DFLAG_PIO;
|
name = ata_mode_string(xfer_mask);
|
||||||
|
else {
|
||||||
|
/* SWDMA perhaps? */
|
||||||
|
name = "DMA";
|
||||||
|
xfer_mask |= ata_xfer_mode2mask(XFER_MW_DMA_0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ata_dev_printk(dev, KERN_INFO, "configured for %s\n",
|
||||||
|
name);
|
||||||
|
|
||||||
|
dev->xfer_mode = ata_xfer_mask2mode(xfer_mask);
|
||||||
|
dev->xfer_shift = ata_xfer_mode2shift(dev->xfer_mode);
|
||||||
|
dev->flags &= ~ATA_DFLAG_PIO;
|
||||||
|
} else {
|
||||||
|
ata_dev_printk(dev, KERN_INFO, "configured for PIO\n");
|
||||||
|
dev->xfer_mode = XFER_PIO_0;
|
||||||
|
dev->xfer_shift = ATA_SHIFT_PIO;
|
||||||
|
dev->flags |= ATA_DFLAG_PIO;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@ -185,6 +205,7 @@ static struct pci_device_id ata_generic[] = {
|
|||||||
{ PCI_DEVICE(PCI_VENDOR_ID_HINT, PCI_DEVICE_ID_HINT_VXPROII_IDE), },
|
{ PCI_DEVICE(PCI_VENDOR_ID_HINT, PCI_DEVICE_ID_HINT_VXPROII_IDE), },
|
||||||
{ PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C561), },
|
{ PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C561), },
|
||||||
{ PCI_DEVICE(PCI_VENDOR_ID_OPTI, PCI_DEVICE_ID_OPTI_82C558), },
|
{ PCI_DEVICE(PCI_VENDOR_ID_OPTI, PCI_DEVICE_ID_OPTI_82C558), },
|
||||||
|
{ PCI_DEVICE(PCI_VENDOR_ID_CENATEK,PCI_DEVICE_ID_CENATEK_IDE), },
|
||||||
{ PCI_DEVICE(PCI_VENDOR_ID_TOSHIBA,PCI_DEVICE_ID_TOSHIBA_PICCOLO), },
|
{ PCI_DEVICE(PCI_VENDOR_ID_TOSHIBA,PCI_DEVICE_ID_TOSHIBA_PICCOLO), },
|
||||||
{ PCI_DEVICE(PCI_VENDOR_ID_TOSHIBA,PCI_DEVICE_ID_TOSHIBA_PICCOLO_1), },
|
{ PCI_DEVICE(PCI_VENDOR_ID_TOSHIBA,PCI_DEVICE_ID_TOSHIBA_PICCOLO_1), },
|
||||||
{ PCI_DEVICE(PCI_VENDOR_ID_TOSHIBA,PCI_DEVICE_ID_TOSHIBA_PICCOLO_2), },
|
{ PCI_DEVICE(PCI_VENDOR_ID_TOSHIBA,PCI_DEVICE_ID_TOSHIBA_PICCOLO_2), },
|
||||||
|
@ -101,39 +101,21 @@ enum {
|
|||||||
ICH5_PMR = 0x90, /* port mapping register */
|
ICH5_PMR = 0x90, /* port mapping register */
|
||||||
ICH5_PCS = 0x92, /* port control and status */
|
ICH5_PCS = 0x92, /* port control and status */
|
||||||
PIIX_SCC = 0x0A, /* sub-class code register */
|
PIIX_SCC = 0x0A, /* sub-class code register */
|
||||||
|
PIIX_SIDPR_BAR = 5,
|
||||||
|
PIIX_SIDPR_LEN = 16,
|
||||||
|
PIIX_SIDPR_IDX = 0,
|
||||||
|
PIIX_SIDPR_DATA = 4,
|
||||||
|
|
||||||
PIIX_FLAG_SCR = (1 << 26), /* SCR available */
|
|
||||||
PIIX_FLAG_AHCI = (1 << 27), /* AHCI possible */
|
PIIX_FLAG_AHCI = (1 << 27), /* AHCI possible */
|
||||||
PIIX_FLAG_CHECKINTR = (1 << 28), /* make sure PCI INTx enabled */
|
PIIX_FLAG_CHECKINTR = (1 << 28), /* make sure PCI INTx enabled */
|
||||||
|
PIIX_FLAG_SIDPR = (1 << 29), /* SATA idx/data pair regs */
|
||||||
|
|
||||||
PIIX_PATA_FLAGS = ATA_FLAG_SLAVE_POSS,
|
PIIX_PATA_FLAGS = ATA_FLAG_SLAVE_POSS,
|
||||||
PIIX_SATA_FLAGS = ATA_FLAG_SATA | PIIX_FLAG_CHECKINTR,
|
PIIX_SATA_FLAGS = ATA_FLAG_SATA | PIIX_FLAG_CHECKINTR,
|
||||||
|
|
||||||
/* combined mode. if set, PATA is channel 0.
|
|
||||||
* if clear, PATA is channel 1.
|
|
||||||
*/
|
|
||||||
PIIX_PORT_ENABLED = (1 << 0),
|
|
||||||
PIIX_PORT_PRESENT = (1 << 4),
|
|
||||||
|
|
||||||
PIIX_80C_PRI = (1 << 5) | (1 << 4),
|
PIIX_80C_PRI = (1 << 5) | (1 << 4),
|
||||||
PIIX_80C_SEC = (1 << 7) | (1 << 6),
|
PIIX_80C_SEC = (1 << 7) | (1 << 6),
|
||||||
|
|
||||||
/* controller IDs */
|
|
||||||
piix_pata_mwdma = 0, /* PIIX3 MWDMA only */
|
|
||||||
piix_pata_33, /* PIIX4 at 33Mhz */
|
|
||||||
ich_pata_33, /* ICH up to UDMA 33 only */
|
|
||||||
ich_pata_66, /* ICH up to 66 Mhz */
|
|
||||||
ich_pata_100, /* ICH up to UDMA 100 */
|
|
||||||
ich5_sata,
|
|
||||||
ich6_sata,
|
|
||||||
ich6_sata_ahci,
|
|
||||||
ich6m_sata_ahci,
|
|
||||||
ich8_sata_ahci,
|
|
||||||
ich8_2port_sata,
|
|
||||||
ich8m_apple_sata_ahci, /* locks up on second port enable */
|
|
||||||
tolapai_sata_ahci,
|
|
||||||
piix_pata_vmw, /* PIIX4 for VMware, spurious DMA_ERR */
|
|
||||||
|
|
||||||
/* constants for mapping table */
|
/* constants for mapping table */
|
||||||
P0 = 0, /* port 0 */
|
P0 = 0, /* port 0 */
|
||||||
P1 = 1, /* port 1 */
|
P1 = 1, /* port 1 */
|
||||||
@ -149,6 +131,24 @@ enum {
|
|||||||
PIIX_HOST_BROKEN_SUSPEND = (1 << 24),
|
PIIX_HOST_BROKEN_SUSPEND = (1 << 24),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum piix_controller_ids {
|
||||||
|
/* controller IDs */
|
||||||
|
piix_pata_mwdma, /* PIIX3 MWDMA only */
|
||||||
|
piix_pata_33, /* PIIX4 at 33Mhz */
|
||||||
|
ich_pata_33, /* ICH up to UDMA 33 only */
|
||||||
|
ich_pata_66, /* ICH up to 66 Mhz */
|
||||||
|
ich_pata_100, /* ICH up to UDMA 100 */
|
||||||
|
ich5_sata,
|
||||||
|
ich6_sata,
|
||||||
|
ich6_sata_ahci,
|
||||||
|
ich6m_sata_ahci,
|
||||||
|
ich8_sata_ahci,
|
||||||
|
ich8_2port_sata,
|
||||||
|
ich8m_apple_sata_ahci, /* locks up on second port enable */
|
||||||
|
tolapai_sata_ahci,
|
||||||
|
piix_pata_vmw, /* PIIX4 for VMware, spurious DMA_ERR */
|
||||||
|
};
|
||||||
|
|
||||||
struct piix_map_db {
|
struct piix_map_db {
|
||||||
const u32 mask;
|
const u32 mask;
|
||||||
const u16 port_enable;
|
const u16 port_enable;
|
||||||
@ -157,6 +157,7 @@ struct piix_map_db {
|
|||||||
|
|
||||||
struct piix_host_priv {
|
struct piix_host_priv {
|
||||||
const int *map;
|
const int *map;
|
||||||
|
void __iomem *sidpr;
|
||||||
};
|
};
|
||||||
|
|
||||||
static int piix_init_one(struct pci_dev *pdev,
|
static int piix_init_one(struct pci_dev *pdev,
|
||||||
@ -167,6 +168,9 @@ static void piix_set_dmamode(struct ata_port *ap, struct ata_device *adev);
|
|||||||
static void ich_set_dmamode(struct ata_port *ap, struct ata_device *adev);
|
static void ich_set_dmamode(struct ata_port *ap, struct ata_device *adev);
|
||||||
static int ich_pata_cable_detect(struct ata_port *ap);
|
static int ich_pata_cable_detect(struct ata_port *ap);
|
||||||
static u8 piix_vmw_bmdma_status(struct ata_port *ap);
|
static u8 piix_vmw_bmdma_status(struct ata_port *ap);
|
||||||
|
static int piix_sidpr_scr_read(struct ata_port *ap, unsigned int reg, u32 *val);
|
||||||
|
static int piix_sidpr_scr_write(struct ata_port *ap, unsigned int reg, u32 val);
|
||||||
|
static void piix_sidpr_error_handler(struct ata_port *ap);
|
||||||
#ifdef CONFIG_PM
|
#ifdef CONFIG_PM
|
||||||
static int piix_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg);
|
static int piix_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg);
|
||||||
static int piix_pci_device_resume(struct pci_dev *pdev);
|
static int piix_pci_device_resume(struct pci_dev *pdev);
|
||||||
@ -321,7 +325,6 @@ static const struct ata_port_operations piix_pata_ops = {
|
|||||||
.post_internal_cmd = ata_bmdma_post_internal_cmd,
|
.post_internal_cmd = ata_bmdma_post_internal_cmd,
|
||||||
.cable_detect = ata_cable_40wire,
|
.cable_detect = ata_cable_40wire,
|
||||||
|
|
||||||
.irq_handler = ata_interrupt,
|
|
||||||
.irq_clear = ata_bmdma_irq_clear,
|
.irq_clear = ata_bmdma_irq_clear,
|
||||||
.irq_on = ata_irq_on,
|
.irq_on = ata_irq_on,
|
||||||
|
|
||||||
@ -353,7 +356,6 @@ static const struct ata_port_operations ich_pata_ops = {
|
|||||||
.post_internal_cmd = ata_bmdma_post_internal_cmd,
|
.post_internal_cmd = ata_bmdma_post_internal_cmd,
|
||||||
.cable_detect = ich_pata_cable_detect,
|
.cable_detect = ich_pata_cable_detect,
|
||||||
|
|
||||||
.irq_handler = ata_interrupt,
|
|
||||||
.irq_clear = ata_bmdma_irq_clear,
|
.irq_clear = ata_bmdma_irq_clear,
|
||||||
.irq_on = ata_irq_on,
|
.irq_on = ata_irq_on,
|
||||||
|
|
||||||
@ -380,7 +382,6 @@ static const struct ata_port_operations piix_sata_ops = {
|
|||||||
.error_handler = ata_bmdma_error_handler,
|
.error_handler = ata_bmdma_error_handler,
|
||||||
.post_internal_cmd = ata_bmdma_post_internal_cmd,
|
.post_internal_cmd = ata_bmdma_post_internal_cmd,
|
||||||
|
|
||||||
.irq_handler = ata_interrupt,
|
|
||||||
.irq_clear = ata_bmdma_irq_clear,
|
.irq_clear = ata_bmdma_irq_clear,
|
||||||
.irq_on = ata_irq_on,
|
.irq_on = ata_irq_on,
|
||||||
|
|
||||||
@ -419,6 +420,35 @@ static const struct ata_port_operations piix_vmw_ops = {
|
|||||||
.port_start = ata_port_start,
|
.port_start = ata_port_start,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const struct ata_port_operations piix_sidpr_sata_ops = {
|
||||||
|
.tf_load = ata_tf_load,
|
||||||
|
.tf_read = ata_tf_read,
|
||||||
|
.check_status = ata_check_status,
|
||||||
|
.exec_command = ata_exec_command,
|
||||||
|
.dev_select = ata_std_dev_select,
|
||||||
|
|
||||||
|
.bmdma_setup = ata_bmdma_setup,
|
||||||
|
.bmdma_start = ata_bmdma_start,
|
||||||
|
.bmdma_stop = ata_bmdma_stop,
|
||||||
|
.bmdma_status = ata_bmdma_status,
|
||||||
|
.qc_prep = ata_qc_prep,
|
||||||
|
.qc_issue = ata_qc_issue_prot,
|
||||||
|
.data_xfer = ata_data_xfer,
|
||||||
|
|
||||||
|
.scr_read = piix_sidpr_scr_read,
|
||||||
|
.scr_write = piix_sidpr_scr_write,
|
||||||
|
|
||||||
|
.freeze = ata_bmdma_freeze,
|
||||||
|
.thaw = ata_bmdma_thaw,
|
||||||
|
.error_handler = piix_sidpr_error_handler,
|
||||||
|
.post_internal_cmd = ata_bmdma_post_internal_cmd,
|
||||||
|
|
||||||
|
.irq_clear = ata_bmdma_irq_clear,
|
||||||
|
.irq_on = ata_irq_on,
|
||||||
|
|
||||||
|
.port_start = ata_port_start,
|
||||||
|
};
|
||||||
|
|
||||||
static const struct piix_map_db ich5_map_db = {
|
static const struct piix_map_db ich5_map_db = {
|
||||||
.mask = 0x7,
|
.mask = 0x7,
|
||||||
.port_enable = 0x3,
|
.port_enable = 0x3,
|
||||||
@ -526,7 +556,6 @@ static const struct piix_map_db *piix_map_db_table[] = {
|
|||||||
static struct ata_port_info piix_port_info[] = {
|
static struct ata_port_info piix_port_info[] = {
|
||||||
[piix_pata_mwdma] = /* PIIX3 MWDMA only */
|
[piix_pata_mwdma] = /* PIIX3 MWDMA only */
|
||||||
{
|
{
|
||||||
.sht = &piix_sht,
|
|
||||||
.flags = PIIX_PATA_FLAGS,
|
.flags = PIIX_PATA_FLAGS,
|
||||||
.pio_mask = 0x1f, /* pio0-4 */
|
.pio_mask = 0x1f, /* pio0-4 */
|
||||||
.mwdma_mask = 0x06, /* mwdma1-2 ?? CHECK 0 should be ok but slow */
|
.mwdma_mask = 0x06, /* mwdma1-2 ?? CHECK 0 should be ok but slow */
|
||||||
@ -535,7 +564,6 @@ static struct ata_port_info piix_port_info[] = {
|
|||||||
|
|
||||||
[piix_pata_33] = /* PIIX4 at 33MHz */
|
[piix_pata_33] = /* PIIX4 at 33MHz */
|
||||||
{
|
{
|
||||||
.sht = &piix_sht,
|
|
||||||
.flags = PIIX_PATA_FLAGS,
|
.flags = PIIX_PATA_FLAGS,
|
||||||
.pio_mask = 0x1f, /* pio0-4 */
|
.pio_mask = 0x1f, /* pio0-4 */
|
||||||
.mwdma_mask = 0x06, /* mwdma1-2 ?? CHECK 0 should be ok but slow */
|
.mwdma_mask = 0x06, /* mwdma1-2 ?? CHECK 0 should be ok but slow */
|
||||||
@ -545,7 +573,6 @@ static struct ata_port_info piix_port_info[] = {
|
|||||||
|
|
||||||
[ich_pata_33] = /* ICH0 - ICH at 33Mhz*/
|
[ich_pata_33] = /* ICH0 - ICH at 33Mhz*/
|
||||||
{
|
{
|
||||||
.sht = &piix_sht,
|
|
||||||
.flags = PIIX_PATA_FLAGS,
|
.flags = PIIX_PATA_FLAGS,
|
||||||
.pio_mask = 0x1f, /* pio 0-4 */
|
.pio_mask = 0x1f, /* pio 0-4 */
|
||||||
.mwdma_mask = 0x06, /* Check: maybe 0x07 */
|
.mwdma_mask = 0x06, /* Check: maybe 0x07 */
|
||||||
@ -555,7 +582,6 @@ static struct ata_port_info piix_port_info[] = {
|
|||||||
|
|
||||||
[ich_pata_66] = /* ICH controllers up to 66MHz */
|
[ich_pata_66] = /* ICH controllers up to 66MHz */
|
||||||
{
|
{
|
||||||
.sht = &piix_sht,
|
|
||||||
.flags = PIIX_PATA_FLAGS,
|
.flags = PIIX_PATA_FLAGS,
|
||||||
.pio_mask = 0x1f, /* pio 0-4 */
|
.pio_mask = 0x1f, /* pio 0-4 */
|
||||||
.mwdma_mask = 0x06, /* MWDMA0 is broken on chip */
|
.mwdma_mask = 0x06, /* MWDMA0 is broken on chip */
|
||||||
@ -565,7 +591,6 @@ static struct ata_port_info piix_port_info[] = {
|
|||||||
|
|
||||||
[ich_pata_100] =
|
[ich_pata_100] =
|
||||||
{
|
{
|
||||||
.sht = &piix_sht,
|
|
||||||
.flags = PIIX_PATA_FLAGS | PIIX_FLAG_CHECKINTR,
|
.flags = PIIX_PATA_FLAGS | PIIX_FLAG_CHECKINTR,
|
||||||
.pio_mask = 0x1f, /* pio0-4 */
|
.pio_mask = 0x1f, /* pio0-4 */
|
||||||
.mwdma_mask = 0x06, /* mwdma1-2 */
|
.mwdma_mask = 0x06, /* mwdma1-2 */
|
||||||
@ -575,7 +600,6 @@ static struct ata_port_info piix_port_info[] = {
|
|||||||
|
|
||||||
[ich5_sata] =
|
[ich5_sata] =
|
||||||
{
|
{
|
||||||
.sht = &piix_sht,
|
|
||||||
.flags = PIIX_SATA_FLAGS,
|
.flags = PIIX_SATA_FLAGS,
|
||||||
.pio_mask = 0x1f, /* pio0-4 */
|
.pio_mask = 0x1f, /* pio0-4 */
|
||||||
.mwdma_mask = 0x07, /* mwdma0-2 */
|
.mwdma_mask = 0x07, /* mwdma0-2 */
|
||||||
@ -585,8 +609,7 @@ static struct ata_port_info piix_port_info[] = {
|
|||||||
|
|
||||||
[ich6_sata] =
|
[ich6_sata] =
|
||||||
{
|
{
|
||||||
.sht = &piix_sht,
|
.flags = PIIX_SATA_FLAGS,
|
||||||
.flags = PIIX_SATA_FLAGS | PIIX_FLAG_SCR,
|
|
||||||
.pio_mask = 0x1f, /* pio0-4 */
|
.pio_mask = 0x1f, /* pio0-4 */
|
||||||
.mwdma_mask = 0x07, /* mwdma0-2 */
|
.mwdma_mask = 0x07, /* mwdma0-2 */
|
||||||
.udma_mask = ATA_UDMA6,
|
.udma_mask = ATA_UDMA6,
|
||||||
@ -595,9 +618,7 @@ static struct ata_port_info piix_port_info[] = {
|
|||||||
|
|
||||||
[ich6_sata_ahci] =
|
[ich6_sata_ahci] =
|
||||||
{
|
{
|
||||||
.sht = &piix_sht,
|
.flags = PIIX_SATA_FLAGS | PIIX_FLAG_AHCI,
|
||||||
.flags = PIIX_SATA_FLAGS | PIIX_FLAG_SCR |
|
|
||||||
PIIX_FLAG_AHCI,
|
|
||||||
.pio_mask = 0x1f, /* pio0-4 */
|
.pio_mask = 0x1f, /* pio0-4 */
|
||||||
.mwdma_mask = 0x07, /* mwdma0-2 */
|
.mwdma_mask = 0x07, /* mwdma0-2 */
|
||||||
.udma_mask = ATA_UDMA6,
|
.udma_mask = ATA_UDMA6,
|
||||||
@ -606,9 +627,7 @@ static struct ata_port_info piix_port_info[] = {
|
|||||||
|
|
||||||
[ich6m_sata_ahci] =
|
[ich6m_sata_ahci] =
|
||||||
{
|
{
|
||||||
.sht = &piix_sht,
|
.flags = PIIX_SATA_FLAGS | PIIX_FLAG_AHCI,
|
||||||
.flags = PIIX_SATA_FLAGS | PIIX_FLAG_SCR |
|
|
||||||
PIIX_FLAG_AHCI,
|
|
||||||
.pio_mask = 0x1f, /* pio0-4 */
|
.pio_mask = 0x1f, /* pio0-4 */
|
||||||
.mwdma_mask = 0x07, /* mwdma0-2 */
|
.mwdma_mask = 0x07, /* mwdma0-2 */
|
||||||
.udma_mask = ATA_UDMA6,
|
.udma_mask = ATA_UDMA6,
|
||||||
@ -617,9 +636,8 @@ static struct ata_port_info piix_port_info[] = {
|
|||||||
|
|
||||||
[ich8_sata_ahci] =
|
[ich8_sata_ahci] =
|
||||||
{
|
{
|
||||||
.sht = &piix_sht,
|
.flags = PIIX_SATA_FLAGS | PIIX_FLAG_AHCI |
|
||||||
.flags = PIIX_SATA_FLAGS | PIIX_FLAG_SCR |
|
PIIX_FLAG_SIDPR,
|
||||||
PIIX_FLAG_AHCI,
|
|
||||||
.pio_mask = 0x1f, /* pio0-4 */
|
.pio_mask = 0x1f, /* pio0-4 */
|
||||||
.mwdma_mask = 0x07, /* mwdma0-2 */
|
.mwdma_mask = 0x07, /* mwdma0-2 */
|
||||||
.udma_mask = ATA_UDMA6,
|
.udma_mask = ATA_UDMA6,
|
||||||
@ -628,9 +646,8 @@ static struct ata_port_info piix_port_info[] = {
|
|||||||
|
|
||||||
[ich8_2port_sata] =
|
[ich8_2port_sata] =
|
||||||
{
|
{
|
||||||
.sht = &piix_sht,
|
.flags = PIIX_SATA_FLAGS | PIIX_FLAG_AHCI |
|
||||||
.flags = PIIX_SATA_FLAGS | PIIX_FLAG_SCR |
|
PIIX_FLAG_SIDPR,
|
||||||
PIIX_FLAG_AHCI,
|
|
||||||
.pio_mask = 0x1f, /* pio0-4 */
|
.pio_mask = 0x1f, /* pio0-4 */
|
||||||
.mwdma_mask = 0x07, /* mwdma0-2 */
|
.mwdma_mask = 0x07, /* mwdma0-2 */
|
||||||
.udma_mask = ATA_UDMA6,
|
.udma_mask = ATA_UDMA6,
|
||||||
@ -639,9 +656,7 @@ static struct ata_port_info piix_port_info[] = {
|
|||||||
|
|
||||||
[tolapai_sata_ahci] =
|
[tolapai_sata_ahci] =
|
||||||
{
|
{
|
||||||
.sht = &piix_sht,
|
.flags = PIIX_SATA_FLAGS | PIIX_FLAG_AHCI,
|
||||||
.flags = PIIX_SATA_FLAGS | PIIX_FLAG_SCR |
|
|
||||||
PIIX_FLAG_AHCI,
|
|
||||||
.pio_mask = 0x1f, /* pio0-4 */
|
.pio_mask = 0x1f, /* pio0-4 */
|
||||||
.mwdma_mask = 0x07, /* mwdma0-2 */
|
.mwdma_mask = 0x07, /* mwdma0-2 */
|
||||||
.udma_mask = ATA_UDMA6,
|
.udma_mask = ATA_UDMA6,
|
||||||
@ -650,9 +665,8 @@ static struct ata_port_info piix_port_info[] = {
|
|||||||
|
|
||||||
[ich8m_apple_sata_ahci] =
|
[ich8m_apple_sata_ahci] =
|
||||||
{
|
{
|
||||||
.sht = &piix_sht,
|
.flags = PIIX_SATA_FLAGS | PIIX_FLAG_AHCI |
|
||||||
.flags = PIIX_SATA_FLAGS | PIIX_FLAG_SCR |
|
PIIX_FLAG_SIDPR,
|
||||||
PIIX_FLAG_AHCI,
|
|
||||||
.pio_mask = 0x1f, /* pio0-4 */
|
.pio_mask = 0x1f, /* pio0-4 */
|
||||||
.mwdma_mask = 0x07, /* mwdma0-2 */
|
.mwdma_mask = 0x07, /* mwdma0-2 */
|
||||||
.udma_mask = ATA_UDMA6,
|
.udma_mask = ATA_UDMA6,
|
||||||
@ -1001,6 +1015,180 @@ static void ich_set_dmamode(struct ata_port *ap, struct ata_device *adev)
|
|||||||
do_pata_set_dmamode(ap, adev, 1);
|
do_pata_set_dmamode(ap, adev, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Serial ATA Index/Data Pair Superset Registers access
|
||||||
|
*
|
||||||
|
* Beginning from ICH8, there's a sane way to access SCRs using index
|
||||||
|
* and data register pair located at BAR5. This creates an
|
||||||
|
* interesting problem of mapping two SCRs to one port.
|
||||||
|
*
|
||||||
|
* Although they have separate SCRs, the master and slave aren't
|
||||||
|
* independent enough to be treated as separate links - e.g. softreset
|
||||||
|
* resets both. Also, there's no protocol defined for hard resetting
|
||||||
|
* singled device sharing the virtual port (no defined way to acquire
|
||||||
|
* device signature). This is worked around by merging the SCR values
|
||||||
|
* into one sensible value and requesting follow-up SRST after
|
||||||
|
* hardreset.
|
||||||
|
*
|
||||||
|
* SCR merging is perfomed in nibbles which is the unit contents in
|
||||||
|
* SCRs are organized. If two values are equal, the value is used.
|
||||||
|
* When they differ, merge table which lists precedence of possible
|
||||||
|
* values is consulted and the first match or the last entry when
|
||||||
|
* nothing matches is used. When there's no merge table for the
|
||||||
|
* specific nibble, value from the first port is used.
|
||||||
|
*/
|
||||||
|
static const int piix_sidx_map[] = {
|
||||||
|
[SCR_STATUS] = 0,
|
||||||
|
[SCR_ERROR] = 2,
|
||||||
|
[SCR_CONTROL] = 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
static void piix_sidpr_sel(struct ata_device *dev, unsigned int reg)
|
||||||
|
{
|
||||||
|
struct ata_port *ap = dev->link->ap;
|
||||||
|
struct piix_host_priv *hpriv = ap->host->private_data;
|
||||||
|
|
||||||
|
iowrite32(((ap->port_no * 2 + dev->devno) << 8) | piix_sidx_map[reg],
|
||||||
|
hpriv->sidpr + PIIX_SIDPR_IDX);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int piix_sidpr_read(struct ata_device *dev, unsigned int reg)
|
||||||
|
{
|
||||||
|
struct piix_host_priv *hpriv = dev->link->ap->host->private_data;
|
||||||
|
|
||||||
|
piix_sidpr_sel(dev, reg);
|
||||||
|
return ioread32(hpriv->sidpr + PIIX_SIDPR_DATA);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void piix_sidpr_write(struct ata_device *dev, unsigned int reg, u32 val)
|
||||||
|
{
|
||||||
|
struct piix_host_priv *hpriv = dev->link->ap->host->private_data;
|
||||||
|
|
||||||
|
piix_sidpr_sel(dev, reg);
|
||||||
|
iowrite32(val, hpriv->sidpr + PIIX_SIDPR_DATA);
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 piix_merge_scr(u32 val0, u32 val1, const int * const *merge_tbl)
|
||||||
|
{
|
||||||
|
u32 val = 0;
|
||||||
|
int i, mi;
|
||||||
|
|
||||||
|
for (i = 0, mi = 0; i < 32 / 4; i++) {
|
||||||
|
u8 c0 = (val0 >> (i * 4)) & 0xf;
|
||||||
|
u8 c1 = (val1 >> (i * 4)) & 0xf;
|
||||||
|
u8 merged = c0;
|
||||||
|
const int *cur;
|
||||||
|
|
||||||
|
/* if no merge preference, assume the first value */
|
||||||
|
cur = merge_tbl[mi];
|
||||||
|
if (!cur)
|
||||||
|
goto done;
|
||||||
|
mi++;
|
||||||
|
|
||||||
|
/* if two values equal, use it */
|
||||||
|
if (c0 == c1)
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
/* choose the first match or the last from the merge table */
|
||||||
|
while (*cur != -1) {
|
||||||
|
if (c0 == *cur || c1 == *cur)
|
||||||
|
break;
|
||||||
|
cur++;
|
||||||
|
}
|
||||||
|
if (*cur == -1)
|
||||||
|
cur--;
|
||||||
|
merged = *cur;
|
||||||
|
done:
|
||||||
|
val |= merged << (i * 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int piix_sidpr_scr_read(struct ata_port *ap, unsigned int reg, u32 *val)
|
||||||
|
{
|
||||||
|
const int * const sstatus_merge_tbl[] = {
|
||||||
|
/* DET */ (const int []){ 1, 3, 0, 4, 3, -1 },
|
||||||
|
/* SPD */ (const int []){ 2, 1, 0, -1 },
|
||||||
|
/* IPM */ (const int []){ 6, 2, 1, 0, -1 },
|
||||||
|
NULL,
|
||||||
|
};
|
||||||
|
const int * const scontrol_merge_tbl[] = {
|
||||||
|
/* DET */ (const int []){ 1, 0, 4, 0, -1 },
|
||||||
|
/* SPD */ (const int []){ 0, 2, 1, 0, -1 },
|
||||||
|
/* IPM */ (const int []){ 0, 1, 2, 3, 0, -1 },
|
||||||
|
NULL,
|
||||||
|
};
|
||||||
|
u32 v0, v1;
|
||||||
|
|
||||||
|
if (reg >= ARRAY_SIZE(piix_sidx_map))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (!(ap->flags & ATA_FLAG_SLAVE_POSS)) {
|
||||||
|
*val = piix_sidpr_read(&ap->link.device[0], reg);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
v0 = piix_sidpr_read(&ap->link.device[0], reg);
|
||||||
|
v1 = piix_sidpr_read(&ap->link.device[1], reg);
|
||||||
|
|
||||||
|
switch (reg) {
|
||||||
|
case SCR_STATUS:
|
||||||
|
*val = piix_merge_scr(v0, v1, sstatus_merge_tbl);
|
||||||
|
break;
|
||||||
|
case SCR_ERROR:
|
||||||
|
*val = v0 | v1;
|
||||||
|
break;
|
||||||
|
case SCR_CONTROL:
|
||||||
|
*val = piix_merge_scr(v0, v1, scontrol_merge_tbl);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int piix_sidpr_scr_write(struct ata_port *ap, unsigned int reg, u32 val)
|
||||||
|
{
|
||||||
|
if (reg >= ARRAY_SIZE(piix_sidx_map))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
piix_sidpr_write(&ap->link.device[0], reg, val);
|
||||||
|
|
||||||
|
if (ap->flags & ATA_FLAG_SLAVE_POSS)
|
||||||
|
piix_sidpr_write(&ap->link.device[1], reg, val);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int piix_sidpr_hardreset(struct ata_link *link, unsigned int *class,
|
||||||
|
unsigned long deadline)
|
||||||
|
{
|
||||||
|
const unsigned long *timing = sata_ehc_deb_timing(&link->eh_context);
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
/* do hardreset */
|
||||||
|
rc = sata_link_hardreset(link, timing, deadline);
|
||||||
|
if (rc) {
|
||||||
|
ata_link_printk(link, KERN_ERR,
|
||||||
|
"COMRESET failed (errno=%d)\n", rc);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TODO: phy layer with polling, timeouts, etc. */
|
||||||
|
if (ata_link_offline(link)) {
|
||||||
|
*class = ATA_DEV_NONE;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -EAGAIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void piix_sidpr_error_handler(struct ata_port *ap)
|
||||||
|
{
|
||||||
|
ata_bmdma_drive_eh(ap, ata_std_prereset, ata_std_softreset,
|
||||||
|
piix_sidpr_hardreset, ata_std_postreset);
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_PM
|
#ifdef CONFIG_PM
|
||||||
static int piix_broken_suspend(void)
|
static int piix_broken_suspend(void)
|
||||||
{
|
{
|
||||||
@ -1033,6 +1221,13 @@ static int piix_broken_suspend(void)
|
|||||||
DMI_MATCH(DMI_PRODUCT_NAME, "TECRA M5"),
|
DMI_MATCH(DMI_PRODUCT_NAME, "TECRA M5"),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
.ident = "TECRA M6",
|
||||||
|
.matches = {
|
||||||
|
DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
|
||||||
|
DMI_MATCH(DMI_PRODUCT_NAME, "TECRA M6"),
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
.ident = "TECRA M7",
|
.ident = "TECRA M7",
|
||||||
.matches = {
|
.matches = {
|
||||||
@ -1047,6 +1242,13 @@ static int piix_broken_suspend(void)
|
|||||||
DMI_MATCH(DMI_PRODUCT_NAME, "TECRA A8"),
|
DMI_MATCH(DMI_PRODUCT_NAME, "TECRA A8"),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
.ident = "Satellite R20",
|
||||||
|
.matches = {
|
||||||
|
DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
|
||||||
|
DMI_MATCH(DMI_PRODUCT_NAME, "Satellite R20"),
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
.ident = "Satellite R25",
|
.ident = "Satellite R25",
|
||||||
.matches = {
|
.matches = {
|
||||||
@ -1253,10 +1455,10 @@ static int __devinit piix_check_450nx_errata(struct pci_dev *ata_dev)
|
|||||||
return no_piix_dma;
|
return no_piix_dma;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __devinit piix_init_pcs(struct pci_dev *pdev,
|
static void __devinit piix_init_pcs(struct ata_host *host,
|
||||||
struct ata_port_info *pinfo,
|
|
||||||
const struct piix_map_db *map_db)
|
const struct piix_map_db *map_db)
|
||||||
{
|
{
|
||||||
|
struct pci_dev *pdev = to_pci_dev(host->dev);
|
||||||
u16 pcs, new_pcs;
|
u16 pcs, new_pcs;
|
||||||
|
|
||||||
pci_read_config_word(pdev, ICH5_PCS, &pcs);
|
pci_read_config_word(pdev, ICH5_PCS, &pcs);
|
||||||
@ -1270,11 +1472,10 @@ static void __devinit piix_init_pcs(struct pci_dev *pdev,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __devinit piix_init_sata_map(struct pci_dev *pdev,
|
static const int *__devinit piix_init_sata_map(struct pci_dev *pdev,
|
||||||
struct ata_port_info *pinfo,
|
struct ata_port_info *pinfo,
|
||||||
const struct piix_map_db *map_db)
|
const struct piix_map_db *map_db)
|
||||||
{
|
{
|
||||||
struct piix_host_priv *hpriv = pinfo[0].private_data;
|
|
||||||
const int *map;
|
const int *map;
|
||||||
int i, invalid_map = 0;
|
int i, invalid_map = 0;
|
||||||
u8 map_value;
|
u8 map_value;
|
||||||
@ -1298,7 +1499,6 @@ static void __devinit piix_init_sata_map(struct pci_dev *pdev,
|
|||||||
case IDE:
|
case IDE:
|
||||||
WARN_ON((i & 1) || map[i + 1] != IDE);
|
WARN_ON((i & 1) || map[i + 1] != IDE);
|
||||||
pinfo[i / 2] = piix_port_info[ich_pata_100];
|
pinfo[i / 2] = piix_port_info[ich_pata_100];
|
||||||
pinfo[i / 2].private_data = hpriv;
|
|
||||||
i++;
|
i++;
|
||||||
printk(" IDE IDE");
|
printk(" IDE IDE");
|
||||||
break;
|
break;
|
||||||
@ -1316,7 +1516,33 @@ static void __devinit piix_init_sata_map(struct pci_dev *pdev,
|
|||||||
dev_printk(KERN_ERR, &pdev->dev,
|
dev_printk(KERN_ERR, &pdev->dev,
|
||||||
"invalid MAP value %u\n", map_value);
|
"invalid MAP value %u\n", map_value);
|
||||||
|
|
||||||
hpriv->map = map;
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __devinit piix_init_sidpr(struct ata_host *host)
|
||||||
|
{
|
||||||
|
struct pci_dev *pdev = to_pci_dev(host->dev);
|
||||||
|
struct piix_host_priv *hpriv = host->private_data;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* check for availability */
|
||||||
|
for (i = 0; i < 4; i++)
|
||||||
|
if (hpriv->map[i] == IDE)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!(host->ports[0]->flags & PIIX_FLAG_SIDPR))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (pci_resource_start(pdev, PIIX_SIDPR_BAR) == 0 ||
|
||||||
|
pci_resource_len(pdev, PIIX_SIDPR_BAR) != PIIX_SIDPR_LEN)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (pcim_iomap_regions(pdev, 1 << PIIX_SIDPR_BAR, DRV_NAME))
|
||||||
|
return;
|
||||||
|
|
||||||
|
hpriv->sidpr = pcim_iomap_table(pdev)[PIIX_SIDPR_BAR];
|
||||||
|
host->ports[0]->ops = &piix_sidpr_sata_ops;
|
||||||
|
host->ports[1]->ops = &piix_sidpr_sata_ops;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void piix_iocfg_bit18_quirk(struct pci_dev *pdev)
|
static void piix_iocfg_bit18_quirk(struct pci_dev *pdev)
|
||||||
@ -1375,8 +1601,10 @@ static int piix_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
|
|||||||
struct device *dev = &pdev->dev;
|
struct device *dev = &pdev->dev;
|
||||||
struct ata_port_info port_info[2];
|
struct ata_port_info port_info[2];
|
||||||
const struct ata_port_info *ppi[] = { &port_info[0], &port_info[1] };
|
const struct ata_port_info *ppi[] = { &port_info[0], &port_info[1] };
|
||||||
struct piix_host_priv *hpriv;
|
|
||||||
unsigned long port_flags;
|
unsigned long port_flags;
|
||||||
|
struct ata_host *host;
|
||||||
|
struct piix_host_priv *hpriv;
|
||||||
|
int rc;
|
||||||
|
|
||||||
if (!printed_version++)
|
if (!printed_version++)
|
||||||
dev_printk(KERN_DEBUG, &pdev->dev,
|
dev_printk(KERN_DEBUG, &pdev->dev,
|
||||||
@ -1386,17 +1614,31 @@ static int piix_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
|
|||||||
if (!in_module_init)
|
if (!in_module_init)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
|
port_info[0] = piix_port_info[ent->driver_data];
|
||||||
|
port_info[1] = piix_port_info[ent->driver_data];
|
||||||
|
|
||||||
|
port_flags = port_info[0].flags;
|
||||||
|
|
||||||
|
/* enable device and prepare host */
|
||||||
|
rc = pcim_enable_device(pdev);
|
||||||
|
if (rc)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
/* SATA map init can change port_info, do it before prepping host */
|
||||||
hpriv = devm_kzalloc(dev, sizeof(*hpriv), GFP_KERNEL);
|
hpriv = devm_kzalloc(dev, sizeof(*hpriv), GFP_KERNEL);
|
||||||
if (!hpriv)
|
if (!hpriv)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
port_info[0] = piix_port_info[ent->driver_data];
|
if (port_flags & ATA_FLAG_SATA)
|
||||||
port_info[1] = piix_port_info[ent->driver_data];
|
hpriv->map = piix_init_sata_map(pdev, port_info,
|
||||||
port_info[0].private_data = hpriv;
|
piix_map_db_table[ent->driver_data]);
|
||||||
port_info[1].private_data = hpriv;
|
|
||||||
|
|
||||||
port_flags = port_info[0].flags;
|
rc = ata_pci_prepare_sff_host(pdev, ppi, &host);
|
||||||
|
if (rc)
|
||||||
|
return rc;
|
||||||
|
host->private_data = hpriv;
|
||||||
|
|
||||||
|
/* initialize controller */
|
||||||
if (port_flags & PIIX_FLAG_AHCI) {
|
if (port_flags & PIIX_FLAG_AHCI) {
|
||||||
u8 tmp;
|
u8 tmp;
|
||||||
pci_read_config_byte(pdev, PIIX_SCC, &tmp);
|
pci_read_config_byte(pdev, PIIX_SCC, &tmp);
|
||||||
@ -1407,12 +1649,9 @@ static int piix_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Initialize SATA map */
|
|
||||||
if (port_flags & ATA_FLAG_SATA) {
|
if (port_flags & ATA_FLAG_SATA) {
|
||||||
piix_init_sata_map(pdev, port_info,
|
piix_init_pcs(host, piix_map_db_table[ent->driver_data]);
|
||||||
piix_map_db_table[ent->driver_data]);
|
piix_init_sidpr(host);
|
||||||
piix_init_pcs(pdev, port_info,
|
|
||||||
piix_map_db_table[ent->driver_data]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* apply IOCFG bit18 quirk */
|
/* apply IOCFG bit18 quirk */
|
||||||
@ -1431,12 +1670,14 @@ static int piix_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
|
|||||||
/* This writes into the master table but it does not
|
/* This writes into the master table but it does not
|
||||||
really matter for this errata as we will apply it to
|
really matter for this errata as we will apply it to
|
||||||
all the PIIX devices on the board */
|
all the PIIX devices on the board */
|
||||||
port_info[0].mwdma_mask = 0;
|
host->ports[0]->mwdma_mask = 0;
|
||||||
port_info[0].udma_mask = 0;
|
host->ports[0]->udma_mask = 0;
|
||||||
port_info[1].mwdma_mask = 0;
|
host->ports[1]->mwdma_mask = 0;
|
||||||
port_info[1].udma_mask = 0;
|
host->ports[1]->udma_mask = 0;
|
||||||
}
|
}
|
||||||
return ata_pci_init_one(pdev, ppi);
|
|
||||||
|
pci_set_master(pdev);
|
||||||
|
return ata_pci_activate_sff_host(host, ata_interrupt, &piix_sht);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __init piix_init(void)
|
static int __init piix_init(void)
|
||||||
|
@ -441,41 +441,78 @@ static int ata_dev_get_GTF(struct ata_device *dev, struct ata_acpi_gtf **gtf)
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ata_acpi_gtm_xfermode - determine xfermode from GTM parameter
|
||||||
|
* @dev: target device
|
||||||
|
* @gtm: GTM parameter to use
|
||||||
|
*
|
||||||
|
* Determine xfermask for @dev from @gtm.
|
||||||
|
*
|
||||||
|
* LOCKING:
|
||||||
|
* None.
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* Determined xfermask.
|
||||||
|
*/
|
||||||
|
unsigned long ata_acpi_gtm_xfermask(struct ata_device *dev,
|
||||||
|
const struct ata_acpi_gtm *gtm)
|
||||||
|
{
|
||||||
|
unsigned long xfer_mask = 0;
|
||||||
|
unsigned int type;
|
||||||
|
int unit;
|
||||||
|
u8 mode;
|
||||||
|
|
||||||
|
/* we always use the 0 slot for crap hardware */
|
||||||
|
unit = dev->devno;
|
||||||
|
if (!(gtm->flags & 0x10))
|
||||||
|
unit = 0;
|
||||||
|
|
||||||
|
/* PIO */
|
||||||
|
mode = ata_timing_cycle2mode(ATA_SHIFT_PIO, gtm->drive[unit].pio);
|
||||||
|
xfer_mask |= ata_xfer_mode2mask(mode);
|
||||||
|
|
||||||
|
/* See if we have MWDMA or UDMA data. We don't bother with
|
||||||
|
* MWDMA if UDMA is available as this means the BIOS set UDMA
|
||||||
|
* and our error changedown if it works is UDMA to PIO anyway.
|
||||||
|
*/
|
||||||
|
if (!(gtm->flags & (1 << (2 * unit))))
|
||||||
|
type = ATA_SHIFT_MWDMA;
|
||||||
|
else
|
||||||
|
type = ATA_SHIFT_UDMA;
|
||||||
|
|
||||||
|
mode = ata_timing_cycle2mode(type, gtm->drive[unit].dma);
|
||||||
|
xfer_mask |= ata_xfer_mode2mask(mode);
|
||||||
|
|
||||||
|
return xfer_mask;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(ata_acpi_gtm_xfermask);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ata_acpi_cbl_80wire - Check for 80 wire cable
|
* ata_acpi_cbl_80wire - Check for 80 wire cable
|
||||||
* @ap: Port to check
|
* @ap: Port to check
|
||||||
|
* @gtm: GTM data to use
|
||||||
*
|
*
|
||||||
* Return 1 if the ACPI mode data for this port indicates the BIOS selected
|
* Return 1 if the @gtm indicates the BIOS selected an 80wire mode.
|
||||||
* an 80wire mode.
|
|
||||||
*/
|
*/
|
||||||
|
int ata_acpi_cbl_80wire(struct ata_port *ap, const struct ata_acpi_gtm *gtm)
|
||||||
int ata_acpi_cbl_80wire(struct ata_port *ap)
|
|
||||||
{
|
{
|
||||||
const struct ata_acpi_gtm *gtm = ata_acpi_init_gtm(ap);
|
struct ata_device *dev;
|
||||||
int valid = 0;
|
|
||||||
|
|
||||||
if (!gtm)
|
ata_link_for_each_dev(dev, &ap->link) {
|
||||||
return 0;
|
unsigned long xfer_mask, udma_mask;
|
||||||
|
|
||||||
/* Split timing, DMA enabled */
|
if (!ata_dev_enabled(dev))
|
||||||
if ((gtm->flags & 0x11) == 0x11 && gtm->drive[0].dma < 55)
|
continue;
|
||||||
valid |= 1;
|
|
||||||
if ((gtm->flags & 0x14) == 0x14 && gtm->drive[1].dma < 55)
|
xfer_mask = ata_acpi_gtm_xfermask(dev, gtm);
|
||||||
valid |= 2;
|
ata_unpack_xfermask(xfer_mask, NULL, NULL, &udma_mask);
|
||||||
/* Shared timing, DMA enabled */
|
|
||||||
if ((gtm->flags & 0x11) == 0x01 && gtm->drive[0].dma < 55)
|
if (udma_mask & ~ATA_UDMA_MASK_40C)
|
||||||
valid |= 1;
|
return 1;
|
||||||
if ((gtm->flags & 0x14) == 0x04 && gtm->drive[0].dma < 55)
|
}
|
||||||
valid |= 2;
|
|
||||||
|
|
||||||
/* Drive check */
|
|
||||||
if ((valid & 1) && ata_dev_enabled(&ap->link.device[0]))
|
|
||||||
return 1;
|
|
||||||
if ((valid & 2) && ata_dev_enabled(&ap->link.device[1]))
|
|
||||||
return 1;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPORT_SYMBOL_GPL(ata_acpi_cbl_80wire);
|
EXPORT_SYMBOL_GPL(ata_acpi_cbl_80wire);
|
||||||
|
|
||||||
static void ata_acpi_gtf_to_tf(struct ata_device *dev,
|
static void ata_acpi_gtf_to_tf(struct ata_device *dev,
|
||||||
@ -775,6 +812,36 @@ void ata_acpi_on_resume(struct ata_port *ap)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ata_acpi_set_state - set the port power state
|
||||||
|
* @ap: target ATA port
|
||||||
|
* @state: state, on/off
|
||||||
|
*
|
||||||
|
* This function executes the _PS0/_PS3 ACPI method to set the power state.
|
||||||
|
* ACPI spec requires _PS0 when IDE power on and _PS3 when power off
|
||||||
|
*/
|
||||||
|
void ata_acpi_set_state(struct ata_port *ap, pm_message_t state)
|
||||||
|
{
|
||||||
|
struct ata_device *dev;
|
||||||
|
|
||||||
|
if (!ap->acpi_handle || (ap->flags & ATA_FLAG_ACPI_SATA))
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* channel first and then drives for power on and vica versa
|
||||||
|
for power off */
|
||||||
|
if (state.event == PM_EVENT_ON)
|
||||||
|
acpi_bus_set_power(ap->acpi_handle, ACPI_STATE_D0);
|
||||||
|
|
||||||
|
ata_link_for_each_dev(dev, &ap->link) {
|
||||||
|
if (dev->acpi_handle && ata_dev_enabled(dev))
|
||||||
|
acpi_bus_set_power(dev->acpi_handle,
|
||||||
|
state.event == PM_EVENT_ON ?
|
||||||
|
ACPI_STATE_D0 : ACPI_STATE_D3);
|
||||||
|
}
|
||||||
|
if (state.event != PM_EVENT_ON)
|
||||||
|
acpi_bus_set_power(ap->acpi_handle, ACPI_STATE_D3);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ata_acpi_on_devcfg - ATA ACPI hook called on device donfiguration
|
* ata_acpi_on_devcfg - ATA ACPI hook called on device donfiguration
|
||||||
* @dev: target ATA device
|
* @dev: target ATA device
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -46,9 +46,26 @@
|
|||||||
#include "libata.h"
|
#include "libata.h"
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
|
/* speed down verdicts */
|
||||||
ATA_EH_SPDN_NCQ_OFF = (1 << 0),
|
ATA_EH_SPDN_NCQ_OFF = (1 << 0),
|
||||||
ATA_EH_SPDN_SPEED_DOWN = (1 << 1),
|
ATA_EH_SPDN_SPEED_DOWN = (1 << 1),
|
||||||
ATA_EH_SPDN_FALLBACK_TO_PIO = (1 << 2),
|
ATA_EH_SPDN_FALLBACK_TO_PIO = (1 << 2),
|
||||||
|
ATA_EH_SPDN_KEEP_ERRORS = (1 << 3),
|
||||||
|
|
||||||
|
/* error flags */
|
||||||
|
ATA_EFLAG_IS_IO = (1 << 0),
|
||||||
|
ATA_EFLAG_DUBIOUS_XFER = (1 << 1),
|
||||||
|
|
||||||
|
/* error categories */
|
||||||
|
ATA_ECAT_NONE = 0,
|
||||||
|
ATA_ECAT_ATA_BUS = 1,
|
||||||
|
ATA_ECAT_TOUT_HSM = 2,
|
||||||
|
ATA_ECAT_UNK_DEV = 3,
|
||||||
|
ATA_ECAT_DUBIOUS_NONE = 4,
|
||||||
|
ATA_ECAT_DUBIOUS_ATA_BUS = 5,
|
||||||
|
ATA_ECAT_DUBIOUS_TOUT_HSM = 6,
|
||||||
|
ATA_ECAT_DUBIOUS_UNK_DEV = 7,
|
||||||
|
ATA_ECAT_NR = 8,
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Waiting in ->prereset can never be reliable. It's sometimes nice
|
/* Waiting in ->prereset can never be reliable. It's sometimes nice
|
||||||
@ -213,12 +230,13 @@ void ata_port_pbar_desc(struct ata_port *ap, int bar, ssize_t offset,
|
|||||||
if (offset < 0)
|
if (offset < 0)
|
||||||
ata_port_desc(ap, "%s %s%llu@0x%llx", name, type, len, start);
|
ata_port_desc(ap, "%s %s%llu@0x%llx", name, type, len, start);
|
||||||
else
|
else
|
||||||
ata_port_desc(ap, "%s 0x%llx", name, start + offset);
|
ata_port_desc(ap, "%s 0x%llx", name,
|
||||||
|
start + (unsigned long long)offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* CONFIG_PCI */
|
#endif /* CONFIG_PCI */
|
||||||
|
|
||||||
static void ata_ering_record(struct ata_ering *ering, int is_io,
|
static void ata_ering_record(struct ata_ering *ering, unsigned int eflags,
|
||||||
unsigned int err_mask)
|
unsigned int err_mask)
|
||||||
{
|
{
|
||||||
struct ata_ering_entry *ent;
|
struct ata_ering_entry *ent;
|
||||||
@ -229,11 +247,20 @@ static void ata_ering_record(struct ata_ering *ering, int is_io,
|
|||||||
ering->cursor %= ATA_ERING_SIZE;
|
ering->cursor %= ATA_ERING_SIZE;
|
||||||
|
|
||||||
ent = &ering->ring[ering->cursor];
|
ent = &ering->ring[ering->cursor];
|
||||||
ent->is_io = is_io;
|
ent->eflags = eflags;
|
||||||
ent->err_mask = err_mask;
|
ent->err_mask = err_mask;
|
||||||
ent->timestamp = get_jiffies_64();
|
ent->timestamp = get_jiffies_64();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct ata_ering_entry *ata_ering_top(struct ata_ering *ering)
|
||||||
|
{
|
||||||
|
struct ata_ering_entry *ent = &ering->ring[ering->cursor];
|
||||||
|
|
||||||
|
if (ent->err_mask)
|
||||||
|
return ent;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
static void ata_ering_clear(struct ata_ering *ering)
|
static void ata_ering_clear(struct ata_ering *ering)
|
||||||
{
|
{
|
||||||
memset(ering, 0, sizeof(*ering));
|
memset(ering, 0, sizeof(*ering));
|
||||||
@ -445,9 +472,20 @@ void ata_scsi_error(struct Scsi_Host *host)
|
|||||||
spin_lock_irqsave(ap->lock, flags);
|
spin_lock_irqsave(ap->lock, flags);
|
||||||
|
|
||||||
__ata_port_for_each_link(link, ap) {
|
__ata_port_for_each_link(link, ap) {
|
||||||
|
struct ata_eh_context *ehc = &link->eh_context;
|
||||||
|
struct ata_device *dev;
|
||||||
|
|
||||||
memset(&link->eh_context, 0, sizeof(link->eh_context));
|
memset(&link->eh_context, 0, sizeof(link->eh_context));
|
||||||
link->eh_context.i = link->eh_info;
|
link->eh_context.i = link->eh_info;
|
||||||
memset(&link->eh_info, 0, sizeof(link->eh_info));
|
memset(&link->eh_info, 0, sizeof(link->eh_info));
|
||||||
|
|
||||||
|
ata_link_for_each_dev(dev, link) {
|
||||||
|
int devno = dev->devno;
|
||||||
|
|
||||||
|
ehc->saved_xfer_mode[devno] = dev->xfer_mode;
|
||||||
|
if (ata_ncq_enabled(dev))
|
||||||
|
ehc->saved_ncq_enabled |= 1 << devno;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ap->pflags |= ATA_PFLAG_EH_IN_PROGRESS;
|
ap->pflags |= ATA_PFLAG_EH_IN_PROGRESS;
|
||||||
@ -1260,10 +1298,10 @@ static unsigned int atapi_eh_request_sense(struct ata_queued_cmd *qc)
|
|||||||
|
|
||||||
/* is it pointless to prefer PIO for "safety reasons"? */
|
/* is it pointless to prefer PIO for "safety reasons"? */
|
||||||
if (ap->flags & ATA_FLAG_PIO_DMA) {
|
if (ap->flags & ATA_FLAG_PIO_DMA) {
|
||||||
tf.protocol = ATA_PROT_ATAPI_DMA;
|
tf.protocol = ATAPI_PROT_DMA;
|
||||||
tf.feature |= ATAPI_PKT_DMA;
|
tf.feature |= ATAPI_PKT_DMA;
|
||||||
} else {
|
} else {
|
||||||
tf.protocol = ATA_PROT_ATAPI;
|
tf.protocol = ATAPI_PROT_PIO;
|
||||||
tf.lbam = SCSI_SENSE_BUFFERSIZE;
|
tf.lbam = SCSI_SENSE_BUFFERSIZE;
|
||||||
tf.lbah = 0;
|
tf.lbah = 0;
|
||||||
}
|
}
|
||||||
@ -1451,20 +1489,29 @@ static unsigned int ata_eh_analyze_tf(struct ata_queued_cmd *qc,
|
|||||||
return action;
|
return action;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ata_eh_categorize_error(int is_io, unsigned int err_mask)
|
static int ata_eh_categorize_error(unsigned int eflags, unsigned int err_mask,
|
||||||
|
int *xfer_ok)
|
||||||
{
|
{
|
||||||
|
int base = 0;
|
||||||
|
|
||||||
|
if (!(eflags & ATA_EFLAG_DUBIOUS_XFER))
|
||||||
|
*xfer_ok = 1;
|
||||||
|
|
||||||
|
if (!*xfer_ok)
|
||||||
|
base = ATA_ECAT_DUBIOUS_NONE;
|
||||||
|
|
||||||
if (err_mask & AC_ERR_ATA_BUS)
|
if (err_mask & AC_ERR_ATA_BUS)
|
||||||
return 1;
|
return base + ATA_ECAT_ATA_BUS;
|
||||||
|
|
||||||
if (err_mask & AC_ERR_TIMEOUT)
|
if (err_mask & AC_ERR_TIMEOUT)
|
||||||
return 2;
|
return base + ATA_ECAT_TOUT_HSM;
|
||||||
|
|
||||||
if (is_io) {
|
if (eflags & ATA_EFLAG_IS_IO) {
|
||||||
if (err_mask & AC_ERR_HSM)
|
if (err_mask & AC_ERR_HSM)
|
||||||
return 2;
|
return base + ATA_ECAT_TOUT_HSM;
|
||||||
if ((err_mask &
|
if ((err_mask &
|
||||||
(AC_ERR_DEV|AC_ERR_MEDIA|AC_ERR_INVALID)) == AC_ERR_DEV)
|
(AC_ERR_DEV|AC_ERR_MEDIA|AC_ERR_INVALID)) == AC_ERR_DEV)
|
||||||
return 3;
|
return base + ATA_ECAT_UNK_DEV;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -1472,18 +1519,22 @@ static int ata_eh_categorize_error(int is_io, unsigned int err_mask)
|
|||||||
|
|
||||||
struct speed_down_verdict_arg {
|
struct speed_down_verdict_arg {
|
||||||
u64 since;
|
u64 since;
|
||||||
int nr_errors[4];
|
int xfer_ok;
|
||||||
|
int nr_errors[ATA_ECAT_NR];
|
||||||
};
|
};
|
||||||
|
|
||||||
static int speed_down_verdict_cb(struct ata_ering_entry *ent, void *void_arg)
|
static int speed_down_verdict_cb(struct ata_ering_entry *ent, void *void_arg)
|
||||||
{
|
{
|
||||||
struct speed_down_verdict_arg *arg = void_arg;
|
struct speed_down_verdict_arg *arg = void_arg;
|
||||||
int cat = ata_eh_categorize_error(ent->is_io, ent->err_mask);
|
int cat;
|
||||||
|
|
||||||
if (ent->timestamp < arg->since)
|
if (ent->timestamp < arg->since)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
cat = ata_eh_categorize_error(ent->eflags, ent->err_mask,
|
||||||
|
&arg->xfer_ok);
|
||||||
arg->nr_errors[cat]++;
|
arg->nr_errors[cat]++;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1495,22 +1546,48 @@ static int speed_down_verdict_cb(struct ata_ering_entry *ent, void *void_arg)
|
|||||||
* whether NCQ needs to be turned off, transfer speed should be
|
* whether NCQ needs to be turned off, transfer speed should be
|
||||||
* stepped down, or falling back to PIO is necessary.
|
* stepped down, or falling back to PIO is necessary.
|
||||||
*
|
*
|
||||||
* Cat-1 is ATA_BUS error for any command.
|
* ECAT_ATA_BUS : ATA_BUS error for any command
|
||||||
*
|
*
|
||||||
* Cat-2 is TIMEOUT for any command or HSM violation for known
|
* ECAT_TOUT_HSM : TIMEOUT for any command or HSM violation for
|
||||||
* supported commands.
|
* IO commands
|
||||||
*
|
*
|
||||||
* Cat-3 is is unclassified DEV error for known supported
|
* ECAT_UNK_DEV : Unknown DEV error for IO commands
|
||||||
* command.
|
|
||||||
*
|
*
|
||||||
* NCQ needs to be turned off if there have been more than 3
|
* ECAT_DUBIOUS_* : Identical to above three but occurred while
|
||||||
* Cat-2 + Cat-3 errors during last 10 minutes.
|
* data transfer hasn't been verified.
|
||||||
*
|
*
|
||||||
* Speed down is necessary if there have been more than 3 Cat-1 +
|
* Verdicts are
|
||||||
* Cat-2 errors or 10 Cat-3 errors during last 10 minutes.
|
|
||||||
*
|
*
|
||||||
* Falling back to PIO mode is necessary if there have been more
|
* NCQ_OFF : Turn off NCQ.
|
||||||
* than 10 Cat-1 + Cat-2 + Cat-3 errors during last 5 minutes.
|
*
|
||||||
|
* SPEED_DOWN : Speed down transfer speed but don't fall back
|
||||||
|
* to PIO.
|
||||||
|
*
|
||||||
|
* FALLBACK_TO_PIO : Fall back to PIO.
|
||||||
|
*
|
||||||
|
* Even if multiple verdicts are returned, only one action is
|
||||||
|
* taken per error. An action triggered by non-DUBIOUS errors
|
||||||
|
* clears ering, while one triggered by DUBIOUS_* errors doesn't.
|
||||||
|
* This is to expedite speed down decisions right after device is
|
||||||
|
* initially configured.
|
||||||
|
*
|
||||||
|
* The followings are speed down rules. #1 and #2 deal with
|
||||||
|
* DUBIOUS errors.
|
||||||
|
*
|
||||||
|
* 1. If more than one DUBIOUS_ATA_BUS or DUBIOUS_TOUT_HSM errors
|
||||||
|
* occurred during last 5 mins, SPEED_DOWN and FALLBACK_TO_PIO.
|
||||||
|
*
|
||||||
|
* 2. If more than one DUBIOUS_TOUT_HSM or DUBIOUS_UNK_DEV errors
|
||||||
|
* occurred during last 5 mins, NCQ_OFF.
|
||||||
|
*
|
||||||
|
* 3. If more than 8 ATA_BUS, TOUT_HSM or UNK_DEV errors
|
||||||
|
* ocurred during last 5 mins, FALLBACK_TO_PIO
|
||||||
|
*
|
||||||
|
* 4. If more than 3 TOUT_HSM or UNK_DEV errors occurred
|
||||||
|
* during last 10 mins, NCQ_OFF.
|
||||||
|
*
|
||||||
|
* 5. If more than 3 ATA_BUS or TOUT_HSM errors, or more than 6
|
||||||
|
* UNK_DEV errors occurred during last 10 mins, SPEED_DOWN.
|
||||||
*
|
*
|
||||||
* LOCKING:
|
* LOCKING:
|
||||||
* Inherited from caller.
|
* Inherited from caller.
|
||||||
@ -1525,31 +1602,46 @@ static unsigned int ata_eh_speed_down_verdict(struct ata_device *dev)
|
|||||||
struct speed_down_verdict_arg arg;
|
struct speed_down_verdict_arg arg;
|
||||||
unsigned int verdict = 0;
|
unsigned int verdict = 0;
|
||||||
|
|
||||||
|
/* scan past 5 mins of error history */
|
||||||
|
memset(&arg, 0, sizeof(arg));
|
||||||
|
arg.since = j64 - min(j64, j5mins);
|
||||||
|
ata_ering_map(&dev->ering, speed_down_verdict_cb, &arg);
|
||||||
|
|
||||||
|
if (arg.nr_errors[ATA_ECAT_DUBIOUS_ATA_BUS] +
|
||||||
|
arg.nr_errors[ATA_ECAT_DUBIOUS_TOUT_HSM] > 1)
|
||||||
|
verdict |= ATA_EH_SPDN_SPEED_DOWN |
|
||||||
|
ATA_EH_SPDN_FALLBACK_TO_PIO | ATA_EH_SPDN_KEEP_ERRORS;
|
||||||
|
|
||||||
|
if (arg.nr_errors[ATA_ECAT_DUBIOUS_TOUT_HSM] +
|
||||||
|
arg.nr_errors[ATA_ECAT_DUBIOUS_UNK_DEV] > 1)
|
||||||
|
verdict |= ATA_EH_SPDN_NCQ_OFF | ATA_EH_SPDN_KEEP_ERRORS;
|
||||||
|
|
||||||
|
if (arg.nr_errors[ATA_ECAT_ATA_BUS] +
|
||||||
|
arg.nr_errors[ATA_ECAT_TOUT_HSM] +
|
||||||
|
arg.nr_errors[ATA_ECAT_UNK_DEV] > 6)
|
||||||
|
verdict |= ATA_EH_SPDN_FALLBACK_TO_PIO;
|
||||||
|
|
||||||
/* scan past 10 mins of error history */
|
/* scan past 10 mins of error history */
|
||||||
memset(&arg, 0, sizeof(arg));
|
memset(&arg, 0, sizeof(arg));
|
||||||
arg.since = j64 - min(j64, j10mins);
|
arg.since = j64 - min(j64, j10mins);
|
||||||
ata_ering_map(&dev->ering, speed_down_verdict_cb, &arg);
|
ata_ering_map(&dev->ering, speed_down_verdict_cb, &arg);
|
||||||
|
|
||||||
if (arg.nr_errors[2] + arg.nr_errors[3] > 3)
|
if (arg.nr_errors[ATA_ECAT_TOUT_HSM] +
|
||||||
|
arg.nr_errors[ATA_ECAT_UNK_DEV] > 3)
|
||||||
verdict |= ATA_EH_SPDN_NCQ_OFF;
|
verdict |= ATA_EH_SPDN_NCQ_OFF;
|
||||||
if (arg.nr_errors[1] + arg.nr_errors[2] > 3 || arg.nr_errors[3] > 10)
|
|
||||||
|
if (arg.nr_errors[ATA_ECAT_ATA_BUS] +
|
||||||
|
arg.nr_errors[ATA_ECAT_TOUT_HSM] > 3 ||
|
||||||
|
arg.nr_errors[ATA_ECAT_UNK_DEV] > 6)
|
||||||
verdict |= ATA_EH_SPDN_SPEED_DOWN;
|
verdict |= ATA_EH_SPDN_SPEED_DOWN;
|
||||||
|
|
||||||
/* scan past 3 mins of error history */
|
|
||||||
memset(&arg, 0, sizeof(arg));
|
|
||||||
arg.since = j64 - min(j64, j5mins);
|
|
||||||
ata_ering_map(&dev->ering, speed_down_verdict_cb, &arg);
|
|
||||||
|
|
||||||
if (arg.nr_errors[1] + arg.nr_errors[2] + arg.nr_errors[3] > 10)
|
|
||||||
verdict |= ATA_EH_SPDN_FALLBACK_TO_PIO;
|
|
||||||
|
|
||||||
return verdict;
|
return verdict;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ata_eh_speed_down - record error and speed down if necessary
|
* ata_eh_speed_down - record error and speed down if necessary
|
||||||
* @dev: Failed device
|
* @dev: Failed device
|
||||||
* @is_io: Did the device fail during normal IO?
|
* @eflags: mask of ATA_EFLAG_* flags
|
||||||
* @err_mask: err_mask of the error
|
* @err_mask: err_mask of the error
|
||||||
*
|
*
|
||||||
* Record error and examine error history to determine whether
|
* Record error and examine error history to determine whether
|
||||||
@ -1563,18 +1655,20 @@ static unsigned int ata_eh_speed_down_verdict(struct ata_device *dev)
|
|||||||
* RETURNS:
|
* RETURNS:
|
||||||
* Determined recovery action.
|
* Determined recovery action.
|
||||||
*/
|
*/
|
||||||
static unsigned int ata_eh_speed_down(struct ata_device *dev, int is_io,
|
static unsigned int ata_eh_speed_down(struct ata_device *dev,
|
||||||
unsigned int err_mask)
|
unsigned int eflags, unsigned int err_mask)
|
||||||
{
|
{
|
||||||
|
struct ata_link *link = dev->link;
|
||||||
|
int xfer_ok = 0;
|
||||||
unsigned int verdict;
|
unsigned int verdict;
|
||||||
unsigned int action = 0;
|
unsigned int action = 0;
|
||||||
|
|
||||||
/* don't bother if Cat-0 error */
|
/* don't bother if Cat-0 error */
|
||||||
if (ata_eh_categorize_error(is_io, err_mask) == 0)
|
if (ata_eh_categorize_error(eflags, err_mask, &xfer_ok) == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* record error and determine whether speed down is necessary */
|
/* record error and determine whether speed down is necessary */
|
||||||
ata_ering_record(&dev->ering, is_io, err_mask);
|
ata_ering_record(&dev->ering, eflags, err_mask);
|
||||||
verdict = ata_eh_speed_down_verdict(dev);
|
verdict = ata_eh_speed_down_verdict(dev);
|
||||||
|
|
||||||
/* turn off NCQ? */
|
/* turn off NCQ? */
|
||||||
@ -1590,7 +1684,7 @@ static unsigned int ata_eh_speed_down(struct ata_device *dev, int is_io,
|
|||||||
/* speed down? */
|
/* speed down? */
|
||||||
if (verdict & ATA_EH_SPDN_SPEED_DOWN) {
|
if (verdict & ATA_EH_SPDN_SPEED_DOWN) {
|
||||||
/* speed down SATA link speed if possible */
|
/* speed down SATA link speed if possible */
|
||||||
if (sata_down_spd_limit(dev->link) == 0) {
|
if (sata_down_spd_limit(link) == 0) {
|
||||||
action |= ATA_EH_HARDRESET;
|
action |= ATA_EH_HARDRESET;
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
@ -1618,10 +1712,10 @@ static unsigned int ata_eh_speed_down(struct ata_device *dev, int is_io,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Fall back to PIO? Slowing down to PIO is meaningless for
|
/* Fall back to PIO? Slowing down to PIO is meaningless for
|
||||||
* SATA. Consider it only for PATA.
|
* SATA ATA devices. Consider it only for PATA and SATAPI.
|
||||||
*/
|
*/
|
||||||
if ((verdict & ATA_EH_SPDN_FALLBACK_TO_PIO) && (dev->spdn_cnt >= 2) &&
|
if ((verdict & ATA_EH_SPDN_FALLBACK_TO_PIO) && (dev->spdn_cnt >= 2) &&
|
||||||
(dev->link->ap->cbl != ATA_CBL_SATA) &&
|
(link->ap->cbl != ATA_CBL_SATA || dev->class == ATA_DEV_ATAPI) &&
|
||||||
(dev->xfer_shift != ATA_SHIFT_PIO)) {
|
(dev->xfer_shift != ATA_SHIFT_PIO)) {
|
||||||
if (ata_down_xfermask_limit(dev, ATA_DNXFER_FORCE_PIO) == 0) {
|
if (ata_down_xfermask_limit(dev, ATA_DNXFER_FORCE_PIO) == 0) {
|
||||||
dev->spdn_cnt = 0;
|
dev->spdn_cnt = 0;
|
||||||
@ -1633,7 +1727,8 @@ static unsigned int ata_eh_speed_down(struct ata_device *dev, int is_io,
|
|||||||
return 0;
|
return 0;
|
||||||
done:
|
done:
|
||||||
/* device has been slowed down, blow error history */
|
/* device has been slowed down, blow error history */
|
||||||
ata_ering_clear(&dev->ering);
|
if (!(verdict & ATA_EH_SPDN_KEEP_ERRORS))
|
||||||
|
ata_ering_clear(&dev->ering);
|
||||||
return action;
|
return action;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1653,8 +1748,8 @@ static void ata_eh_link_autopsy(struct ata_link *link)
|
|||||||
struct ata_port *ap = link->ap;
|
struct ata_port *ap = link->ap;
|
||||||
struct ata_eh_context *ehc = &link->eh_context;
|
struct ata_eh_context *ehc = &link->eh_context;
|
||||||
struct ata_device *dev;
|
struct ata_device *dev;
|
||||||
unsigned int all_err_mask = 0;
|
unsigned int all_err_mask = 0, eflags = 0;
|
||||||
int tag, is_io = 0;
|
int tag;
|
||||||
u32 serror;
|
u32 serror;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
@ -1713,15 +1808,15 @@ static void ata_eh_link_autopsy(struct ata_link *link)
|
|||||||
ehc->i.dev = qc->dev;
|
ehc->i.dev = qc->dev;
|
||||||
all_err_mask |= qc->err_mask;
|
all_err_mask |= qc->err_mask;
|
||||||
if (qc->flags & ATA_QCFLAG_IO)
|
if (qc->flags & ATA_QCFLAG_IO)
|
||||||
is_io = 1;
|
eflags |= ATA_EFLAG_IS_IO;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* enforce default EH actions */
|
/* enforce default EH actions */
|
||||||
if (ap->pflags & ATA_PFLAG_FROZEN ||
|
if (ap->pflags & ATA_PFLAG_FROZEN ||
|
||||||
all_err_mask & (AC_ERR_HSM | AC_ERR_TIMEOUT))
|
all_err_mask & (AC_ERR_HSM | AC_ERR_TIMEOUT))
|
||||||
ehc->i.action |= ATA_EH_SOFTRESET;
|
ehc->i.action |= ATA_EH_SOFTRESET;
|
||||||
else if ((is_io && all_err_mask) ||
|
else if (((eflags & ATA_EFLAG_IS_IO) && all_err_mask) ||
|
||||||
(!is_io && (all_err_mask & ~AC_ERR_DEV)))
|
(!(eflags & ATA_EFLAG_IS_IO) && (all_err_mask & ~AC_ERR_DEV)))
|
||||||
ehc->i.action |= ATA_EH_REVALIDATE;
|
ehc->i.action |= ATA_EH_REVALIDATE;
|
||||||
|
|
||||||
/* If we have offending qcs and the associated failed device,
|
/* If we have offending qcs and the associated failed device,
|
||||||
@ -1743,8 +1838,11 @@ static void ata_eh_link_autopsy(struct ata_link *link)
|
|||||||
ata_dev_enabled(link->device))))
|
ata_dev_enabled(link->device))))
|
||||||
dev = link->device;
|
dev = link->device;
|
||||||
|
|
||||||
if (dev)
|
if (dev) {
|
||||||
ehc->i.action |= ata_eh_speed_down(dev, is_io, all_err_mask);
|
if (dev->flags & ATA_DFLAG_DUBIOUS_XFER)
|
||||||
|
eflags |= ATA_EFLAG_DUBIOUS_XFER;
|
||||||
|
ehc->i.action |= ata_eh_speed_down(dev, eflags, all_err_mask);
|
||||||
|
}
|
||||||
|
|
||||||
DPRINTK("EXIT\n");
|
DPRINTK("EXIT\n");
|
||||||
}
|
}
|
||||||
@ -1880,8 +1978,8 @@ static void ata_eh_link_report(struct ata_link *link)
|
|||||||
[ATA_PROT_PIO] = "pio",
|
[ATA_PROT_PIO] = "pio",
|
||||||
[ATA_PROT_DMA] = "dma",
|
[ATA_PROT_DMA] = "dma",
|
||||||
[ATA_PROT_NCQ] = "ncq",
|
[ATA_PROT_NCQ] = "ncq",
|
||||||
[ATA_PROT_ATAPI] = "pio",
|
[ATAPI_PROT_PIO] = "pio",
|
||||||
[ATA_PROT_ATAPI_DMA] = "dma",
|
[ATAPI_PROT_DMA] = "dma",
|
||||||
};
|
};
|
||||||
|
|
||||||
snprintf(data_buf, sizeof(data_buf), " %s %u %s",
|
snprintf(data_buf, sizeof(data_buf), " %s %u %s",
|
||||||
@ -1889,7 +1987,7 @@ static void ata_eh_link_report(struct ata_link *link)
|
|||||||
dma_str[qc->dma_dir]);
|
dma_str[qc->dma_dir]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_atapi_taskfile(&qc->tf))
|
if (ata_is_atapi(qc->tf.protocol))
|
||||||
snprintf(cdb_buf, sizeof(cdb_buf),
|
snprintf(cdb_buf, sizeof(cdb_buf),
|
||||||
"cdb %02x %02x %02x %02x %02x %02x %02x %02x "
|
"cdb %02x %02x %02x %02x %02x %02x %02x %02x "
|
||||||
"%02x %02x %02x %02x %02x %02x %02x %02x\n ",
|
"%02x %02x %02x %02x %02x %02x %02x %02x\n ",
|
||||||
@ -2329,6 +2427,58 @@ static int ata_eh_revalidate_and_attach(struct ata_link *link,
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ata_set_mode - Program timings and issue SET FEATURES - XFER
|
||||||
|
* @link: link on which timings will be programmed
|
||||||
|
* @r_failed_dev: out paramter for failed device
|
||||||
|
*
|
||||||
|
* Set ATA device disk transfer mode (PIO3, UDMA6, etc.). If
|
||||||
|
* ata_set_mode() fails, pointer to the failing device is
|
||||||
|
* returned in @r_failed_dev.
|
||||||
|
*
|
||||||
|
* LOCKING:
|
||||||
|
* PCI/etc. bus probe sem.
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* 0 on success, negative errno otherwise
|
||||||
|
*/
|
||||||
|
int ata_set_mode(struct ata_link *link, struct ata_device **r_failed_dev)
|
||||||
|
{
|
||||||
|
struct ata_port *ap = link->ap;
|
||||||
|
struct ata_device *dev;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
/* if data transfer is verified, clear DUBIOUS_XFER on ering top */
|
||||||
|
ata_link_for_each_dev(dev, link) {
|
||||||
|
if (!(dev->flags & ATA_DFLAG_DUBIOUS_XFER)) {
|
||||||
|
struct ata_ering_entry *ent;
|
||||||
|
|
||||||
|
ent = ata_ering_top(&dev->ering);
|
||||||
|
if (ent)
|
||||||
|
ent->eflags &= ~ATA_EFLAG_DUBIOUS_XFER;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* has private set_mode? */
|
||||||
|
if (ap->ops->set_mode)
|
||||||
|
rc = ap->ops->set_mode(link, r_failed_dev);
|
||||||
|
else
|
||||||
|
rc = ata_do_set_mode(link, r_failed_dev);
|
||||||
|
|
||||||
|
/* if transfer mode has changed, set DUBIOUS_XFER on device */
|
||||||
|
ata_link_for_each_dev(dev, link) {
|
||||||
|
struct ata_eh_context *ehc = &link->eh_context;
|
||||||
|
u8 saved_xfer_mode = ehc->saved_xfer_mode[dev->devno];
|
||||||
|
u8 saved_ncq = !!(ehc->saved_ncq_enabled & (1 << dev->devno));
|
||||||
|
|
||||||
|
if (dev->xfer_mode != saved_xfer_mode ||
|
||||||
|
ata_ncq_enabled(dev) != saved_ncq)
|
||||||
|
dev->flags |= ATA_DFLAG_DUBIOUS_XFER;
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
static int ata_link_nr_enabled(struct ata_link *link)
|
static int ata_link_nr_enabled(struct ata_link *link)
|
||||||
{
|
{
|
||||||
struct ata_device *dev;
|
struct ata_device *dev;
|
||||||
@ -2375,6 +2525,24 @@ static int ata_eh_skip_recovery(struct ata_link *link)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int ata_eh_schedule_probe(struct ata_device *dev)
|
||||||
|
{
|
||||||
|
struct ata_eh_context *ehc = &dev->link->eh_context;
|
||||||
|
|
||||||
|
if (!(ehc->i.probe_mask & (1 << dev->devno)) ||
|
||||||
|
(ehc->did_probe_mask & (1 << dev->devno)))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
ata_eh_detach_dev(dev);
|
||||||
|
ata_dev_init(dev);
|
||||||
|
ehc->did_probe_mask |= (1 << dev->devno);
|
||||||
|
ehc->i.action |= ATA_EH_SOFTRESET;
|
||||||
|
ehc->saved_xfer_mode[dev->devno] = 0;
|
||||||
|
ehc->saved_ncq_enabled &= ~(1 << dev->devno);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
static int ata_eh_handle_dev_fail(struct ata_device *dev, int err)
|
static int ata_eh_handle_dev_fail(struct ata_device *dev, int err)
|
||||||
{
|
{
|
||||||
struct ata_eh_context *ehc = &dev->link->eh_context;
|
struct ata_eh_context *ehc = &dev->link->eh_context;
|
||||||
@ -2406,16 +2574,9 @@ static int ata_eh_handle_dev_fail(struct ata_device *dev, int err)
|
|||||||
if (ata_link_offline(dev->link))
|
if (ata_link_offline(dev->link))
|
||||||
ata_eh_detach_dev(dev);
|
ata_eh_detach_dev(dev);
|
||||||
|
|
||||||
/* probe if requested */
|
/* schedule probe if necessary */
|
||||||
if ((ehc->i.probe_mask & (1 << dev->devno)) &&
|
if (ata_eh_schedule_probe(dev))
|
||||||
!(ehc->did_probe_mask & (1 << dev->devno))) {
|
|
||||||
ata_eh_detach_dev(dev);
|
|
||||||
ata_dev_init(dev);
|
|
||||||
|
|
||||||
ehc->tries[dev->devno] = ATA_EH_DEV_TRIES;
|
ehc->tries[dev->devno] = ATA_EH_DEV_TRIES;
|
||||||
ehc->did_probe_mask |= (1 << dev->devno);
|
|
||||||
ehc->i.action |= ATA_EH_SOFTRESET;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
} else {
|
} else {
|
||||||
@ -2492,14 +2653,9 @@ int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset,
|
|||||||
if (dev->flags & ATA_DFLAG_DETACH)
|
if (dev->flags & ATA_DFLAG_DETACH)
|
||||||
ata_eh_detach_dev(dev);
|
ata_eh_detach_dev(dev);
|
||||||
|
|
||||||
if (!ata_dev_enabled(dev) &&
|
/* schedule probe if necessary */
|
||||||
((ehc->i.probe_mask & (1 << dev->devno)) &&
|
if (!ata_dev_enabled(dev))
|
||||||
!(ehc->did_probe_mask & (1 << dev->devno)))) {
|
ata_eh_schedule_probe(dev);
|
||||||
ata_eh_detach_dev(dev);
|
|
||||||
ata_dev_init(dev);
|
|
||||||
ehc->did_probe_mask |= (1 << dev->devno);
|
|
||||||
ehc->i.action |= ATA_EH_SOFTRESET;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2747,6 +2903,7 @@ static void ata_eh_handle_port_suspend(struct ata_port *ap)
|
|||||||
if (ap->ops->port_suspend)
|
if (ap->ops->port_suspend)
|
||||||
rc = ap->ops->port_suspend(ap, ap->pm_mesg);
|
rc = ap->ops->port_suspend(ap, ap->pm_mesg);
|
||||||
|
|
||||||
|
ata_acpi_set_state(ap, PMSG_SUSPEND);
|
||||||
out:
|
out:
|
||||||
/* report result */
|
/* report result */
|
||||||
spin_lock_irqsave(ap->lock, flags);
|
spin_lock_irqsave(ap->lock, flags);
|
||||||
@ -2792,6 +2949,8 @@ static void ata_eh_handle_port_resume(struct ata_port *ap)
|
|||||||
|
|
||||||
WARN_ON(!(ap->pflags & ATA_PFLAG_SUSPENDED));
|
WARN_ON(!(ap->pflags & ATA_PFLAG_SUSPENDED));
|
||||||
|
|
||||||
|
ata_acpi_set_state(ap, PMSG_ON);
|
||||||
|
|
||||||
if (ap->ops->port_resume)
|
if (ap->ops->port_resume)
|
||||||
rc = ap->ops->port_resume(ap);
|
rc = ap->ops->port_resume(ap);
|
||||||
|
|
||||||
|
@ -517,7 +517,7 @@ static struct ata_queued_cmd *ata_scsi_qc_new(struct ata_device *dev,
|
|||||||
qc->scsicmd = cmd;
|
qc->scsicmd = cmd;
|
||||||
qc->scsidone = done;
|
qc->scsidone = done;
|
||||||
|
|
||||||
qc->__sg = scsi_sglist(cmd);
|
qc->sg = scsi_sglist(cmd);
|
||||||
qc->n_elem = scsi_sg_count(cmd);
|
qc->n_elem = scsi_sg_count(cmd);
|
||||||
} else {
|
} else {
|
||||||
cmd->result = (DID_OK << 16) | (QUEUE_FULL << 1);
|
cmd->result = (DID_OK << 16) | (QUEUE_FULL << 1);
|
||||||
@ -2210,7 +2210,7 @@ unsigned int ata_scsiop_read_cap(struct ata_scsi_args *args, u8 *rbuf,
|
|||||||
|
|
||||||
/* sector size */
|
/* sector size */
|
||||||
ATA_SCSI_RBUF_SET(6, ATA_SECT_SIZE >> 8);
|
ATA_SCSI_RBUF_SET(6, ATA_SECT_SIZE >> 8);
|
||||||
ATA_SCSI_RBUF_SET(7, ATA_SECT_SIZE);
|
ATA_SCSI_RBUF_SET(7, ATA_SECT_SIZE & 0xff);
|
||||||
} else {
|
} else {
|
||||||
/* sector count, 64-bit */
|
/* sector count, 64-bit */
|
||||||
ATA_SCSI_RBUF_SET(0, last_lba >> (8 * 7));
|
ATA_SCSI_RBUF_SET(0, last_lba >> (8 * 7));
|
||||||
@ -2224,7 +2224,7 @@ unsigned int ata_scsiop_read_cap(struct ata_scsi_args *args, u8 *rbuf,
|
|||||||
|
|
||||||
/* sector size */
|
/* sector size */
|
||||||
ATA_SCSI_RBUF_SET(10, ATA_SECT_SIZE >> 8);
|
ATA_SCSI_RBUF_SET(10, ATA_SECT_SIZE >> 8);
|
||||||
ATA_SCSI_RBUF_SET(11, ATA_SECT_SIZE);
|
ATA_SCSI_RBUF_SET(11, ATA_SECT_SIZE & 0xff);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -2331,7 +2331,7 @@ static void atapi_request_sense(struct ata_queued_cmd *qc)
|
|||||||
DPRINTK("ATAPI request sense\n");
|
DPRINTK("ATAPI request sense\n");
|
||||||
|
|
||||||
/* FIXME: is this needed? */
|
/* FIXME: is this needed? */
|
||||||
memset(cmd->sense_buffer, 0, sizeof(cmd->sense_buffer));
|
memset(cmd->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE);
|
||||||
|
|
||||||
ap->ops->tf_read(ap, &qc->tf);
|
ap->ops->tf_read(ap, &qc->tf);
|
||||||
|
|
||||||
@ -2341,7 +2341,9 @@ static void atapi_request_sense(struct ata_queued_cmd *qc)
|
|||||||
|
|
||||||
ata_qc_reinit(qc);
|
ata_qc_reinit(qc);
|
||||||
|
|
||||||
ata_sg_init_one(qc, cmd->sense_buffer, sizeof(cmd->sense_buffer));
|
/* setup sg table and init transfer direction */
|
||||||
|
sg_init_one(&qc->sgent, cmd->sense_buffer, SCSI_SENSE_BUFFERSIZE);
|
||||||
|
ata_sg_init(qc, &qc->sgent, 1);
|
||||||
qc->dma_dir = DMA_FROM_DEVICE;
|
qc->dma_dir = DMA_FROM_DEVICE;
|
||||||
|
|
||||||
memset(&qc->cdb, 0, qc->dev->cdb_len);
|
memset(&qc->cdb, 0, qc->dev->cdb_len);
|
||||||
@ -2352,10 +2354,10 @@ static void atapi_request_sense(struct ata_queued_cmd *qc)
|
|||||||
qc->tf.command = ATA_CMD_PACKET;
|
qc->tf.command = ATA_CMD_PACKET;
|
||||||
|
|
||||||
if (ata_pio_use_silly(ap)) {
|
if (ata_pio_use_silly(ap)) {
|
||||||
qc->tf.protocol = ATA_PROT_ATAPI_DMA;
|
qc->tf.protocol = ATAPI_PROT_DMA;
|
||||||
qc->tf.feature |= ATAPI_PKT_DMA;
|
qc->tf.feature |= ATAPI_PKT_DMA;
|
||||||
} else {
|
} else {
|
||||||
qc->tf.protocol = ATA_PROT_ATAPI;
|
qc->tf.protocol = ATAPI_PROT_PIO;
|
||||||
qc->tf.lbam = SCSI_SENSE_BUFFERSIZE;
|
qc->tf.lbam = SCSI_SENSE_BUFFERSIZE;
|
||||||
qc->tf.lbah = 0;
|
qc->tf.lbah = 0;
|
||||||
}
|
}
|
||||||
@ -2526,12 +2528,12 @@ static unsigned int atapi_xlat(struct ata_queued_cmd *qc)
|
|||||||
if (using_pio || nodata) {
|
if (using_pio || nodata) {
|
||||||
/* no data, or PIO data xfer */
|
/* no data, or PIO data xfer */
|
||||||
if (nodata)
|
if (nodata)
|
||||||
qc->tf.protocol = ATA_PROT_ATAPI_NODATA;
|
qc->tf.protocol = ATAPI_PROT_NODATA;
|
||||||
else
|
else
|
||||||
qc->tf.protocol = ATA_PROT_ATAPI;
|
qc->tf.protocol = ATAPI_PROT_PIO;
|
||||||
} else {
|
} else {
|
||||||
/* DMA data xfer */
|
/* DMA data xfer */
|
||||||
qc->tf.protocol = ATA_PROT_ATAPI_DMA;
|
qc->tf.protocol = ATAPI_PROT_DMA;
|
||||||
qc->tf.feature |= ATAPI_PKT_DMA;
|
qc->tf.feature |= ATAPI_PKT_DMA;
|
||||||
|
|
||||||
if (atapi_dmadir && (scmd->sc_data_direction != DMA_TO_DEVICE))
|
if (atapi_dmadir && (scmd->sc_data_direction != DMA_TO_DEVICE))
|
||||||
@ -2690,6 +2692,24 @@ static unsigned int ata_scsi_pass_thru(struct ata_queued_cmd *qc)
|
|||||||
if ((tf->protocol = ata_scsi_map_proto(cdb[1])) == ATA_PROT_UNKNOWN)
|
if ((tf->protocol = ata_scsi_map_proto(cdb[1])) == ATA_PROT_UNKNOWN)
|
||||||
goto invalid_fld;
|
goto invalid_fld;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Filter TPM commands by default. These provide an
|
||||||
|
* essentially uncontrolled encrypted "back door" between
|
||||||
|
* applications and the disk. Set libata.allow_tpm=1 if you
|
||||||
|
* have a real reason for wanting to use them. This ensures
|
||||||
|
* that installed software cannot easily mess stuff up without
|
||||||
|
* user intent. DVR type users will probably ship with this enabled
|
||||||
|
* for movie content management.
|
||||||
|
*
|
||||||
|
* Note that for ATA8 we can issue a DCS change and DCS freeze lock
|
||||||
|
* for this and should do in future but that it is not sufficient as
|
||||||
|
* DCS is an optional feature set. Thus we also do the software filter
|
||||||
|
* so that we comply with the TC consortium stated goal that the user
|
||||||
|
* can turn off TC features of their system.
|
||||||
|
*/
|
||||||
|
if (tf->command >= 0x5C && tf->command <= 0x5F && !libata_allow_tpm)
|
||||||
|
goto invalid_fld;
|
||||||
|
|
||||||
/* We may not issue DMA commands if no DMA mode is set */
|
/* We may not issue DMA commands if no DMA mode is set */
|
||||||
if (tf->protocol == ATA_PROT_DMA && dev->dma_mode == 0)
|
if (tf->protocol == ATA_PROT_DMA && dev->dma_mode == 0)
|
||||||
goto invalid_fld;
|
goto invalid_fld;
|
||||||
|
@ -147,7 +147,9 @@ void ata_exec_command(struct ata_port *ap, const struct ata_taskfile *tf)
|
|||||||
* @tf: ATA taskfile register set for storing input
|
* @tf: ATA taskfile register set for storing input
|
||||||
*
|
*
|
||||||
* Reads ATA taskfile registers for currently-selected device
|
* Reads ATA taskfile registers for currently-selected device
|
||||||
* into @tf.
|
* into @tf. Assumes the device has a fully SFF compliant task file
|
||||||
|
* layout and behaviour. If you device does not (eg has a different
|
||||||
|
* status method) then you will need to provide a replacement tf_read
|
||||||
*
|
*
|
||||||
* LOCKING:
|
* LOCKING:
|
||||||
* Inherited from caller.
|
* Inherited from caller.
|
||||||
@ -156,7 +158,7 @@ void ata_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
|
|||||||
{
|
{
|
||||||
struct ata_ioports *ioaddr = &ap->ioaddr;
|
struct ata_ioports *ioaddr = &ap->ioaddr;
|
||||||
|
|
||||||
tf->command = ata_chk_status(ap);
|
tf->command = ata_check_status(ap);
|
||||||
tf->feature = ioread8(ioaddr->error_addr);
|
tf->feature = ioread8(ioaddr->error_addr);
|
||||||
tf->nsect = ioread8(ioaddr->nsect_addr);
|
tf->nsect = ioread8(ioaddr->nsect_addr);
|
||||||
tf->lbal = ioread8(ioaddr->lbal_addr);
|
tf->lbal = ioread8(ioaddr->lbal_addr);
|
||||||
@ -415,7 +417,7 @@ void ata_bmdma_drive_eh(struct ata_port *ap, ata_prereset_fn_t prereset,
|
|||||||
ap->hsm_task_state = HSM_ST_IDLE;
|
ap->hsm_task_state = HSM_ST_IDLE;
|
||||||
|
|
||||||
if (qc && (qc->tf.protocol == ATA_PROT_DMA ||
|
if (qc && (qc->tf.protocol == ATA_PROT_DMA ||
|
||||||
qc->tf.protocol == ATA_PROT_ATAPI_DMA)) {
|
qc->tf.protocol == ATAPI_PROT_DMA)) {
|
||||||
u8 host_stat;
|
u8 host_stat;
|
||||||
|
|
||||||
host_stat = ap->ops->bmdma_status(ap);
|
host_stat = ap->ops->bmdma_status(ap);
|
||||||
@ -549,7 +551,7 @@ int ata_pci_init_bmdma(struct ata_host *host)
|
|||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
/* request and iomap DMA region */
|
/* request and iomap DMA region */
|
||||||
rc = pcim_iomap_regions(pdev, 1 << 4, DRV_NAME);
|
rc = pcim_iomap_regions(pdev, 1 << 4, dev_driver_string(gdev));
|
||||||
if (rc) {
|
if (rc) {
|
||||||
dev_printk(KERN_ERR, gdev, "failed to request/iomap BAR4\n");
|
dev_printk(KERN_ERR, gdev, "failed to request/iomap BAR4\n");
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
@ -619,7 +621,8 @@ int ata_pci_init_sff_host(struct ata_host *host)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = pcim_iomap_regions(pdev, 0x3 << base, DRV_NAME);
|
rc = pcim_iomap_regions(pdev, 0x3 << base,
|
||||||
|
dev_driver_string(gdev));
|
||||||
if (rc) {
|
if (rc) {
|
||||||
dev_printk(KERN_WARNING, gdev,
|
dev_printk(KERN_WARNING, gdev,
|
||||||
"failed to request/iomap BARs for port %d "
|
"failed to request/iomap BARs for port %d "
|
||||||
@ -710,6 +713,99 @@ int ata_pci_prepare_sff_host(struct pci_dev *pdev,
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ata_pci_activate_sff_host - start SFF host, request IRQ and register it
|
||||||
|
* @host: target SFF ATA host
|
||||||
|
* @irq_handler: irq_handler used when requesting IRQ(s)
|
||||||
|
* @sht: scsi_host_template to use when registering the host
|
||||||
|
*
|
||||||
|
* This is the counterpart of ata_host_activate() for SFF ATA
|
||||||
|
* hosts. This separate helper is necessary because SFF hosts
|
||||||
|
* use two separate interrupts in legacy mode.
|
||||||
|
*
|
||||||
|
* LOCKING:
|
||||||
|
* Inherited from calling layer (may sleep).
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* 0 on success, -errno otherwise.
|
||||||
|
*/
|
||||||
|
int ata_pci_activate_sff_host(struct ata_host *host,
|
||||||
|
irq_handler_t irq_handler,
|
||||||
|
struct scsi_host_template *sht)
|
||||||
|
{
|
||||||
|
struct device *dev = host->dev;
|
||||||
|
struct pci_dev *pdev = to_pci_dev(dev);
|
||||||
|
const char *drv_name = dev_driver_string(host->dev);
|
||||||
|
int legacy_mode = 0, rc;
|
||||||
|
|
||||||
|
rc = ata_host_start(host);
|
||||||
|
if (rc)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
if ((pdev->class >> 8) == PCI_CLASS_STORAGE_IDE) {
|
||||||
|
u8 tmp8, mask;
|
||||||
|
|
||||||
|
/* TODO: What if one channel is in native mode ... */
|
||||||
|
pci_read_config_byte(pdev, PCI_CLASS_PROG, &tmp8);
|
||||||
|
mask = (1 << 2) | (1 << 0);
|
||||||
|
if ((tmp8 & mask) != mask)
|
||||||
|
legacy_mode = 1;
|
||||||
|
#if defined(CONFIG_NO_ATA_LEGACY)
|
||||||
|
/* Some platforms with PCI limits cannot address compat
|
||||||
|
port space. In that case we punt if their firmware has
|
||||||
|
left a device in compatibility mode */
|
||||||
|
if (legacy_mode) {
|
||||||
|
printk(KERN_ERR "ata: Compatibility mode ATA is not supported on this platform, skipping.\n");
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!devres_open_group(dev, NULL, GFP_KERNEL))
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
if (!legacy_mode && pdev->irq) {
|
||||||
|
rc = devm_request_irq(dev, pdev->irq, irq_handler,
|
||||||
|
IRQF_SHARED, drv_name, host);
|
||||||
|
if (rc)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
ata_port_desc(host->ports[0], "irq %d", pdev->irq);
|
||||||
|
ata_port_desc(host->ports[1], "irq %d", pdev->irq);
|
||||||
|
} else if (legacy_mode) {
|
||||||
|
if (!ata_port_is_dummy(host->ports[0])) {
|
||||||
|
rc = devm_request_irq(dev, ATA_PRIMARY_IRQ(pdev),
|
||||||
|
irq_handler, IRQF_SHARED,
|
||||||
|
drv_name, host);
|
||||||
|
if (rc)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
ata_port_desc(host->ports[0], "irq %d",
|
||||||
|
ATA_PRIMARY_IRQ(pdev));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ata_port_is_dummy(host->ports[1])) {
|
||||||
|
rc = devm_request_irq(dev, ATA_SECONDARY_IRQ(pdev),
|
||||||
|
irq_handler, IRQF_SHARED,
|
||||||
|
drv_name, host);
|
||||||
|
if (rc)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
ata_port_desc(host->ports[1], "irq %d",
|
||||||
|
ATA_SECONDARY_IRQ(pdev));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = ata_host_register(host, sht);
|
||||||
|
out:
|
||||||
|
if (rc == 0)
|
||||||
|
devres_remove_group(dev, NULL);
|
||||||
|
else
|
||||||
|
devres_release_group(dev, NULL);
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ata_pci_init_one - Initialize/register PCI IDE host controller
|
* ata_pci_init_one - Initialize/register PCI IDE host controller
|
||||||
* @pdev: Controller to be initialized
|
* @pdev: Controller to be initialized
|
||||||
@ -739,8 +835,6 @@ int ata_pci_init_one(struct pci_dev *pdev,
|
|||||||
struct device *dev = &pdev->dev;
|
struct device *dev = &pdev->dev;
|
||||||
const struct ata_port_info *pi = NULL;
|
const struct ata_port_info *pi = NULL;
|
||||||
struct ata_host *host = NULL;
|
struct ata_host *host = NULL;
|
||||||
u8 mask;
|
|
||||||
int legacy_mode = 0;
|
|
||||||
int i, rc;
|
int i, rc;
|
||||||
|
|
||||||
DPRINTK("ENTER\n");
|
DPRINTK("ENTER\n");
|
||||||
@ -762,95 +856,24 @@ int ata_pci_init_one(struct pci_dev *pdev,
|
|||||||
if (!devres_open_group(dev, NULL, GFP_KERNEL))
|
if (!devres_open_group(dev, NULL, GFP_KERNEL))
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
/* FIXME: Really for ATA it isn't safe because the device may be
|
|
||||||
multi-purpose and we want to leave it alone if it was already
|
|
||||||
enabled. Secondly for shared use as Arjan says we want refcounting
|
|
||||||
|
|
||||||
Checking dev->is_enabled is insufficient as this is not set at
|
|
||||||
boot for the primary video which is BIOS enabled
|
|
||||||
*/
|
|
||||||
|
|
||||||
rc = pcim_enable_device(pdev);
|
rc = pcim_enable_device(pdev);
|
||||||
if (rc)
|
if (rc)
|
||||||
goto err_out;
|
goto out;
|
||||||
|
|
||||||
if ((pdev->class >> 8) == PCI_CLASS_STORAGE_IDE) {
|
/* prepare and activate SFF host */
|
||||||
u8 tmp8;
|
|
||||||
|
|
||||||
/* TODO: What if one channel is in native mode ... */
|
|
||||||
pci_read_config_byte(pdev, PCI_CLASS_PROG, &tmp8);
|
|
||||||
mask = (1 << 2) | (1 << 0);
|
|
||||||
if ((tmp8 & mask) != mask)
|
|
||||||
legacy_mode = 1;
|
|
||||||
#if defined(CONFIG_NO_ATA_LEGACY)
|
|
||||||
/* Some platforms with PCI limits cannot address compat
|
|
||||||
port space. In that case we punt if their firmware has
|
|
||||||
left a device in compatibility mode */
|
|
||||||
if (legacy_mode) {
|
|
||||||
printk(KERN_ERR "ata: Compatibility mode ATA is not supported on this platform, skipping.\n");
|
|
||||||
rc = -EOPNOTSUPP;
|
|
||||||
goto err_out;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
/* prepare host */
|
|
||||||
rc = ata_pci_prepare_sff_host(pdev, ppi, &host);
|
rc = ata_pci_prepare_sff_host(pdev, ppi, &host);
|
||||||
if (rc)
|
if (rc)
|
||||||
goto err_out;
|
goto out;
|
||||||
|
|
||||||
pci_set_master(pdev);
|
pci_set_master(pdev);
|
||||||
|
rc = ata_pci_activate_sff_host(host, pi->port_ops->irq_handler,
|
||||||
|
pi->sht);
|
||||||
|
out:
|
||||||
|
if (rc == 0)
|
||||||
|
devres_remove_group(&pdev->dev, NULL);
|
||||||
|
else
|
||||||
|
devres_release_group(&pdev->dev, NULL);
|
||||||
|
|
||||||
/* start host and request IRQ */
|
|
||||||
rc = ata_host_start(host);
|
|
||||||
if (rc)
|
|
||||||
goto err_out;
|
|
||||||
|
|
||||||
if (!legacy_mode && pdev->irq) {
|
|
||||||
/* We may have no IRQ assigned in which case we can poll. This
|
|
||||||
shouldn't happen on a sane system but robustness is cheap
|
|
||||||
in this case */
|
|
||||||
rc = devm_request_irq(dev, pdev->irq, pi->port_ops->irq_handler,
|
|
||||||
IRQF_SHARED, DRV_NAME, host);
|
|
||||||
if (rc)
|
|
||||||
goto err_out;
|
|
||||||
|
|
||||||
ata_port_desc(host->ports[0], "irq %d", pdev->irq);
|
|
||||||
ata_port_desc(host->ports[1], "irq %d", pdev->irq);
|
|
||||||
} else if (legacy_mode) {
|
|
||||||
if (!ata_port_is_dummy(host->ports[0])) {
|
|
||||||
rc = devm_request_irq(dev, ATA_PRIMARY_IRQ(pdev),
|
|
||||||
pi->port_ops->irq_handler,
|
|
||||||
IRQF_SHARED, DRV_NAME, host);
|
|
||||||
if (rc)
|
|
||||||
goto err_out;
|
|
||||||
|
|
||||||
ata_port_desc(host->ports[0], "irq %d",
|
|
||||||
ATA_PRIMARY_IRQ(pdev));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!ata_port_is_dummy(host->ports[1])) {
|
|
||||||
rc = devm_request_irq(dev, ATA_SECONDARY_IRQ(pdev),
|
|
||||||
pi->port_ops->irq_handler,
|
|
||||||
IRQF_SHARED, DRV_NAME, host);
|
|
||||||
if (rc)
|
|
||||||
goto err_out;
|
|
||||||
|
|
||||||
ata_port_desc(host->ports[1], "irq %d",
|
|
||||||
ATA_SECONDARY_IRQ(pdev));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* register */
|
|
||||||
rc = ata_host_register(host, pi->sht);
|
|
||||||
if (rc)
|
|
||||||
goto err_out;
|
|
||||||
|
|
||||||
devres_remove_group(dev, NULL);
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
err_out:
|
|
||||||
devres_release_group(dev, NULL);
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,6 +60,7 @@ extern int atapi_dmadir;
|
|||||||
extern int atapi_passthru16;
|
extern int atapi_passthru16;
|
||||||
extern int libata_fua;
|
extern int libata_fua;
|
||||||
extern int libata_noacpi;
|
extern int libata_noacpi;
|
||||||
|
extern int libata_allow_tpm;
|
||||||
extern struct ata_queued_cmd *ata_qc_new_init(struct ata_device *dev);
|
extern struct ata_queued_cmd *ata_qc_new_init(struct ata_device *dev);
|
||||||
extern int ata_build_rw_tf(struct ata_taskfile *tf, struct ata_device *dev,
|
extern int ata_build_rw_tf(struct ata_taskfile *tf, struct ata_device *dev,
|
||||||
u64 block, u32 n_block, unsigned int tf_flags,
|
u64 block, u32 n_block, unsigned int tf_flags,
|
||||||
@ -85,7 +86,6 @@ extern int ata_dev_configure(struct ata_device *dev);
|
|||||||
extern int sata_down_spd_limit(struct ata_link *link);
|
extern int sata_down_spd_limit(struct ata_link *link);
|
||||||
extern int sata_set_spd_needed(struct ata_link *link);
|
extern int sata_set_spd_needed(struct ata_link *link);
|
||||||
extern int ata_down_xfermask_limit(struct ata_device *dev, unsigned int sel);
|
extern int ata_down_xfermask_limit(struct ata_device *dev, unsigned int sel);
|
||||||
extern int ata_set_mode(struct ata_link *link, struct ata_device **r_failed_dev);
|
|
||||||
extern void ata_sg_clean(struct ata_queued_cmd *qc);
|
extern void ata_sg_clean(struct ata_queued_cmd *qc);
|
||||||
extern void ata_qc_free(struct ata_queued_cmd *qc);
|
extern void ata_qc_free(struct ata_queued_cmd *qc);
|
||||||
extern void ata_qc_issue(struct ata_queued_cmd *qc);
|
extern void ata_qc_issue(struct ata_queued_cmd *qc);
|
||||||
@ -113,6 +113,7 @@ extern int ata_acpi_on_suspend(struct ata_port *ap);
|
|||||||
extern void ata_acpi_on_resume(struct ata_port *ap);
|
extern void ata_acpi_on_resume(struct ata_port *ap);
|
||||||
extern int ata_acpi_on_devcfg(struct ata_device *dev);
|
extern int ata_acpi_on_devcfg(struct ata_device *dev);
|
||||||
extern void ata_acpi_on_disable(struct ata_device *dev);
|
extern void ata_acpi_on_disable(struct ata_device *dev);
|
||||||
|
extern void ata_acpi_set_state(struct ata_port *ap, pm_message_t state);
|
||||||
#else
|
#else
|
||||||
static inline void ata_acpi_associate_sata_port(struct ata_port *ap) { }
|
static inline void ata_acpi_associate_sata_port(struct ata_port *ap) { }
|
||||||
static inline void ata_acpi_associate(struct ata_host *host) { }
|
static inline void ata_acpi_associate(struct ata_host *host) { }
|
||||||
@ -121,6 +122,8 @@ static inline int ata_acpi_on_suspend(struct ata_port *ap) { return 0; }
|
|||||||
static inline void ata_acpi_on_resume(struct ata_port *ap) { }
|
static inline void ata_acpi_on_resume(struct ata_port *ap) { }
|
||||||
static inline int ata_acpi_on_devcfg(struct ata_device *dev) { return 0; }
|
static inline int ata_acpi_on_devcfg(struct ata_device *dev) { return 0; }
|
||||||
static inline void ata_acpi_on_disable(struct ata_device *dev) { }
|
static inline void ata_acpi_on_disable(struct ata_device *dev) { }
|
||||||
|
static inline void ata_acpi_set_state(struct ata_port *ap,
|
||||||
|
pm_message_t state) { }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* libata-scsi.c */
|
/* libata-scsi.c */
|
||||||
@ -183,6 +186,7 @@ extern void ata_eh_report(struct ata_port *ap);
|
|||||||
extern int ata_eh_reset(struct ata_link *link, int classify,
|
extern int ata_eh_reset(struct ata_link *link, int classify,
|
||||||
ata_prereset_fn_t prereset, ata_reset_fn_t softreset,
|
ata_prereset_fn_t prereset, ata_reset_fn_t softreset,
|
||||||
ata_reset_fn_t hardreset, ata_postreset_fn_t postreset);
|
ata_reset_fn_t hardreset, ata_postreset_fn_t postreset);
|
||||||
|
extern int ata_set_mode(struct ata_link *link, struct ata_device **r_failed_dev);
|
||||||
extern int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset,
|
extern int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset,
|
||||||
ata_reset_fn_t softreset, ata_reset_fn_t hardreset,
|
ata_reset_fn_t softreset, ata_reset_fn_t hardreset,
|
||||||
ata_postreset_fn_t postreset,
|
ata_postreset_fn_t postreset,
|
||||||
|
@ -81,17 +81,6 @@ static void pacpi_error_handler(struct ata_port *ap)
|
|||||||
NULL, ata_std_postreset);
|
NULL, ata_std_postreset);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Welcome to ACPI, bring a bucket */
|
|
||||||
static const unsigned int pio_cycle[7] = {
|
|
||||||
600, 383, 240, 180, 120, 100, 80
|
|
||||||
};
|
|
||||||
static const unsigned int mwdma_cycle[5] = {
|
|
||||||
480, 150, 120, 100, 80
|
|
||||||
};
|
|
||||||
static const unsigned int udma_cycle[7] = {
|
|
||||||
120, 80, 60, 45, 30, 20, 15
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* pacpi_discover_modes - filter non ACPI modes
|
* pacpi_discover_modes - filter non ACPI modes
|
||||||
* @adev: ATA device
|
* @adev: ATA device
|
||||||
@ -103,56 +92,20 @@ static const unsigned int udma_cycle[7] = {
|
|||||||
|
|
||||||
static unsigned long pacpi_discover_modes(struct ata_port *ap, struct ata_device *adev)
|
static unsigned long pacpi_discover_modes(struct ata_port *ap, struct ata_device *adev)
|
||||||
{
|
{
|
||||||
int unit = adev->devno;
|
|
||||||
struct pata_acpi *acpi = ap->private_data;
|
struct pata_acpi *acpi = ap->private_data;
|
||||||
int i;
|
|
||||||
u32 t;
|
|
||||||
unsigned long mask = (0x7f << ATA_SHIFT_UDMA) | (0x7 << ATA_SHIFT_MWDMA) | (0x1F << ATA_SHIFT_PIO);
|
|
||||||
|
|
||||||
struct ata_acpi_gtm probe;
|
struct ata_acpi_gtm probe;
|
||||||
|
unsigned int xfer_mask;
|
||||||
|
|
||||||
probe = acpi->gtm;
|
probe = acpi->gtm;
|
||||||
|
|
||||||
/* We always use the 0 slot for crap hardware */
|
|
||||||
if (!(probe.flags & 0x10))
|
|
||||||
unit = 0;
|
|
||||||
|
|
||||||
ata_acpi_gtm(ap, &probe);
|
ata_acpi_gtm(ap, &probe);
|
||||||
|
|
||||||
/* Start by scanning for PIO modes */
|
xfer_mask = ata_acpi_gtm_xfermask(adev, &probe);
|
||||||
for (i = 0; i < 7; i++) {
|
|
||||||
t = probe.drive[unit].pio;
|
|
||||||
if (t <= pio_cycle[i]) {
|
|
||||||
mask |= (2 << (ATA_SHIFT_PIO + i)) - 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* See if we have MWDMA or UDMA data. We don't bother with MWDMA
|
if (xfer_mask & (0xF8 << ATA_SHIFT_UDMA))
|
||||||
if UDMA is availabe as this means the BIOS set UDMA and our
|
|
||||||
error changedown if it works is UDMA to PIO anyway */
|
|
||||||
if (probe.flags & (1 << (2 * unit))) {
|
|
||||||
/* MWDMA */
|
|
||||||
for (i = 0; i < 5; i++) {
|
|
||||||
t = probe.drive[unit].dma;
|
|
||||||
if (t <= mwdma_cycle[i]) {
|
|
||||||
mask |= (2 << (ATA_SHIFT_MWDMA + i)) - 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
/* UDMA */
|
|
||||||
for (i = 0; i < 7; i++) {
|
|
||||||
t = probe.drive[unit].dma;
|
|
||||||
if (t <= udma_cycle[i]) {
|
|
||||||
mask |= (2 << (ATA_SHIFT_UDMA + i)) - 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (mask & (0xF8 << ATA_SHIFT_UDMA))
|
|
||||||
ap->cbl = ATA_CBL_PATA80;
|
ap->cbl = ATA_CBL_PATA80;
|
||||||
return mask;
|
|
||||||
|
return xfer_mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -180,12 +133,14 @@ static void pacpi_set_piomode(struct ata_port *ap, struct ata_device *adev)
|
|||||||
{
|
{
|
||||||
int unit = adev->devno;
|
int unit = adev->devno;
|
||||||
struct pata_acpi *acpi = ap->private_data;
|
struct pata_acpi *acpi = ap->private_data;
|
||||||
|
const struct ata_timing *t;
|
||||||
|
|
||||||
if (!(acpi->gtm.flags & 0x10))
|
if (!(acpi->gtm.flags & 0x10))
|
||||||
unit = 0;
|
unit = 0;
|
||||||
|
|
||||||
/* Now stuff the nS values into the structure */
|
/* Now stuff the nS values into the structure */
|
||||||
acpi->gtm.drive[unit].pio = pio_cycle[adev->pio_mode - XFER_PIO_0];
|
t = ata_timing_find_mode(adev->pio_mode);
|
||||||
|
acpi->gtm.drive[unit].pio = t->cycle;
|
||||||
ata_acpi_stm(ap, &acpi->gtm);
|
ata_acpi_stm(ap, &acpi->gtm);
|
||||||
/* See what mode we actually got */
|
/* See what mode we actually got */
|
||||||
ata_acpi_gtm(ap, &acpi->gtm);
|
ata_acpi_gtm(ap, &acpi->gtm);
|
||||||
@ -201,16 +156,18 @@ static void pacpi_set_dmamode(struct ata_port *ap, struct ata_device *adev)
|
|||||||
{
|
{
|
||||||
int unit = adev->devno;
|
int unit = adev->devno;
|
||||||
struct pata_acpi *acpi = ap->private_data;
|
struct pata_acpi *acpi = ap->private_data;
|
||||||
|
const struct ata_timing *t;
|
||||||
|
|
||||||
if (!(acpi->gtm.flags & 0x10))
|
if (!(acpi->gtm.flags & 0x10))
|
||||||
unit = 0;
|
unit = 0;
|
||||||
|
|
||||||
/* Now stuff the nS values into the structure */
|
/* Now stuff the nS values into the structure */
|
||||||
|
t = ata_timing_find_mode(adev->dma_mode);
|
||||||
if (adev->dma_mode >= XFER_UDMA_0) {
|
if (adev->dma_mode >= XFER_UDMA_0) {
|
||||||
acpi->gtm.drive[unit].dma = udma_cycle[adev->dma_mode - XFER_UDMA_0];
|
acpi->gtm.drive[unit].dma = t->udma;
|
||||||
acpi->gtm.flags |= (1 << (2 * unit));
|
acpi->gtm.flags |= (1 << (2 * unit));
|
||||||
} else {
|
} else {
|
||||||
acpi->gtm.drive[unit].dma = mwdma_cycle[adev->dma_mode - XFER_MW_DMA_0];
|
acpi->gtm.drive[unit].dma = t->cycle;
|
||||||
acpi->gtm.flags &= ~(1 << (2 * unit));
|
acpi->gtm.flags &= ~(1 << (2 * unit));
|
||||||
}
|
}
|
||||||
ata_acpi_stm(ap, &acpi->gtm);
|
ata_acpi_stm(ap, &acpi->gtm);
|
||||||
|
@ -64,7 +64,7 @@ static int ali_cable_override(struct pci_dev *pdev)
|
|||||||
if (pdev->subsystem_vendor == 0x10CF && pdev->subsystem_device == 0x10AF)
|
if (pdev->subsystem_vendor == 0x10CF && pdev->subsystem_device == 0x10AF)
|
||||||
return 1;
|
return 1;
|
||||||
/* Mitac 8317 (Winbook-A) and relatives */
|
/* Mitac 8317 (Winbook-A) and relatives */
|
||||||
if (pdev->subsystem_vendor == 0x1071 && pdev->subsystem_device == 0x8317)
|
if (pdev->subsystem_vendor == 0x1071 && pdev->subsystem_device == 0x8317)
|
||||||
return 1;
|
return 1;
|
||||||
/* Systems by DMI */
|
/* Systems by DMI */
|
||||||
if (dmi_check_system(cable_dmi_table))
|
if (dmi_check_system(cable_dmi_table))
|
||||||
|
@ -220,6 +220,62 @@ static void amd133_set_dmamode(struct ata_port *ap, struct ata_device *adev)
|
|||||||
timing_setup(ap, adev, 0x40, adev->dma_mode, 4);
|
timing_setup(ap, adev, 0x40, adev->dma_mode, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Both host-side and drive-side detection results are worthless on NV
|
||||||
|
* PATAs. Ignore them and just follow what BIOS configured. Both the
|
||||||
|
* current configuration in PCI config reg and ACPI GTM result are
|
||||||
|
* cached during driver attach and are consulted to select transfer
|
||||||
|
* mode.
|
||||||
|
*/
|
||||||
|
static unsigned long nv_mode_filter(struct ata_device *dev,
|
||||||
|
unsigned long xfer_mask)
|
||||||
|
{
|
||||||
|
static const unsigned int udma_mask_map[] =
|
||||||
|
{ ATA_UDMA2, ATA_UDMA1, ATA_UDMA0, 0,
|
||||||
|
ATA_UDMA3, ATA_UDMA4, ATA_UDMA5, ATA_UDMA6 };
|
||||||
|
struct ata_port *ap = dev->link->ap;
|
||||||
|
char acpi_str[32] = "";
|
||||||
|
u32 saved_udma, udma;
|
||||||
|
const struct ata_acpi_gtm *gtm;
|
||||||
|
unsigned long bios_limit = 0, acpi_limit = 0, limit;
|
||||||
|
|
||||||
|
/* find out what BIOS configured */
|
||||||
|
udma = saved_udma = (unsigned long)ap->host->private_data;
|
||||||
|
|
||||||
|
if (ap->port_no == 0)
|
||||||
|
udma >>= 16;
|
||||||
|
if (dev->devno == 0)
|
||||||
|
udma >>= 8;
|
||||||
|
|
||||||
|
if ((udma & 0xc0) == 0xc0)
|
||||||
|
bios_limit = ata_pack_xfermask(0, 0, udma_mask_map[udma & 0x7]);
|
||||||
|
|
||||||
|
/* consult ACPI GTM too */
|
||||||
|
gtm = ata_acpi_init_gtm(ap);
|
||||||
|
if (gtm) {
|
||||||
|
acpi_limit = ata_acpi_gtm_xfermask(dev, gtm);
|
||||||
|
|
||||||
|
snprintf(acpi_str, sizeof(acpi_str), " (%u:%u:0x%x)",
|
||||||
|
gtm->drive[0].dma, gtm->drive[1].dma, gtm->flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* be optimistic, EH can take care of things if something goes wrong */
|
||||||
|
limit = bios_limit | acpi_limit;
|
||||||
|
|
||||||
|
/* If PIO or DMA isn't configured at all, don't limit. Let EH
|
||||||
|
* handle it.
|
||||||
|
*/
|
||||||
|
if (!(limit & ATA_MASK_PIO))
|
||||||
|
limit |= ATA_MASK_PIO;
|
||||||
|
if (!(limit & (ATA_MASK_MWDMA | ATA_MASK_UDMA)))
|
||||||
|
limit |= ATA_MASK_MWDMA | ATA_MASK_UDMA;
|
||||||
|
|
||||||
|
ata_port_printk(ap, KERN_DEBUG, "nv_mode_filter: 0x%lx&0x%lx->0x%lx, "
|
||||||
|
"BIOS=0x%lx (0x%x) ACPI=0x%lx%s\n",
|
||||||
|
xfer_mask, limit, xfer_mask & limit, bios_limit,
|
||||||
|
saved_udma, acpi_limit, acpi_str);
|
||||||
|
|
||||||
|
return xfer_mask & limit;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* nv_probe_init - cable detection
|
* nv_probe_init - cable detection
|
||||||
@ -252,31 +308,6 @@ static void nv_error_handler(struct ata_port *ap)
|
|||||||
ata_std_postreset);
|
ata_std_postreset);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int nv_cable_detect(struct ata_port *ap)
|
|
||||||
{
|
|
||||||
static const u8 bitmask[2] = {0x03, 0x0C};
|
|
||||||
struct pci_dev *pdev = to_pci_dev(ap->host->dev);
|
|
||||||
u8 ata66;
|
|
||||||
u16 udma;
|
|
||||||
int cbl;
|
|
||||||
|
|
||||||
pci_read_config_byte(pdev, 0x52, &ata66);
|
|
||||||
if (ata66 & bitmask[ap->port_no])
|
|
||||||
cbl = ATA_CBL_PATA80;
|
|
||||||
else
|
|
||||||
cbl = ATA_CBL_PATA40;
|
|
||||||
|
|
||||||
/* We now have to double check because the Nvidia boxes BIOS
|
|
||||||
doesn't always set the cable bits but does set mode bits */
|
|
||||||
pci_read_config_word(pdev, 0x62 - 2 * ap->port_no, &udma);
|
|
||||||
if ((udma & 0xC4) == 0xC4 || (udma & 0xC400) == 0xC400)
|
|
||||||
cbl = ATA_CBL_PATA80;
|
|
||||||
/* And a triple check across suspend/resume with ACPI around */
|
|
||||||
if (ata_acpi_cbl_80wire(ap))
|
|
||||||
cbl = ATA_CBL_PATA80;
|
|
||||||
return cbl;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* nv100_set_piomode - set initial PIO mode data
|
* nv100_set_piomode - set initial PIO mode data
|
||||||
* @ap: ATA interface
|
* @ap: ATA interface
|
||||||
@ -314,6 +345,14 @@ static void nv133_set_dmamode(struct ata_port *ap, struct ata_device *adev)
|
|||||||
timing_setup(ap, adev, 0x50, adev->dma_mode, 4);
|
timing_setup(ap, adev, 0x50, adev->dma_mode, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void nv_host_stop(struct ata_host *host)
|
||||||
|
{
|
||||||
|
u32 udma = (unsigned long)host->private_data;
|
||||||
|
|
||||||
|
/* restore PCI config register 0x60 */
|
||||||
|
pci_write_config_dword(to_pci_dev(host->dev), 0x60, udma);
|
||||||
|
}
|
||||||
|
|
||||||
static struct scsi_host_template amd_sht = {
|
static struct scsi_host_template amd_sht = {
|
||||||
.module = THIS_MODULE,
|
.module = THIS_MODULE,
|
||||||
.name = DRV_NAME,
|
.name = DRV_NAME,
|
||||||
@ -478,7 +517,8 @@ static struct ata_port_operations nv100_port_ops = {
|
|||||||
.thaw = ata_bmdma_thaw,
|
.thaw = ata_bmdma_thaw,
|
||||||
.error_handler = nv_error_handler,
|
.error_handler = nv_error_handler,
|
||||||
.post_internal_cmd = ata_bmdma_post_internal_cmd,
|
.post_internal_cmd = ata_bmdma_post_internal_cmd,
|
||||||
.cable_detect = nv_cable_detect,
|
.cable_detect = ata_cable_ignore,
|
||||||
|
.mode_filter = nv_mode_filter,
|
||||||
|
|
||||||
.bmdma_setup = ata_bmdma_setup,
|
.bmdma_setup = ata_bmdma_setup,
|
||||||
.bmdma_start = ata_bmdma_start,
|
.bmdma_start = ata_bmdma_start,
|
||||||
@ -495,6 +535,7 @@ static struct ata_port_operations nv100_port_ops = {
|
|||||||
.irq_on = ata_irq_on,
|
.irq_on = ata_irq_on,
|
||||||
|
|
||||||
.port_start = ata_sff_port_start,
|
.port_start = ata_sff_port_start,
|
||||||
|
.host_stop = nv_host_stop,
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct ata_port_operations nv133_port_ops = {
|
static struct ata_port_operations nv133_port_ops = {
|
||||||
@ -511,7 +552,8 @@ static struct ata_port_operations nv133_port_ops = {
|
|||||||
.thaw = ata_bmdma_thaw,
|
.thaw = ata_bmdma_thaw,
|
||||||
.error_handler = nv_error_handler,
|
.error_handler = nv_error_handler,
|
||||||
.post_internal_cmd = ata_bmdma_post_internal_cmd,
|
.post_internal_cmd = ata_bmdma_post_internal_cmd,
|
||||||
.cable_detect = nv_cable_detect,
|
.cable_detect = ata_cable_ignore,
|
||||||
|
.mode_filter = nv_mode_filter,
|
||||||
|
|
||||||
.bmdma_setup = ata_bmdma_setup,
|
.bmdma_setup = ata_bmdma_setup,
|
||||||
.bmdma_start = ata_bmdma_start,
|
.bmdma_start = ata_bmdma_start,
|
||||||
@ -528,6 +570,7 @@ static struct ata_port_operations nv133_port_ops = {
|
|||||||
.irq_on = ata_irq_on,
|
.irq_on = ata_irq_on,
|
||||||
|
|
||||||
.port_start = ata_sff_port_start,
|
.port_start = ata_sff_port_start,
|
||||||
|
.host_stop = nv_host_stop,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int amd_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
|
static int amd_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
|
||||||
@ -614,7 +657,8 @@ static int amd_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
|
|||||||
.port_ops = &amd100_port_ops
|
.port_ops = &amd100_port_ops
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const struct ata_port_info *ppi[] = { NULL, NULL };
|
struct ata_port_info pi;
|
||||||
|
const struct ata_port_info *ppi[] = { &pi, NULL };
|
||||||
static int printed_version;
|
static int printed_version;
|
||||||
int type = id->driver_data;
|
int type = id->driver_data;
|
||||||
u8 fifo;
|
u8 fifo;
|
||||||
@ -628,6 +672,19 @@ static int amd_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
|
|||||||
if (type == 1 && pdev->revision > 0x7)
|
if (type == 1 && pdev->revision > 0x7)
|
||||||
type = 2;
|
type = 2;
|
||||||
|
|
||||||
|
/* Serenade ? */
|
||||||
|
if (type == 5 && pdev->subsystem_vendor == PCI_VENDOR_ID_AMD &&
|
||||||
|
pdev->subsystem_device == PCI_DEVICE_ID_AMD_SERENADE)
|
||||||
|
type = 6; /* UDMA 100 only */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Okay, type is determined now. Apply type-specific workarounds.
|
||||||
|
*/
|
||||||
|
pi = info[type];
|
||||||
|
|
||||||
|
if (type < 3)
|
||||||
|
ata_pci_clear_simplex(pdev);
|
||||||
|
|
||||||
/* Check for AMD7411 */
|
/* Check for AMD7411 */
|
||||||
if (type == 3)
|
if (type == 3)
|
||||||
/* FIFO is broken */
|
/* FIFO is broken */
|
||||||
@ -635,16 +692,17 @@ static int amd_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
|
|||||||
else
|
else
|
||||||
pci_write_config_byte(pdev, 0x41, fifo | 0xF0);
|
pci_write_config_byte(pdev, 0x41, fifo | 0xF0);
|
||||||
|
|
||||||
/* Serenade ? */
|
/* Cable detection on Nvidia chips doesn't work too well,
|
||||||
if (type == 5 && pdev->subsystem_vendor == PCI_VENDOR_ID_AMD &&
|
* cache BIOS programmed UDMA mode.
|
||||||
pdev->subsystem_device == PCI_DEVICE_ID_AMD_SERENADE)
|
*/
|
||||||
type = 6; /* UDMA 100 only */
|
if (type == 7 || type == 8) {
|
||||||
|
u32 udma;
|
||||||
|
|
||||||
if (type < 3)
|
pci_read_config_dword(pdev, 0x60, &udma);
|
||||||
ata_pci_clear_simplex(pdev);
|
pi.private_data = (void *)(unsigned long)udma;
|
||||||
|
}
|
||||||
|
|
||||||
/* And fire it up */
|
/* And fire it up */
|
||||||
ppi[0] = &info[type];
|
|
||||||
return ata_pci_init_one(pdev, ppi);
|
return ata_pci_init_one(pdev, ppi);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -832,6 +832,7 @@ static void bfin_bmdma_setup(struct ata_queued_cmd *qc)
|
|||||||
{
|
{
|
||||||
unsigned short config = WDSIZE_16;
|
unsigned short config = WDSIZE_16;
|
||||||
struct scatterlist *sg;
|
struct scatterlist *sg;
|
||||||
|
unsigned int si;
|
||||||
|
|
||||||
pr_debug("in atapi dma setup\n");
|
pr_debug("in atapi dma setup\n");
|
||||||
/* Program the ATA_CTRL register with dir */
|
/* Program the ATA_CTRL register with dir */
|
||||||
@ -839,7 +840,7 @@ static void bfin_bmdma_setup(struct ata_queued_cmd *qc)
|
|||||||
/* fill the ATAPI DMA controller */
|
/* fill the ATAPI DMA controller */
|
||||||
set_dma_config(CH_ATAPI_TX, config);
|
set_dma_config(CH_ATAPI_TX, config);
|
||||||
set_dma_x_modify(CH_ATAPI_TX, 2);
|
set_dma_x_modify(CH_ATAPI_TX, 2);
|
||||||
ata_for_each_sg(sg, qc) {
|
for_each_sg(qc->sg, sg, qc->n_elem, si) {
|
||||||
set_dma_start_addr(CH_ATAPI_TX, sg_dma_address(sg));
|
set_dma_start_addr(CH_ATAPI_TX, sg_dma_address(sg));
|
||||||
set_dma_x_count(CH_ATAPI_TX, sg_dma_len(sg) >> 1);
|
set_dma_x_count(CH_ATAPI_TX, sg_dma_len(sg) >> 1);
|
||||||
}
|
}
|
||||||
@ -848,7 +849,7 @@ static void bfin_bmdma_setup(struct ata_queued_cmd *qc)
|
|||||||
/* fill the ATAPI DMA controller */
|
/* fill the ATAPI DMA controller */
|
||||||
set_dma_config(CH_ATAPI_RX, config);
|
set_dma_config(CH_ATAPI_RX, config);
|
||||||
set_dma_x_modify(CH_ATAPI_RX, 2);
|
set_dma_x_modify(CH_ATAPI_RX, 2);
|
||||||
ata_for_each_sg(sg, qc) {
|
for_each_sg(qc->sg, sg, qc->n_elem, si) {
|
||||||
set_dma_start_addr(CH_ATAPI_RX, sg_dma_address(sg));
|
set_dma_start_addr(CH_ATAPI_RX, sg_dma_address(sg));
|
||||||
set_dma_x_count(CH_ATAPI_RX, sg_dma_len(sg) >> 1);
|
set_dma_x_count(CH_ATAPI_RX, sg_dma_len(sg) >> 1);
|
||||||
}
|
}
|
||||||
@ -867,6 +868,7 @@ static void bfin_bmdma_start(struct ata_queued_cmd *qc)
|
|||||||
struct ata_port *ap = qc->ap;
|
struct ata_port *ap = qc->ap;
|
||||||
void __iomem *base = (void __iomem *)ap->ioaddr.ctl_addr;
|
void __iomem *base = (void __iomem *)ap->ioaddr.ctl_addr;
|
||||||
struct scatterlist *sg;
|
struct scatterlist *sg;
|
||||||
|
unsigned int si;
|
||||||
|
|
||||||
pr_debug("in atapi dma start\n");
|
pr_debug("in atapi dma start\n");
|
||||||
if (!(ap->udma_mask || ap->mwdma_mask))
|
if (!(ap->udma_mask || ap->mwdma_mask))
|
||||||
@ -881,7 +883,7 @@ static void bfin_bmdma_start(struct ata_queued_cmd *qc)
|
|||||||
* data cache is enabled. Otherwise, this loop
|
* data cache is enabled. Otherwise, this loop
|
||||||
* is an empty loop and optimized out.
|
* is an empty loop and optimized out.
|
||||||
*/
|
*/
|
||||||
ata_for_each_sg(sg, qc) {
|
for_each_sg(qc->sg, sg, qc->n_elem, si) {
|
||||||
flush_dcache_range(sg_dma_address(sg),
|
flush_dcache_range(sg_dma_address(sg),
|
||||||
sg_dma_address(sg) + sg_dma_len(sg));
|
sg_dma_address(sg) + sg_dma_len(sg));
|
||||||
}
|
}
|
||||||
@ -910,7 +912,7 @@ static void bfin_bmdma_start(struct ata_queued_cmd *qc)
|
|||||||
ATAPI_SET_CONTROL(base, ATAPI_GET_CONTROL(base) | TFRCNT_RST);
|
ATAPI_SET_CONTROL(base, ATAPI_GET_CONTROL(base) | TFRCNT_RST);
|
||||||
|
|
||||||
/* Set transfer length to buffer len */
|
/* Set transfer length to buffer len */
|
||||||
ata_for_each_sg(sg, qc) {
|
for_each_sg(qc->sg, sg, qc->n_elem, si) {
|
||||||
ATAPI_SET_XFER_LEN(base, (sg_dma_len(sg) >> 1));
|
ATAPI_SET_XFER_LEN(base, (sg_dma_len(sg) >> 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -932,6 +934,7 @@ static void bfin_bmdma_stop(struct ata_queued_cmd *qc)
|
|||||||
{
|
{
|
||||||
struct ata_port *ap = qc->ap;
|
struct ata_port *ap = qc->ap;
|
||||||
struct scatterlist *sg;
|
struct scatterlist *sg;
|
||||||
|
unsigned int si;
|
||||||
|
|
||||||
pr_debug("in atapi dma stop\n");
|
pr_debug("in atapi dma stop\n");
|
||||||
if (!(ap->udma_mask || ap->mwdma_mask))
|
if (!(ap->udma_mask || ap->mwdma_mask))
|
||||||
@ -950,7 +953,7 @@ static void bfin_bmdma_stop(struct ata_queued_cmd *qc)
|
|||||||
* data cache is enabled. Otherwise, this loop
|
* data cache is enabled. Otherwise, this loop
|
||||||
* is an empty loop and optimized out.
|
* is an empty loop and optimized out.
|
||||||
*/
|
*/
|
||||||
ata_for_each_sg(sg, qc) {
|
for_each_sg(qc->sg, sg, qc->n_elem, si) {
|
||||||
invalidate_dcache_range(
|
invalidate_dcache_range(
|
||||||
sg_dma_address(sg),
|
sg_dma_address(sg),
|
||||||
sg_dma_address(sg)
|
sg_dma_address(sg)
|
||||||
@ -1167,34 +1170,36 @@ static unsigned char bfin_bmdma_status(struct ata_port *ap)
|
|||||||
* Note: Original code is ata_data_xfer().
|
* Note: Original code is ata_data_xfer().
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static void bfin_data_xfer(struct ata_device *adev, unsigned char *buf,
|
static unsigned int bfin_data_xfer(struct ata_device *dev, unsigned char *buf,
|
||||||
unsigned int buflen, int write_data)
|
unsigned int buflen, int rw)
|
||||||
{
|
{
|
||||||
struct ata_port *ap = adev->link->ap;
|
struct ata_port *ap = dev->link->ap;
|
||||||
unsigned int words = buflen >> 1;
|
|
||||||
unsigned short *buf16 = (u16 *) buf;
|
|
||||||
void __iomem *base = (void __iomem *)ap->ioaddr.ctl_addr;
|
void __iomem *base = (void __iomem *)ap->ioaddr.ctl_addr;
|
||||||
|
unsigned int words = buflen >> 1;
|
||||||
|
unsigned short *buf16 = (u16 *)buf;
|
||||||
|
|
||||||
/* Transfer multiple of 2 bytes */
|
/* Transfer multiple of 2 bytes */
|
||||||
if (write_data) {
|
if (rw == READ)
|
||||||
write_atapi_data(base, words, buf16);
|
|
||||||
} else {
|
|
||||||
read_atapi_data(base, words, buf16);
|
read_atapi_data(base, words, buf16);
|
||||||
}
|
else
|
||||||
|
write_atapi_data(base, words, buf16);
|
||||||
|
|
||||||
/* Transfer trailing 1 byte, if any. */
|
/* Transfer trailing 1 byte, if any. */
|
||||||
if (unlikely(buflen & 0x01)) {
|
if (unlikely(buflen & 0x01)) {
|
||||||
unsigned short align_buf[1] = { 0 };
|
unsigned short align_buf[1] = { 0 };
|
||||||
unsigned char *trailing_buf = buf + buflen - 1;
|
unsigned char *trailing_buf = buf + buflen - 1;
|
||||||
|
|
||||||
if (write_data) {
|
if (rw == READ) {
|
||||||
memcpy(align_buf, trailing_buf, 1);
|
|
||||||
write_atapi_data(base, 1, align_buf);
|
|
||||||
} else {
|
|
||||||
read_atapi_data(base, 1, align_buf);
|
read_atapi_data(base, 1, align_buf);
|
||||||
memcpy(trailing_buf, align_buf, 1);
|
memcpy(trailing_buf, align_buf, 1);
|
||||||
|
} else {
|
||||||
|
memcpy(align_buf, trailing_buf, 1);
|
||||||
|
write_atapi_data(base, 1, align_buf);
|
||||||
}
|
}
|
||||||
|
words++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return words << 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -198,7 +198,7 @@ static int __devinit cs5520_init_one(struct pci_dev *pdev, const struct pci_devi
|
|||||||
};
|
};
|
||||||
const struct ata_port_info *ppi[2];
|
const struct ata_port_info *ppi[2];
|
||||||
u8 pcicfg;
|
u8 pcicfg;
|
||||||
void *iomap[5];
|
void __iomem *iomap[5];
|
||||||
struct ata_host *host;
|
struct ata_host *host;
|
||||||
struct ata_ioports *ioaddr;
|
struct ata_ioports *ioaddr;
|
||||||
int i, rc;
|
int i, rc;
|
||||||
|
@ -847,15 +847,16 @@ static u32 hpt374_read_freq(struct pci_dev *pdev)
|
|||||||
u32 freq;
|
u32 freq;
|
||||||
unsigned long io_base = pci_resource_start(pdev, 4);
|
unsigned long io_base = pci_resource_start(pdev, 4);
|
||||||
if (PCI_FUNC(pdev->devfn) & 1) {
|
if (PCI_FUNC(pdev->devfn) & 1) {
|
||||||
struct pci_dev *pdev_0 = pci_get_slot(pdev->bus, pdev->devfn - 1);
|
struct pci_dev *pdev_0;
|
||||||
|
|
||||||
|
pdev_0 = pci_get_slot(pdev->bus, pdev->devfn - 1);
|
||||||
/* Someone hot plugged the controller on us ? */
|
/* Someone hot plugged the controller on us ? */
|
||||||
if (pdev_0 == NULL)
|
if (pdev_0 == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
io_base = pci_resource_start(pdev_0, 4);
|
io_base = pci_resource_start(pdev_0, 4);
|
||||||
freq = inl(io_base + 0x90);
|
freq = inl(io_base + 0x90);
|
||||||
pci_dev_put(pdev_0);
|
pci_dev_put(pdev_0);
|
||||||
}
|
} else
|
||||||
else
|
|
||||||
freq = inl(io_base + 0x90);
|
freq = inl(io_base + 0x90);
|
||||||
return freq;
|
return freq;
|
||||||
}
|
}
|
||||||
|
@ -224,6 +224,7 @@ static void pata_icside_bmdma_setup(struct ata_queued_cmd *qc)
|
|||||||
struct pata_icside_state *state = ap->host->private_data;
|
struct pata_icside_state *state = ap->host->private_data;
|
||||||
struct scatterlist *sg, *rsg = state->sg;
|
struct scatterlist *sg, *rsg = state->sg;
|
||||||
unsigned int write = qc->tf.flags & ATA_TFLAG_WRITE;
|
unsigned int write = qc->tf.flags & ATA_TFLAG_WRITE;
|
||||||
|
unsigned int si;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We are simplex; BUG if we try to fiddle with DMA
|
* We are simplex; BUG if we try to fiddle with DMA
|
||||||
@ -234,7 +235,7 @@ static void pata_icside_bmdma_setup(struct ata_queued_cmd *qc)
|
|||||||
/*
|
/*
|
||||||
* Copy ATAs scattered sg list into a contiguous array of sg
|
* Copy ATAs scattered sg list into a contiguous array of sg
|
||||||
*/
|
*/
|
||||||
ata_for_each_sg(sg, qc) {
|
for_each_sg(qc->sg, sg, qc->n_elem, si) {
|
||||||
memcpy(rsg, sg, sizeof(*sg));
|
memcpy(rsg, sg, sizeof(*sg));
|
||||||
rsg++;
|
rsg++;
|
||||||
}
|
}
|
||||||
|
@ -430,7 +430,7 @@ static unsigned int it821x_smart_qc_issue_prot(struct ata_queued_cmd *qc)
|
|||||||
return ata_qc_issue_prot(qc);
|
return ata_qc_issue_prot(qc);
|
||||||
}
|
}
|
||||||
printk(KERN_DEBUG "it821x: can't process command 0x%02X\n", qc->tf.command);
|
printk(KERN_DEBUG "it821x: can't process command 0x%02X\n", qc->tf.command);
|
||||||
return AC_ERR_INVALID;
|
return AC_ERR_DEV;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -516,6 +516,37 @@ static void it821x_dev_config(struct ata_device *adev)
|
|||||||
printk("(%dK stripe)", adev->id[146]);
|
printk("(%dK stripe)", adev->id[146]);
|
||||||
printk(".\n");
|
printk(".\n");
|
||||||
}
|
}
|
||||||
|
/* This is a controller firmware triggered funny, don't
|
||||||
|
report the drive faulty! */
|
||||||
|
adev->horkage &= ~ATA_HORKAGE_DIAGNOSTIC;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* it821x_ident_hack - Hack identify data up
|
||||||
|
* @ap: Port
|
||||||
|
*
|
||||||
|
* Walk the devices on this firmware driven port and slightly
|
||||||
|
* mash the identify data to stop us and common tools trying to
|
||||||
|
* use features not firmware supported. The firmware itself does
|
||||||
|
* some masking (eg SMART) but not enough.
|
||||||
|
*
|
||||||
|
* This is a bit of an abuse of the cable method, but it is the
|
||||||
|
* only method called at the right time. We could modify the libata
|
||||||
|
* core specifically for ident hacking but while we have one offender
|
||||||
|
* it seems better to keep the fallout localised.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static int it821x_ident_hack(struct ata_port *ap)
|
||||||
|
{
|
||||||
|
struct ata_device *adev;
|
||||||
|
ata_link_for_each_dev(adev, &ap->link) {
|
||||||
|
if (ata_dev_enabled(adev)) {
|
||||||
|
adev->id[84] &= ~(1 << 6); /* No FUA */
|
||||||
|
adev->id[85] &= ~(1 << 10); /* No HPA */
|
||||||
|
adev->id[76] = 0; /* No NCQ/AN etc */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ata_cable_unknown(ap);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -634,7 +665,7 @@ static struct ata_port_operations it821x_smart_port_ops = {
|
|||||||
.thaw = ata_bmdma_thaw,
|
.thaw = ata_bmdma_thaw,
|
||||||
.error_handler = ata_bmdma_error_handler,
|
.error_handler = ata_bmdma_error_handler,
|
||||||
.post_internal_cmd = ata_bmdma_post_internal_cmd,
|
.post_internal_cmd = ata_bmdma_post_internal_cmd,
|
||||||
.cable_detect = ata_cable_unknown,
|
.cable_detect = it821x_ident_hack,
|
||||||
|
|
||||||
.bmdma_setup = ata_bmdma_setup,
|
.bmdma_setup = ata_bmdma_setup,
|
||||||
.bmdma_start = ata_bmdma_start,
|
.bmdma_start = ata_bmdma_start,
|
||||||
|
@ -42,13 +42,13 @@ static int ixp4xx_set_mode(struct ata_link *link, struct ata_device **error)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ixp4xx_mmio_data_xfer(struct ata_device *adev, unsigned char *buf,
|
static unsigned int ixp4xx_mmio_data_xfer(struct ata_device *dev,
|
||||||
unsigned int buflen, int write_data)
|
unsigned char *buf, unsigned int buflen, int rw)
|
||||||
{
|
{
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
unsigned int words = buflen >> 1;
|
unsigned int words = buflen >> 1;
|
||||||
u16 *buf16 = (u16 *) buf;
|
u16 *buf16 = (u16 *) buf;
|
||||||
struct ata_port *ap = adev->link->ap;
|
struct ata_port *ap = dev->link->ap;
|
||||||
void __iomem *mmio = ap->ioaddr.data_addr;
|
void __iomem *mmio = ap->ioaddr.data_addr;
|
||||||
struct ixp4xx_pata_data *data = ap->host->dev->platform_data;
|
struct ixp4xx_pata_data *data = ap->host->dev->platform_data;
|
||||||
|
|
||||||
@ -59,30 +59,32 @@ static void ixp4xx_mmio_data_xfer(struct ata_device *adev, unsigned char *buf,
|
|||||||
udelay(100);
|
udelay(100);
|
||||||
|
|
||||||
/* Transfer multiple of 2 bytes */
|
/* Transfer multiple of 2 bytes */
|
||||||
if (write_data) {
|
if (rw == READ)
|
||||||
for (i = 0; i < words; i++)
|
|
||||||
writew(buf16[i], mmio);
|
|
||||||
} else {
|
|
||||||
for (i = 0; i < words; i++)
|
for (i = 0; i < words; i++)
|
||||||
buf16[i] = readw(mmio);
|
buf16[i] = readw(mmio);
|
||||||
}
|
else
|
||||||
|
for (i = 0; i < words; i++)
|
||||||
|
writew(buf16[i], mmio);
|
||||||
|
|
||||||
/* Transfer trailing 1 byte, if any. */
|
/* Transfer trailing 1 byte, if any. */
|
||||||
if (unlikely(buflen & 0x01)) {
|
if (unlikely(buflen & 0x01)) {
|
||||||
u16 align_buf[1] = { 0 };
|
u16 align_buf[1] = { 0 };
|
||||||
unsigned char *trailing_buf = buf + buflen - 1;
|
unsigned char *trailing_buf = buf + buflen - 1;
|
||||||
|
|
||||||
if (write_data) {
|
if (rw == READ) {
|
||||||
memcpy(align_buf, trailing_buf, 1);
|
|
||||||
writew(align_buf[0], mmio);
|
|
||||||
} else {
|
|
||||||
align_buf[0] = readw(mmio);
|
align_buf[0] = readw(mmio);
|
||||||
memcpy(trailing_buf, align_buf, 1);
|
memcpy(trailing_buf, align_buf, 1);
|
||||||
|
} else {
|
||||||
|
memcpy(align_buf, trailing_buf, 1);
|
||||||
|
writew(align_buf[0], mmio);
|
||||||
}
|
}
|
||||||
|
words++;
|
||||||
}
|
}
|
||||||
|
|
||||||
udelay(100);
|
udelay(100);
|
||||||
*data->cs0_cfg |= 0x01;
|
*data->cs0_cfg |= 0x01;
|
||||||
|
|
||||||
|
return words << 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct scsi_host_template ixp4xx_sht = {
|
static struct scsi_host_template ixp4xx_sht = {
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -364,7 +364,7 @@ mpc52xx_ata_probe(struct of_device *op, const struct of_device_id *match)
|
|||||||
{
|
{
|
||||||
unsigned int ipb_freq;
|
unsigned int ipb_freq;
|
||||||
struct resource res_mem;
|
struct resource res_mem;
|
||||||
int ata_irq = NO_IRQ;
|
int ata_irq;
|
||||||
struct mpc52xx_ata __iomem *ata_regs;
|
struct mpc52xx_ata __iomem *ata_regs;
|
||||||
struct mpc52xx_ata_priv *priv;
|
struct mpc52xx_ata_priv *priv;
|
||||||
int rv;
|
int rv;
|
||||||
|
214
drivers/ata/pata_ninja32.c
Normal file
214
drivers/ata/pata_ninja32.c
Normal file
@ -0,0 +1,214 @@
|
|||||||
|
/*
|
||||||
|
* pata_ninja32.c - Ninja32 PATA for new ATA layer
|
||||||
|
* (C) 2007 Red Hat Inc
|
||||||
|
* Alan Cox <alan@redhat.com>
|
||||||
|
*
|
||||||
|
* Note: The controller like many controllers has shared timings for
|
||||||
|
* PIO and DMA. We thus flip to the DMA timings in dma_start and flip back
|
||||||
|
* in the dma_stop function. Thus we actually don't need a set_dmamode
|
||||||
|
* method as the PIO method is always called and will set the right PIO
|
||||||
|
* timing parameters.
|
||||||
|
*
|
||||||
|
* The Ninja32 Cardbus is not a generic SFF controller. Instead it is
|
||||||
|
* laid out as follows off BAR 0. This is based upon Mark Lord's delkin
|
||||||
|
* driver and the extensive analysis done by the BSD developers, notably
|
||||||
|
* ITOH Yasufumi.
|
||||||
|
*
|
||||||
|
* Base + 0x00 IRQ Status
|
||||||
|
* Base + 0x01 IRQ control
|
||||||
|
* Base + 0x02 Chipset control
|
||||||
|
* Base + 0x04 VDMA and reset control + wait bits
|
||||||
|
* Base + 0x08 BMIMBA
|
||||||
|
* Base + 0x0C DMA Length
|
||||||
|
* Base + 0x10 Taskfile
|
||||||
|
* Base + 0x18 BMDMA Status ?
|
||||||
|
* Base + 0x1C
|
||||||
|
* Base + 0x1D Bus master control
|
||||||
|
* bit 0 = enable
|
||||||
|
* bit 1 = 0 write/1 read
|
||||||
|
* bit 2 = 1 sgtable
|
||||||
|
* bit 3 = go
|
||||||
|
* bit 4-6 wait bits
|
||||||
|
* bit 7 = done
|
||||||
|
* Base + 0x1E AltStatus
|
||||||
|
* Base + 0x1F timing register
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/kernel.h>
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/pci.h>
|
||||||
|
#include <linux/init.h>
|
||||||
|
#include <linux/blkdev.h>
|
||||||
|
#include <linux/delay.h>
|
||||||
|
#include <scsi/scsi_host.h>
|
||||||
|
#include <linux/libata.h>
|
||||||
|
|
||||||
|
#define DRV_NAME "pata_ninja32"
|
||||||
|
#define DRV_VERSION "0.0.1"
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ninja32_set_piomode - set initial PIO mode data
|
||||||
|
* @ap: ATA interface
|
||||||
|
* @adev: ATA device
|
||||||
|
*
|
||||||
|
* Called to do the PIO mode setup. Our timing registers are shared
|
||||||
|
* but we want to set the PIO timing by default.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static void ninja32_set_piomode(struct ata_port *ap, struct ata_device *adev)
|
||||||
|
{
|
||||||
|
static u16 pio_timing[5] = {
|
||||||
|
0xd6, 0x85, 0x44, 0x33, 0x13
|
||||||
|
};
|
||||||
|
iowrite8(pio_timing[adev->pio_mode - XFER_PIO_0],
|
||||||
|
ap->ioaddr.bmdma_addr + 0x1f);
|
||||||
|
ap->private_data = adev;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void ninja32_dev_select(struct ata_port *ap, unsigned int device)
|
||||||
|
{
|
||||||
|
struct ata_device *adev = &ap->link.device[device];
|
||||||
|
if (ap->private_data != adev) {
|
||||||
|
iowrite8(0xd6, ap->ioaddr.bmdma_addr + 0x1f);
|
||||||
|
ata_std_dev_select(ap, device);
|
||||||
|
ninja32_set_piomode(ap, adev);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct scsi_host_template ninja32_sht = {
|
||||||
|
.module = THIS_MODULE,
|
||||||
|
.name = DRV_NAME,
|
||||||
|
.ioctl = ata_scsi_ioctl,
|
||||||
|
.queuecommand = ata_scsi_queuecmd,
|
||||||
|
.can_queue = ATA_DEF_QUEUE,
|
||||||
|
.this_id = ATA_SHT_THIS_ID,
|
||||||
|
.sg_tablesize = LIBATA_MAX_PRD,
|
||||||
|
.cmd_per_lun = ATA_SHT_CMD_PER_LUN,
|
||||||
|
.emulated = ATA_SHT_EMULATED,
|
||||||
|
.use_clustering = ATA_SHT_USE_CLUSTERING,
|
||||||
|
.proc_name = DRV_NAME,
|
||||||
|
.dma_boundary = ATA_DMA_BOUNDARY,
|
||||||
|
.slave_configure = ata_scsi_slave_config,
|
||||||
|
.slave_destroy = ata_scsi_slave_destroy,
|
||||||
|
.bios_param = ata_std_bios_param,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct ata_port_operations ninja32_port_ops = {
|
||||||
|
.set_piomode = ninja32_set_piomode,
|
||||||
|
.mode_filter = ata_pci_default_filter,
|
||||||
|
|
||||||
|
.tf_load = ata_tf_load,
|
||||||
|
.tf_read = ata_tf_read,
|
||||||
|
.check_status = ata_check_status,
|
||||||
|
.exec_command = ata_exec_command,
|
||||||
|
.dev_select = ninja32_dev_select,
|
||||||
|
|
||||||
|
.freeze = ata_bmdma_freeze,
|
||||||
|
.thaw = ata_bmdma_thaw,
|
||||||
|
.error_handler = ata_bmdma_error_handler,
|
||||||
|
.post_internal_cmd = ata_bmdma_post_internal_cmd,
|
||||||
|
.cable_detect = ata_cable_40wire,
|
||||||
|
|
||||||
|
.bmdma_setup = ata_bmdma_setup,
|
||||||
|
.bmdma_start = ata_bmdma_start,
|
||||||
|
.bmdma_stop = ata_bmdma_stop,
|
||||||
|
.bmdma_status = ata_bmdma_status,
|
||||||
|
|
||||||
|
.qc_prep = ata_qc_prep,
|
||||||
|
.qc_issue = ata_qc_issue_prot,
|
||||||
|
|
||||||
|
.data_xfer = ata_data_xfer,
|
||||||
|
|
||||||
|
.irq_handler = ata_interrupt,
|
||||||
|
.irq_clear = ata_bmdma_irq_clear,
|
||||||
|
.irq_on = ata_irq_on,
|
||||||
|
|
||||||
|
.port_start = ata_sff_port_start,
|
||||||
|
};
|
||||||
|
|
||||||
|
static int ninja32_init_one(struct pci_dev *dev, const struct pci_device_id *id)
|
||||||
|
{
|
||||||
|
struct ata_host *host;
|
||||||
|
struct ata_port *ap;
|
||||||
|
void __iomem *base;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
host = ata_host_alloc(&dev->dev, 1);
|
||||||
|
if (!host)
|
||||||
|
return -ENOMEM;
|
||||||
|
ap = host->ports[0];
|
||||||
|
|
||||||
|
/* Set up the PCI device */
|
||||||
|
rc = pcim_enable_device(dev);
|
||||||
|
if (rc)
|
||||||
|
return rc;
|
||||||
|
rc = pcim_iomap_regions(dev, 1 << 0, DRV_NAME);
|
||||||
|
if (rc == -EBUSY)
|
||||||
|
pcim_pin_device(dev);
|
||||||
|
if (rc)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
host->iomap = pcim_iomap_table(dev);
|
||||||
|
rc = pci_set_dma_mask(dev, ATA_DMA_MASK);
|
||||||
|
if (rc)
|
||||||
|
return rc;
|
||||||
|
rc = pci_set_consistent_dma_mask(dev, ATA_DMA_MASK);
|
||||||
|
if (rc)
|
||||||
|
return rc;
|
||||||
|
pci_set_master(dev);
|
||||||
|
|
||||||
|
/* Set up the register mappings */
|
||||||
|
base = host->iomap[0];
|
||||||
|
if (!base)
|
||||||
|
return -ENOMEM;
|
||||||
|
ap->ops = &ninja32_port_ops;
|
||||||
|
ap->pio_mask = 0x1F;
|
||||||
|
ap->flags |= ATA_FLAG_SLAVE_POSS;
|
||||||
|
|
||||||
|
ap->ioaddr.cmd_addr = base + 0x10;
|
||||||
|
ap->ioaddr.ctl_addr = base + 0x1E;
|
||||||
|
ap->ioaddr.altstatus_addr = base + 0x1E;
|
||||||
|
ap->ioaddr.bmdma_addr = base;
|
||||||
|
ata_std_ports(&ap->ioaddr);
|
||||||
|
|
||||||
|
iowrite8(0x05, base + 0x01); /* Enable interrupt lines */
|
||||||
|
iowrite8(0xB3, base + 0x02); /* Burst, ?? setup */
|
||||||
|
iowrite8(0x00, base + 0x04); /* WAIT0 ? */
|
||||||
|
/* FIXME: Should we disable them at remove ? */
|
||||||
|
return ata_host_activate(host, dev->irq, ata_interrupt,
|
||||||
|
IRQF_SHARED, &ninja32_sht);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct pci_device_id ninja32[] = {
|
||||||
|
{ 0x1145, 0xf021, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
|
||||||
|
{ 0x1145, 0xf024, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
|
||||||
|
{ },
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct pci_driver ninja32_pci_driver = {
|
||||||
|
.name = DRV_NAME,
|
||||||
|
.id_table = ninja32,
|
||||||
|
.probe = ninja32_init_one,
|
||||||
|
.remove = ata_pci_remove_one
|
||||||
|
};
|
||||||
|
|
||||||
|
static int __init ninja32_init(void)
|
||||||
|
{
|
||||||
|
return pci_register_driver(&ninja32_pci_driver);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __exit ninja32_exit(void)
|
||||||
|
{
|
||||||
|
pci_unregister_driver(&ninja32_pci_driver);
|
||||||
|
}
|
||||||
|
|
||||||
|
MODULE_AUTHOR("Alan Cox");
|
||||||
|
MODULE_DESCRIPTION("low-level driver for Ninja32 ATA");
|
||||||
|
MODULE_LICENSE("GPL");
|
||||||
|
MODULE_DEVICE_TABLE(pci, ninja32);
|
||||||
|
MODULE_VERSION(DRV_VERSION);
|
||||||
|
|
||||||
|
module_init(ninja32_init);
|
||||||
|
module_exit(ninja32_exit);
|
@ -42,7 +42,7 @@
|
|||||||
|
|
||||||
|
|
||||||
#define DRV_NAME "pata_pcmcia"
|
#define DRV_NAME "pata_pcmcia"
|
||||||
#define DRV_VERSION "0.3.2"
|
#define DRV_VERSION "0.3.3"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Private data structure to glue stuff together
|
* Private data structure to glue stuff together
|
||||||
@ -86,6 +86,47 @@ static int pcmcia_set_mode(struct ata_link *link, struct ata_device **r_failed_d
|
|||||||
return ata_do_set_mode(link, r_failed_dev);
|
return ata_do_set_mode(link, r_failed_dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* pcmcia_set_mode_8bit - PCMCIA specific mode setup
|
||||||
|
* @link: link
|
||||||
|
* @r_failed_dev: Return pointer for failed device
|
||||||
|
*
|
||||||
|
* For the simple emulated 8bit stuff the less we do the better.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static int pcmcia_set_mode_8bit(struct ata_link *link,
|
||||||
|
struct ata_device **r_failed_dev)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ata_data_xfer_8bit - Transfer data by 8bit PIO
|
||||||
|
* @dev: device to target
|
||||||
|
* @buf: data buffer
|
||||||
|
* @buflen: buffer length
|
||||||
|
* @rw: read/write
|
||||||
|
*
|
||||||
|
* Transfer data from/to the device data register by 8 bit PIO.
|
||||||
|
*
|
||||||
|
* LOCKING:
|
||||||
|
* Inherited from caller.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static unsigned int ata_data_xfer_8bit(struct ata_device *dev,
|
||||||
|
unsigned char *buf, unsigned int buflen, int rw)
|
||||||
|
{
|
||||||
|
struct ata_port *ap = dev->link->ap;
|
||||||
|
|
||||||
|
if (rw == READ)
|
||||||
|
ioread8_rep(ap->ioaddr.data_addr, buf, buflen);
|
||||||
|
else
|
||||||
|
iowrite8_rep(ap->ioaddr.data_addr, buf, buflen);
|
||||||
|
|
||||||
|
return buflen;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static struct scsi_host_template pcmcia_sht = {
|
static struct scsi_host_template pcmcia_sht = {
|
||||||
.module = THIS_MODULE,
|
.module = THIS_MODULE,
|
||||||
.name = DRV_NAME,
|
.name = DRV_NAME,
|
||||||
@ -129,6 +170,31 @@ static struct ata_port_operations pcmcia_port_ops = {
|
|||||||
.port_start = ata_sff_port_start,
|
.port_start = ata_sff_port_start,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static struct ata_port_operations pcmcia_8bit_port_ops = {
|
||||||
|
.set_mode = pcmcia_set_mode_8bit,
|
||||||
|
.tf_load = ata_tf_load,
|
||||||
|
.tf_read = ata_tf_read,
|
||||||
|
.check_status = ata_check_status,
|
||||||
|
.exec_command = ata_exec_command,
|
||||||
|
.dev_select = ata_std_dev_select,
|
||||||
|
|
||||||
|
.freeze = ata_bmdma_freeze,
|
||||||
|
.thaw = ata_bmdma_thaw,
|
||||||
|
.error_handler = ata_bmdma_error_handler,
|
||||||
|
.post_internal_cmd = ata_bmdma_post_internal_cmd,
|
||||||
|
.cable_detect = ata_cable_40wire,
|
||||||
|
|
||||||
|
.qc_prep = ata_qc_prep,
|
||||||
|
.qc_issue = ata_qc_issue_prot,
|
||||||
|
|
||||||
|
.data_xfer = ata_data_xfer_8bit,
|
||||||
|
|
||||||
|
.irq_clear = ata_bmdma_irq_clear,
|
||||||
|
.irq_on = ata_irq_on,
|
||||||
|
|
||||||
|
.port_start = ata_sff_port_start,
|
||||||
|
};
|
||||||
|
|
||||||
#define CS_CHECK(fn, ret) \
|
#define CS_CHECK(fn, ret) \
|
||||||
do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
|
do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
|
||||||
|
|
||||||
@ -153,9 +219,12 @@ static int pcmcia_init_one(struct pcmcia_device *pdev)
|
|||||||
cistpl_cftable_entry_t dflt;
|
cistpl_cftable_entry_t dflt;
|
||||||
} *stk = NULL;
|
} *stk = NULL;
|
||||||
cistpl_cftable_entry_t *cfg;
|
cistpl_cftable_entry_t *cfg;
|
||||||
int pass, last_ret = 0, last_fn = 0, is_kme = 0, ret = -ENOMEM;
|
int pass, last_ret = 0, last_fn = 0, is_kme = 0, ret = -ENOMEM, p;
|
||||||
unsigned long io_base, ctl_base;
|
unsigned long io_base, ctl_base;
|
||||||
void __iomem *io_addr, *ctl_addr;
|
void __iomem *io_addr, *ctl_addr;
|
||||||
|
int n_ports = 1;
|
||||||
|
|
||||||
|
struct ata_port_operations *ops = &pcmcia_port_ops;
|
||||||
|
|
||||||
info = kzalloc(sizeof(*info), GFP_KERNEL);
|
info = kzalloc(sizeof(*info), GFP_KERNEL);
|
||||||
if (info == NULL)
|
if (info == NULL)
|
||||||
@ -282,27 +351,32 @@ static int pcmcia_init_one(struct pcmcia_device *pdev)
|
|||||||
/* FIXME: Could be more ports at base + 0x10 but we only deal with
|
/* FIXME: Could be more ports at base + 0x10 but we only deal with
|
||||||
one right now */
|
one right now */
|
||||||
if (pdev->io.NumPorts1 >= 0x20)
|
if (pdev->io.NumPorts1 >= 0x20)
|
||||||
printk(KERN_WARNING DRV_NAME ": second channel not yet supported.\n");
|
n_ports = 2;
|
||||||
|
|
||||||
|
if (pdev->manf_id == 0x0097 && pdev->card_id == 0x1620)
|
||||||
|
ops = &pcmcia_8bit_port_ops;
|
||||||
/*
|
/*
|
||||||
* Having done the PCMCIA plumbing the ATA side is relatively
|
* Having done the PCMCIA plumbing the ATA side is relatively
|
||||||
* sane.
|
* sane.
|
||||||
*/
|
*/
|
||||||
ret = -ENOMEM;
|
ret = -ENOMEM;
|
||||||
host = ata_host_alloc(&pdev->dev, 1);
|
host = ata_host_alloc(&pdev->dev, n_ports);
|
||||||
if (!host)
|
if (!host)
|
||||||
goto failed;
|
goto failed;
|
||||||
ap = host->ports[0];
|
|
||||||
|
|
||||||
ap->ops = &pcmcia_port_ops;
|
for (p = 0; p < n_ports; p++) {
|
||||||
ap->pio_mask = 1; /* ISA so PIO 0 cycles */
|
ap = host->ports[p];
|
||||||
ap->flags |= ATA_FLAG_SLAVE_POSS;
|
|
||||||
ap->ioaddr.cmd_addr = io_addr;
|
|
||||||
ap->ioaddr.altstatus_addr = ctl_addr;
|
|
||||||
ap->ioaddr.ctl_addr = ctl_addr;
|
|
||||||
ata_std_ports(&ap->ioaddr);
|
|
||||||
|
|
||||||
ata_port_desc(ap, "cmd 0x%lx ctl 0x%lx", io_base, ctl_base);
|
ap->ops = ops;
|
||||||
|
ap->pio_mask = 1; /* ISA so PIO 0 cycles */
|
||||||
|
ap->flags |= ATA_FLAG_SLAVE_POSS;
|
||||||
|
ap->ioaddr.cmd_addr = io_addr + 0x10 * p;
|
||||||
|
ap->ioaddr.altstatus_addr = ctl_addr + 0x10 * p;
|
||||||
|
ap->ioaddr.ctl_addr = ctl_addr + 0x10 * p;
|
||||||
|
ata_std_ports(&ap->ioaddr);
|
||||||
|
|
||||||
|
ata_port_desc(ap, "cmd 0x%lx ctl 0x%lx", io_base, ctl_base);
|
||||||
|
}
|
||||||
|
|
||||||
/* activate */
|
/* activate */
|
||||||
ret = ata_host_activate(host, pdev->irq.AssignedIRQ, ata_interrupt,
|
ret = ata_host_activate(host, pdev->irq.AssignedIRQ, ata_interrupt,
|
||||||
@ -360,6 +434,7 @@ static struct pcmcia_device_id pcmcia_devices[] = {
|
|||||||
PCMCIA_DEVICE_MANF_CARD(0x0032, 0x0704),
|
PCMCIA_DEVICE_MANF_CARD(0x0032, 0x0704),
|
||||||
PCMCIA_DEVICE_MANF_CARD(0x0032, 0x2904),
|
PCMCIA_DEVICE_MANF_CARD(0x0032, 0x2904),
|
||||||
PCMCIA_DEVICE_MANF_CARD(0x0045, 0x0401), /* SanDisk CFA */
|
PCMCIA_DEVICE_MANF_CARD(0x0045, 0x0401), /* SanDisk CFA */
|
||||||
|
PCMCIA_DEVICE_MANF_CARD(0x0097, 0x1620), /* TI emulated */
|
||||||
PCMCIA_DEVICE_MANF_CARD(0x0098, 0x0000), /* Toshiba */
|
PCMCIA_DEVICE_MANF_CARD(0x0098, 0x0000), /* Toshiba */
|
||||||
PCMCIA_DEVICE_MANF_CARD(0x00a4, 0x002d),
|
PCMCIA_DEVICE_MANF_CARD(0x00a4, 0x002d),
|
||||||
PCMCIA_DEVICE_MANF_CARD(0x00ce, 0x0000), /* Samsung */
|
PCMCIA_DEVICE_MANF_CARD(0x00ce, 0x0000), /* Samsung */
|
||||||
|
@ -348,7 +348,7 @@ static unsigned long pdc2027x_mode_filter(struct ata_device *adev, unsigned long
|
|||||||
ata_id_c_string(pair->id, model_num, ATA_ID_PROD,
|
ata_id_c_string(pair->id, model_num, ATA_ID_PROD,
|
||||||
ATA_ID_PROD_LEN + 1);
|
ATA_ID_PROD_LEN + 1);
|
||||||
/* If the master is a maxtor in UDMA6 then the slave should not use UDMA 6 */
|
/* If the master is a maxtor in UDMA6 then the slave should not use UDMA 6 */
|
||||||
if (strstr(model_num, "Maxtor") == 0 && pair->dma_mode == XFER_UDMA_6)
|
if (strstr(model_num, "Maxtor") == NULL && pair->dma_mode == XFER_UDMA_6)
|
||||||
mask &= ~ (1 << (6 + ATA_SHIFT_UDMA));
|
mask &= ~ (1 << (6 + ATA_SHIFT_UDMA));
|
||||||
|
|
||||||
return ata_pci_default_filter(adev, mask);
|
return ata_pci_default_filter(adev, mask);
|
||||||
|
@ -168,8 +168,7 @@ static void pdc2026x_bmdma_start(struct ata_queued_cmd *qc)
|
|||||||
pdc202xx_set_dmamode(ap, qc->dev);
|
pdc202xx_set_dmamode(ap, qc->dev);
|
||||||
|
|
||||||
/* Cases the state machine will not complete correctly without help */
|
/* Cases the state machine will not complete correctly without help */
|
||||||
if ((tf->flags & ATA_TFLAG_LBA48) || tf->protocol == ATA_PROT_ATAPI_DMA)
|
if ((tf->flags & ATA_TFLAG_LBA48) || tf->protocol == ATAPI_PROT_DMA) {
|
||||||
{
|
|
||||||
len = qc->nbytes / 2;
|
len = qc->nbytes / 2;
|
||||||
|
|
||||||
if (tf->flags & ATA_TFLAG_WRITE)
|
if (tf->flags & ATA_TFLAG_WRITE)
|
||||||
@ -208,7 +207,7 @@ static void pdc2026x_bmdma_stop(struct ata_queued_cmd *qc)
|
|||||||
void __iomem *atapi_reg = master + 0x20 + (4 * ap->port_no);
|
void __iomem *atapi_reg = master + 0x20 + (4 * ap->port_no);
|
||||||
|
|
||||||
/* Cases the state machine will not complete correctly */
|
/* Cases the state machine will not complete correctly */
|
||||||
if (tf->protocol == ATA_PROT_ATAPI_DMA || ( tf->flags & ATA_TFLAG_LBA48)) {
|
if (tf->protocol == ATAPI_PROT_DMA || (tf->flags & ATA_TFLAG_LBA48)) {
|
||||||
iowrite32(0, atapi_reg);
|
iowrite32(0, atapi_reg);
|
||||||
iowrite8(ioread8(clock) & ~sel66, clock);
|
iowrite8(ioread8(clock) & ~sel66, clock);
|
||||||
}
|
}
|
||||||
|
@ -124,29 +124,33 @@ static unsigned int qdi_qc_issue_prot(struct ata_queued_cmd *qc)
|
|||||||
return ata_qc_issue_prot(qc);
|
return ata_qc_issue_prot(qc);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void qdi_data_xfer(struct ata_device *adev, unsigned char *buf, unsigned int buflen, int write_data)
|
static unsigned int qdi_data_xfer(struct ata_device *dev, unsigned char *buf,
|
||||||
|
unsigned int buflen, int rw)
|
||||||
{
|
{
|
||||||
struct ata_port *ap = adev->link->ap;
|
if (ata_id_has_dword_io(dev->id)) {
|
||||||
int slop = buflen & 3;
|
struct ata_port *ap = dev->link->ap;
|
||||||
|
int slop = buflen & 3;
|
||||||
|
|
||||||
if (ata_id_has_dword_io(adev->id)) {
|
if (rw == READ)
|
||||||
if (write_data)
|
|
||||||
iowrite32_rep(ap->ioaddr.data_addr, buf, buflen >> 2);
|
|
||||||
else
|
|
||||||
ioread32_rep(ap->ioaddr.data_addr, buf, buflen >> 2);
|
ioread32_rep(ap->ioaddr.data_addr, buf, buflen >> 2);
|
||||||
|
else
|
||||||
|
iowrite32_rep(ap->ioaddr.data_addr, buf, buflen >> 2);
|
||||||
|
|
||||||
if (unlikely(slop)) {
|
if (unlikely(slop)) {
|
||||||
__le32 pad = 0;
|
u32 pad;
|
||||||
if (write_data) {
|
if (rw == READ) {
|
||||||
memcpy(&pad, buf + buflen - slop, slop);
|
|
||||||
iowrite32(le32_to_cpu(pad), ap->ioaddr.data_addr);
|
|
||||||
} else {
|
|
||||||
pad = cpu_to_le32(ioread32(ap->ioaddr.data_addr));
|
pad = cpu_to_le32(ioread32(ap->ioaddr.data_addr));
|
||||||
memcpy(buf + buflen - slop, &pad, slop);
|
memcpy(buf + buflen - slop, &pad, slop);
|
||||||
|
} else {
|
||||||
|
memcpy(&pad, buf + buflen - slop, slop);
|
||||||
|
iowrite32(le32_to_cpu(pad), ap->ioaddr.data_addr);
|
||||||
}
|
}
|
||||||
|
buflen += 4 - slop;
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
ata_data_xfer(adev, buf, buflen, write_data);
|
buflen = ata_data_xfer(dev, buf, buflen, rw);
|
||||||
|
|
||||||
|
return buflen;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct scsi_host_template qdi_sht = {
|
static struct scsi_host_template qdi_sht = {
|
||||||
|
@ -768,45 +768,47 @@ static u8 scc_bmdma_status (struct ata_port *ap)
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* scc_data_xfer - Transfer data by PIO
|
* scc_data_xfer - Transfer data by PIO
|
||||||
* @adev: device for this I/O
|
* @dev: device for this I/O
|
||||||
* @buf: data buffer
|
* @buf: data buffer
|
||||||
* @buflen: buffer length
|
* @buflen: buffer length
|
||||||
* @write_data: read/write
|
* @rw: read/write
|
||||||
*
|
*
|
||||||
* Note: Original code is ata_data_xfer().
|
* Note: Original code is ata_data_xfer().
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static void scc_data_xfer (struct ata_device *adev, unsigned char *buf,
|
static unsigned int scc_data_xfer (struct ata_device *dev, unsigned char *buf,
|
||||||
unsigned int buflen, int write_data)
|
unsigned int buflen, int rw)
|
||||||
{
|
{
|
||||||
struct ata_port *ap = adev->link->ap;
|
struct ata_port *ap = dev->link->ap;
|
||||||
unsigned int words = buflen >> 1;
|
unsigned int words = buflen >> 1;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
u16 *buf16 = (u16 *) buf;
|
u16 *buf16 = (u16 *) buf;
|
||||||
void __iomem *mmio = ap->ioaddr.data_addr;
|
void __iomem *mmio = ap->ioaddr.data_addr;
|
||||||
|
|
||||||
/* Transfer multiple of 2 bytes */
|
/* Transfer multiple of 2 bytes */
|
||||||
if (write_data) {
|
if (rw == READ)
|
||||||
for (i = 0; i < words; i++)
|
|
||||||
out_be32(mmio, cpu_to_le16(buf16[i]));
|
|
||||||
} else {
|
|
||||||
for (i = 0; i < words; i++)
|
for (i = 0; i < words; i++)
|
||||||
buf16[i] = le16_to_cpu(in_be32(mmio));
|
buf16[i] = le16_to_cpu(in_be32(mmio));
|
||||||
}
|
else
|
||||||
|
for (i = 0; i < words; i++)
|
||||||
|
out_be32(mmio, cpu_to_le16(buf16[i]));
|
||||||
|
|
||||||
/* Transfer trailing 1 byte, if any. */
|
/* Transfer trailing 1 byte, if any. */
|
||||||
if (unlikely(buflen & 0x01)) {
|
if (unlikely(buflen & 0x01)) {
|
||||||
u16 align_buf[1] = { 0 };
|
u16 align_buf[1] = { 0 };
|
||||||
unsigned char *trailing_buf = buf + buflen - 1;
|
unsigned char *trailing_buf = buf + buflen - 1;
|
||||||
|
|
||||||
if (write_data) {
|
if (rw == READ) {
|
||||||
memcpy(align_buf, trailing_buf, 1);
|
|
||||||
out_be32(mmio, cpu_to_le16(align_buf[0]));
|
|
||||||
} else {
|
|
||||||
align_buf[0] = le16_to_cpu(in_be32(mmio));
|
align_buf[0] = le16_to_cpu(in_be32(mmio));
|
||||||
memcpy(trailing_buf, align_buf, 1);
|
memcpy(trailing_buf, align_buf, 1);
|
||||||
|
} else {
|
||||||
|
memcpy(align_buf, trailing_buf, 1);
|
||||||
|
out_be32(mmio, cpu_to_le16(align_buf[0]));
|
||||||
}
|
}
|
||||||
|
words++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return words << 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -41,7 +41,7 @@
|
|||||||
#include <linux/libata.h>
|
#include <linux/libata.h>
|
||||||
|
|
||||||
#define DRV_NAME "pata_serverworks"
|
#define DRV_NAME "pata_serverworks"
|
||||||
#define DRV_VERSION "0.4.2"
|
#define DRV_VERSION "0.4.3"
|
||||||
|
|
||||||
#define SVWKS_CSB5_REVISION_NEW 0x92 /* min PCI_REVISION_ID for UDMA5 (A2.0) */
|
#define SVWKS_CSB5_REVISION_NEW 0x92 /* min PCI_REVISION_ID for UDMA5 (A2.0) */
|
||||||
#define SVWKS_CSB6_REVISION 0xa0 /* min PCI_REVISION_ID for UDMA4 (A1.0) */
|
#define SVWKS_CSB6_REVISION 0xa0 /* min PCI_REVISION_ID for UDMA4 (A1.0) */
|
||||||
@ -102,7 +102,7 @@ static int osb4_cable(struct ata_port *ap) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* csb4_cable - CSB5/6 cable detect
|
* csb_cable - CSB5/6 cable detect
|
||||||
* @ap: ATA port to check
|
* @ap: ATA port to check
|
||||||
*
|
*
|
||||||
* Serverworks default arrangement is to use the drive side detection
|
* Serverworks default arrangement is to use the drive side detection
|
||||||
@ -110,7 +110,7 @@ static int osb4_cable(struct ata_port *ap) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
static int csb_cable(struct ata_port *ap) {
|
static int csb_cable(struct ata_port *ap) {
|
||||||
return ATA_CBL_PATA80;
|
return ATA_CBL_PATA_UNK;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct sv_cable_table {
|
struct sv_cable_table {
|
||||||
@ -231,7 +231,6 @@ static unsigned long serverworks_csb_filter(struct ata_device *adev, unsigned lo
|
|||||||
return ata_pci_default_filter(adev, mask);
|
return ata_pci_default_filter(adev, mask);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* serverworks_set_piomode - set initial PIO mode data
|
* serverworks_set_piomode - set initial PIO mode data
|
||||||
* @ap: ATA interface
|
* @ap: ATA interface
|
||||||
@ -243,7 +242,7 @@ static unsigned long serverworks_csb_filter(struct ata_device *adev, unsigned lo
|
|||||||
static void serverworks_set_piomode(struct ata_port *ap, struct ata_device *adev)
|
static void serverworks_set_piomode(struct ata_port *ap, struct ata_device *adev)
|
||||||
{
|
{
|
||||||
static const u8 pio_mode[] = { 0x5d, 0x47, 0x34, 0x22, 0x20 };
|
static const u8 pio_mode[] = { 0x5d, 0x47, 0x34, 0x22, 0x20 };
|
||||||
int offset = 1 + (2 * ap->port_no) - adev->devno;
|
int offset = 1 + 2 * ap->port_no - adev->devno;
|
||||||
int devbits = (2 * ap->port_no + adev->devno) * 4;
|
int devbits = (2 * ap->port_no + adev->devno) * 4;
|
||||||
u16 csb5_pio;
|
u16 csb5_pio;
|
||||||
struct pci_dev *pdev = to_pci_dev(ap->host->dev);
|
struct pci_dev *pdev = to_pci_dev(ap->host->dev);
|
||||||
|
@ -185,7 +185,8 @@ static int via_cable_detect(struct ata_port *ap) {
|
|||||||
if (ata66 & (0x10100000 >> (16 * ap->port_no)))
|
if (ata66 & (0x10100000 >> (16 * ap->port_no)))
|
||||||
return ATA_CBL_PATA80;
|
return ATA_CBL_PATA80;
|
||||||
/* Check with ACPI so we can spot BIOS reported SATA bridges */
|
/* Check with ACPI so we can spot BIOS reported SATA bridges */
|
||||||
if (ata_acpi_cbl_80wire(ap))
|
if (ata_acpi_init_gtm(ap) &&
|
||||||
|
ata_acpi_cbl_80wire(ap, ata_acpi_init_gtm(ap)))
|
||||||
return ATA_CBL_PATA80;
|
return ATA_CBL_PATA80;
|
||||||
return ATA_CBL_PATA40;
|
return ATA_CBL_PATA40;
|
||||||
}
|
}
|
||||||
|
@ -92,29 +92,33 @@ static void winbond_set_piomode(struct ata_port *ap, struct ata_device *adev)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void winbond_data_xfer(struct ata_device *adev, unsigned char *buf, unsigned int buflen, int write_data)
|
static unsigned int winbond_data_xfer(struct ata_device *dev,
|
||||||
|
unsigned char *buf, unsigned int buflen, int rw)
|
||||||
{
|
{
|
||||||
struct ata_port *ap = adev->link->ap;
|
struct ata_port *ap = dev->link->ap;
|
||||||
int slop = buflen & 3;
|
int slop = buflen & 3;
|
||||||
|
|
||||||
if (ata_id_has_dword_io(adev->id)) {
|
if (ata_id_has_dword_io(dev->id)) {
|
||||||
if (write_data)
|
if (rw == READ)
|
||||||
iowrite32_rep(ap->ioaddr.data_addr, buf, buflen >> 2);
|
|
||||||
else
|
|
||||||
ioread32_rep(ap->ioaddr.data_addr, buf, buflen >> 2);
|
ioread32_rep(ap->ioaddr.data_addr, buf, buflen >> 2);
|
||||||
|
else
|
||||||
|
iowrite32_rep(ap->ioaddr.data_addr, buf, buflen >> 2);
|
||||||
|
|
||||||
if (unlikely(slop)) {
|
if (unlikely(slop)) {
|
||||||
__le32 pad = 0;
|
u32 pad;
|
||||||
if (write_data) {
|
if (rw == READ) {
|
||||||
memcpy(&pad, buf + buflen - slop, slop);
|
|
||||||
iowrite32(le32_to_cpu(pad), ap->ioaddr.data_addr);
|
|
||||||
} else {
|
|
||||||
pad = cpu_to_le32(ioread32(ap->ioaddr.data_addr));
|
pad = cpu_to_le32(ioread32(ap->ioaddr.data_addr));
|
||||||
memcpy(buf + buflen - slop, &pad, slop);
|
memcpy(buf + buflen - slop, &pad, slop);
|
||||||
|
} else {
|
||||||
|
memcpy(&pad, buf + buflen - slop, slop);
|
||||||
|
iowrite32(le32_to_cpu(pad), ap->ioaddr.data_addr);
|
||||||
}
|
}
|
||||||
|
buflen += 4 - slop;
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
ata_data_xfer(adev, buf, buflen, write_data);
|
buflen = ata_data_xfer(dev, buf, buflen, rw);
|
||||||
|
|
||||||
|
return buflen;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct scsi_host_template winbond_sht = {
|
static struct scsi_host_template winbond_sht = {
|
||||||
@ -191,7 +195,7 @@ static __init int winbond_init_one(unsigned long port)
|
|||||||
reg = winbond_readcfg(port, 0x81);
|
reg = winbond_readcfg(port, 0x81);
|
||||||
|
|
||||||
if (!(reg & 0x03)) /* Disabled */
|
if (!(reg & 0x03)) /* Disabled */
|
||||||
return 0;
|
return -ENODEV;
|
||||||
|
|
||||||
for (i = 0; i < 2 ; i ++) {
|
for (i = 0; i < 2 ; i ++) {
|
||||||
unsigned long cmd_port = 0x1F0 - (0x80 * i);
|
unsigned long cmd_port = 0x1F0 - (0x80 * i);
|
||||||
|
@ -321,8 +321,9 @@ static int adma_fill_sg(struct ata_queued_cmd *qc)
|
|||||||
u8 *buf = pp->pkt, *last_buf = NULL;
|
u8 *buf = pp->pkt, *last_buf = NULL;
|
||||||
int i = (2 + buf[3]) * 8;
|
int i = (2 + buf[3]) * 8;
|
||||||
u8 pFLAGS = pORD | ((qc->tf.flags & ATA_TFLAG_WRITE) ? pDIRO : 0);
|
u8 pFLAGS = pORD | ((qc->tf.flags & ATA_TFLAG_WRITE) ? pDIRO : 0);
|
||||||
|
unsigned int si;
|
||||||
|
|
||||||
ata_for_each_sg(sg, qc) {
|
for_each_sg(qc->sg, sg, qc->n_elem, si) {
|
||||||
u32 addr;
|
u32 addr;
|
||||||
u32 len;
|
u32 len;
|
||||||
|
|
||||||
@ -455,7 +456,7 @@ static unsigned int adma_qc_issue(struct ata_queued_cmd *qc)
|
|||||||
adma_packet_start(qc);
|
adma_packet_start(qc);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
case ATA_PROT_ATAPI_DMA:
|
case ATAPI_PROT_DMA:
|
||||||
BUG();
|
BUG();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -333,13 +333,14 @@ static unsigned int sata_fsl_fill_sg(struct ata_queued_cmd *qc, void *cmd_desc,
|
|||||||
struct prde *prd_ptr_to_indirect_ext = NULL;
|
struct prde *prd_ptr_to_indirect_ext = NULL;
|
||||||
unsigned indirect_ext_segment_sz = 0;
|
unsigned indirect_ext_segment_sz = 0;
|
||||||
dma_addr_t indirect_ext_segment_paddr;
|
dma_addr_t indirect_ext_segment_paddr;
|
||||||
|
unsigned int si;
|
||||||
|
|
||||||
VPRINTK("SATA FSL : cd = 0x%x, prd = 0x%x\n", cmd_desc, prd);
|
VPRINTK("SATA FSL : cd = 0x%x, prd = 0x%x\n", cmd_desc, prd);
|
||||||
|
|
||||||
indirect_ext_segment_paddr = cmd_desc_paddr +
|
indirect_ext_segment_paddr = cmd_desc_paddr +
|
||||||
SATA_FSL_CMD_DESC_OFFSET_TO_PRDT + SATA_FSL_MAX_PRD_DIRECT * 16;
|
SATA_FSL_CMD_DESC_OFFSET_TO_PRDT + SATA_FSL_MAX_PRD_DIRECT * 16;
|
||||||
|
|
||||||
ata_for_each_sg(sg, qc) {
|
for_each_sg(qc->sg, sg, qc->n_elem, si) {
|
||||||
dma_addr_t sg_addr = sg_dma_address(sg);
|
dma_addr_t sg_addr = sg_dma_address(sg);
|
||||||
u32 sg_len = sg_dma_len(sg);
|
u32 sg_len = sg_dma_len(sg);
|
||||||
|
|
||||||
@ -417,7 +418,7 @@ static void sata_fsl_qc_prep(struct ata_queued_cmd *qc)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* setup "ACMD - atapi command" in cmd. desc. if this is ATAPI cmd */
|
/* setup "ACMD - atapi command" in cmd. desc. if this is ATAPI cmd */
|
||||||
if (is_atapi_taskfile(&qc->tf)) {
|
if (ata_is_atapi(qc->tf.protocol)) {
|
||||||
desc_info |= ATAPI_CMD;
|
desc_info |= ATAPI_CMD;
|
||||||
memset((void *)&cd->acmd, 0, 32);
|
memset((void *)&cd->acmd, 0, 32);
|
||||||
memcpy((void *)&cd->acmd, qc->cdb, qc->dev->cdb_len);
|
memcpy((void *)&cd->acmd, qc->cdb, qc->dev->cdb_len);
|
||||||
|
@ -585,7 +585,7 @@ static struct ata_port_operations inic_port_ops = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static struct ata_port_info inic_port_info = {
|
static struct ata_port_info inic_port_info = {
|
||||||
/* For some reason, ATA_PROT_ATAPI is broken on this
|
/* For some reason, ATAPI_PROT_PIO is broken on this
|
||||||
* controller, and no, PIO_POLLING does't fix it. It somehow
|
* controller, and no, PIO_POLLING does't fix it. It somehow
|
||||||
* manages to report the wrong ireason and ignoring ireason
|
* manages to report the wrong ireason and ignoring ireason
|
||||||
* results in machine lock up. Tell libata to always prefer
|
* results in machine lock up. Tell libata to always prefer
|
||||||
|
@ -1136,9 +1136,10 @@ static void mv_fill_sg(struct ata_queued_cmd *qc)
|
|||||||
struct mv_port_priv *pp = qc->ap->private_data;
|
struct mv_port_priv *pp = qc->ap->private_data;
|
||||||
struct scatterlist *sg;
|
struct scatterlist *sg;
|
||||||
struct mv_sg *mv_sg, *last_sg = NULL;
|
struct mv_sg *mv_sg, *last_sg = NULL;
|
||||||
|
unsigned int si;
|
||||||
|
|
||||||
mv_sg = pp->sg_tbl;
|
mv_sg = pp->sg_tbl;
|
||||||
ata_for_each_sg(sg, qc) {
|
for_each_sg(qc->sg, sg, qc->n_elem, si) {
|
||||||
dma_addr_t addr = sg_dma_address(sg);
|
dma_addr_t addr = sg_dma_address(sg);
|
||||||
u32 sg_len = sg_dma_len(sg);
|
u32 sg_len = sg_dma_len(sg);
|
||||||
|
|
||||||
|
@ -1336,21 +1336,18 @@ static void nv_adma_fill_aprd(struct ata_queued_cmd *qc,
|
|||||||
static void nv_adma_fill_sg(struct ata_queued_cmd *qc, struct nv_adma_cpb *cpb)
|
static void nv_adma_fill_sg(struct ata_queued_cmd *qc, struct nv_adma_cpb *cpb)
|
||||||
{
|
{
|
||||||
struct nv_adma_port_priv *pp = qc->ap->private_data;
|
struct nv_adma_port_priv *pp = qc->ap->private_data;
|
||||||
unsigned int idx;
|
|
||||||
struct nv_adma_prd *aprd;
|
struct nv_adma_prd *aprd;
|
||||||
struct scatterlist *sg;
|
struct scatterlist *sg;
|
||||||
|
unsigned int si;
|
||||||
|
|
||||||
VPRINTK("ENTER\n");
|
VPRINTK("ENTER\n");
|
||||||
|
|
||||||
idx = 0;
|
for_each_sg(qc->sg, sg, qc->n_elem, si) {
|
||||||
|
aprd = (si < 5) ? &cpb->aprd[si] :
|
||||||
ata_for_each_sg(sg, qc) {
|
&pp->aprd[NV_ADMA_SGTBL_LEN * qc->tag + (si-5)];
|
||||||
aprd = (idx < 5) ? &cpb->aprd[idx] :
|
nv_adma_fill_aprd(qc, sg, si, aprd);
|
||||||
&pp->aprd[NV_ADMA_SGTBL_LEN * qc->tag + (idx-5)];
|
|
||||||
nv_adma_fill_aprd(qc, sg, idx, aprd);
|
|
||||||
idx++;
|
|
||||||
}
|
}
|
||||||
if (idx > 5)
|
if (si > 5)
|
||||||
cpb->next_aprd = cpu_to_le64(((u64)(pp->aprd_dma + NV_ADMA_SGTBL_SZ * qc->tag)));
|
cpb->next_aprd = cpu_to_le64(((u64)(pp->aprd_dma + NV_ADMA_SGTBL_SZ * qc->tag)));
|
||||||
else
|
else
|
||||||
cpb->next_aprd = cpu_to_le64(0);
|
cpb->next_aprd = cpu_to_le64(0);
|
||||||
@ -1995,17 +1992,14 @@ static void nv_swncq_fill_sg(struct ata_queued_cmd *qc)
|
|||||||
{
|
{
|
||||||
struct ata_port *ap = qc->ap;
|
struct ata_port *ap = qc->ap;
|
||||||
struct scatterlist *sg;
|
struct scatterlist *sg;
|
||||||
unsigned int idx;
|
|
||||||
struct nv_swncq_port_priv *pp = ap->private_data;
|
struct nv_swncq_port_priv *pp = ap->private_data;
|
||||||
struct ata_prd *prd;
|
struct ata_prd *prd;
|
||||||
|
unsigned int si, idx;
|
||||||
WARN_ON(qc->__sg == NULL);
|
|
||||||
WARN_ON(qc->n_elem == 0 && qc->pad_len == 0);
|
|
||||||
|
|
||||||
prd = pp->prd + ATA_MAX_PRD * qc->tag;
|
prd = pp->prd + ATA_MAX_PRD * qc->tag;
|
||||||
|
|
||||||
idx = 0;
|
idx = 0;
|
||||||
ata_for_each_sg(sg, qc) {
|
for_each_sg(qc->sg, sg, qc->n_elem, si) {
|
||||||
u32 addr, offset;
|
u32 addr, offset;
|
||||||
u32 sg_len, len;
|
u32 sg_len, len;
|
||||||
|
|
||||||
@ -2027,8 +2021,7 @@ static void nv_swncq_fill_sg(struct ata_queued_cmd *qc)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (idx)
|
prd[idx - 1].flags_len |= cpu_to_le32(ATA_PRD_EOT);
|
||||||
prd[idx - 1].flags_len |= cpu_to_le32(ATA_PRD_EOT);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned int nv_swncq_issue_atacmd(struct ata_port *ap,
|
static unsigned int nv_swncq_issue_atacmd(struct ata_port *ap,
|
||||||
|
@ -450,19 +450,19 @@ static void pdc_atapi_pkt(struct ata_queued_cmd *qc)
|
|||||||
struct pdc_port_priv *pp = ap->private_data;
|
struct pdc_port_priv *pp = ap->private_data;
|
||||||
u8 *buf = pp->pkt;
|
u8 *buf = pp->pkt;
|
||||||
u32 *buf32 = (u32 *) buf;
|
u32 *buf32 = (u32 *) buf;
|
||||||
unsigned int dev_sel, feature, nbytes;
|
unsigned int dev_sel, feature;
|
||||||
|
|
||||||
/* set control bits (byte 0), zero delay seq id (byte 3),
|
/* set control bits (byte 0), zero delay seq id (byte 3),
|
||||||
* and seq id (byte 2)
|
* and seq id (byte 2)
|
||||||
*/
|
*/
|
||||||
switch (qc->tf.protocol) {
|
switch (qc->tf.protocol) {
|
||||||
case ATA_PROT_ATAPI_DMA:
|
case ATAPI_PROT_DMA:
|
||||||
if (!(qc->tf.flags & ATA_TFLAG_WRITE))
|
if (!(qc->tf.flags & ATA_TFLAG_WRITE))
|
||||||
buf32[0] = cpu_to_le32(PDC_PKT_READ);
|
buf32[0] = cpu_to_le32(PDC_PKT_READ);
|
||||||
else
|
else
|
||||||
buf32[0] = 0;
|
buf32[0] = 0;
|
||||||
break;
|
break;
|
||||||
case ATA_PROT_ATAPI_NODATA:
|
case ATAPI_PROT_NODATA:
|
||||||
buf32[0] = cpu_to_le32(PDC_PKT_NODATA);
|
buf32[0] = cpu_to_le32(PDC_PKT_NODATA);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -473,45 +473,37 @@ static void pdc_atapi_pkt(struct ata_queued_cmd *qc)
|
|||||||
buf32[2] = 0; /* no next-packet */
|
buf32[2] = 0; /* no next-packet */
|
||||||
|
|
||||||
/* select drive */
|
/* select drive */
|
||||||
if (sata_scr_valid(&ap->link)) {
|
if (sata_scr_valid(&ap->link))
|
||||||
dev_sel = PDC_DEVICE_SATA;
|
dev_sel = PDC_DEVICE_SATA;
|
||||||
} else {
|
else
|
||||||
dev_sel = ATA_DEVICE_OBS;
|
dev_sel = qc->tf.device;
|
||||||
if (qc->dev->devno != 0)
|
|
||||||
dev_sel |= ATA_DEV1;
|
|
||||||
}
|
|
||||||
buf[12] = (1 << 5) | ATA_REG_DEVICE;
|
buf[12] = (1 << 5) | ATA_REG_DEVICE;
|
||||||
buf[13] = dev_sel;
|
buf[13] = dev_sel;
|
||||||
buf[14] = (1 << 5) | ATA_REG_DEVICE | PDC_PKT_CLEAR_BSY;
|
buf[14] = (1 << 5) | ATA_REG_DEVICE | PDC_PKT_CLEAR_BSY;
|
||||||
buf[15] = dev_sel; /* once more, waiting for BSY to clear */
|
buf[15] = dev_sel; /* once more, waiting for BSY to clear */
|
||||||
|
|
||||||
buf[16] = (1 << 5) | ATA_REG_NSECT;
|
buf[16] = (1 << 5) | ATA_REG_NSECT;
|
||||||
buf[17] = 0x00;
|
buf[17] = qc->tf.nsect;
|
||||||
buf[18] = (1 << 5) | ATA_REG_LBAL;
|
buf[18] = (1 << 5) | ATA_REG_LBAL;
|
||||||
buf[19] = 0x00;
|
buf[19] = qc->tf.lbal;
|
||||||
|
|
||||||
/* set feature and byte counter registers */
|
/* set feature and byte counter registers */
|
||||||
if (qc->tf.protocol != ATA_PROT_ATAPI_DMA) {
|
if (qc->tf.protocol != ATAPI_PROT_DMA)
|
||||||
feature = PDC_FEATURE_ATAPI_PIO;
|
feature = PDC_FEATURE_ATAPI_PIO;
|
||||||
/* set byte counter register to real transfer byte count */
|
else
|
||||||
nbytes = qc->nbytes;
|
|
||||||
if (nbytes > 0xffff)
|
|
||||||
nbytes = 0xffff;
|
|
||||||
} else {
|
|
||||||
feature = PDC_FEATURE_ATAPI_DMA;
|
feature = PDC_FEATURE_ATAPI_DMA;
|
||||||
/* set byte counter register to 0 */
|
|
||||||
nbytes = 0;
|
|
||||||
}
|
|
||||||
buf[20] = (1 << 5) | ATA_REG_FEATURE;
|
buf[20] = (1 << 5) | ATA_REG_FEATURE;
|
||||||
buf[21] = feature;
|
buf[21] = feature;
|
||||||
buf[22] = (1 << 5) | ATA_REG_BYTEL;
|
buf[22] = (1 << 5) | ATA_REG_BYTEL;
|
||||||
buf[23] = nbytes & 0xFF;
|
buf[23] = qc->tf.lbam;
|
||||||
buf[24] = (1 << 5) | ATA_REG_BYTEH;
|
buf[24] = (1 << 5) | ATA_REG_BYTEH;
|
||||||
buf[25] = (nbytes >> 8) & 0xFF;
|
buf[25] = qc->tf.lbah;
|
||||||
|
|
||||||
/* send ATAPI packet command 0xA0 */
|
/* send ATAPI packet command 0xA0 */
|
||||||
buf[26] = (1 << 5) | ATA_REG_CMD;
|
buf[26] = (1 << 5) | ATA_REG_CMD;
|
||||||
buf[27] = ATA_CMD_PACKET;
|
buf[27] = qc->tf.command;
|
||||||
|
|
||||||
/* select drive and check DRQ */
|
/* select drive and check DRQ */
|
||||||
buf[28] = (1 << 5) | ATA_REG_DEVICE | PDC_PKT_WAIT_DRDY;
|
buf[28] = (1 << 5) | ATA_REG_DEVICE | PDC_PKT_WAIT_DRDY;
|
||||||
@ -541,17 +533,15 @@ static void pdc_fill_sg(struct ata_queued_cmd *qc)
|
|||||||
{
|
{
|
||||||
struct ata_port *ap = qc->ap;
|
struct ata_port *ap = qc->ap;
|
||||||
struct scatterlist *sg;
|
struct scatterlist *sg;
|
||||||
unsigned int idx;
|
|
||||||
const u32 SG_COUNT_ASIC_BUG = 41*4;
|
const u32 SG_COUNT_ASIC_BUG = 41*4;
|
||||||
|
unsigned int si, idx;
|
||||||
|
u32 len;
|
||||||
|
|
||||||
if (!(qc->flags & ATA_QCFLAG_DMAMAP))
|
if (!(qc->flags & ATA_QCFLAG_DMAMAP))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
WARN_ON(qc->__sg == NULL);
|
|
||||||
WARN_ON(qc->n_elem == 0 && qc->pad_len == 0);
|
|
||||||
|
|
||||||
idx = 0;
|
idx = 0;
|
||||||
ata_for_each_sg(sg, qc) {
|
for_each_sg(qc->sg, sg, qc->n_elem, si) {
|
||||||
u32 addr, offset;
|
u32 addr, offset;
|
||||||
u32 sg_len, len;
|
u32 sg_len, len;
|
||||||
|
|
||||||
@ -578,29 +568,27 @@ static void pdc_fill_sg(struct ata_queued_cmd *qc)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (idx) {
|
len = le32_to_cpu(ap->prd[idx - 1].flags_len);
|
||||||
u32 len = le32_to_cpu(ap->prd[idx - 1].flags_len);
|
|
||||||
|
|
||||||
if (len > SG_COUNT_ASIC_BUG) {
|
if (len > SG_COUNT_ASIC_BUG) {
|
||||||
u32 addr;
|
u32 addr;
|
||||||
|
|
||||||
VPRINTK("Splitting last PRD.\n");
|
VPRINTK("Splitting last PRD.\n");
|
||||||
|
|
||||||
addr = le32_to_cpu(ap->prd[idx - 1].addr);
|
addr = le32_to_cpu(ap->prd[idx - 1].addr);
|
||||||
ap->prd[idx - 1].flags_len = cpu_to_le32(len - SG_COUNT_ASIC_BUG);
|
ap->prd[idx - 1].flags_len = cpu_to_le32(len - SG_COUNT_ASIC_BUG);
|
||||||
VPRINTK("PRD[%u] = (0x%X, 0x%X)\n", idx - 1, addr, SG_COUNT_ASIC_BUG);
|
VPRINTK("PRD[%u] = (0x%X, 0x%X)\n", idx - 1, addr, SG_COUNT_ASIC_BUG);
|
||||||
|
|
||||||
addr = addr + len - SG_COUNT_ASIC_BUG;
|
addr = addr + len - SG_COUNT_ASIC_BUG;
|
||||||
len = SG_COUNT_ASIC_BUG;
|
len = SG_COUNT_ASIC_BUG;
|
||||||
ap->prd[idx].addr = cpu_to_le32(addr);
|
ap->prd[idx].addr = cpu_to_le32(addr);
|
||||||
ap->prd[idx].flags_len = cpu_to_le32(len);
|
ap->prd[idx].flags_len = cpu_to_le32(len);
|
||||||
VPRINTK("PRD[%u] = (0x%X, 0x%X)\n", idx, addr, len);
|
VPRINTK("PRD[%u] = (0x%X, 0x%X)\n", idx, addr, len);
|
||||||
|
|
||||||
idx++;
|
idx++;
|
||||||
}
|
|
||||||
|
|
||||||
ap->prd[idx - 1].flags_len |= cpu_to_le32(ATA_PRD_EOT);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ap->prd[idx - 1].flags_len |= cpu_to_le32(ATA_PRD_EOT);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pdc_qc_prep(struct ata_queued_cmd *qc)
|
static void pdc_qc_prep(struct ata_queued_cmd *qc)
|
||||||
@ -627,14 +615,14 @@ static void pdc_qc_prep(struct ata_queued_cmd *qc)
|
|||||||
pdc_pkt_footer(&qc->tf, pp->pkt, i);
|
pdc_pkt_footer(&qc->tf, pp->pkt, i);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ATA_PROT_ATAPI:
|
case ATAPI_PROT_PIO:
|
||||||
pdc_fill_sg(qc);
|
pdc_fill_sg(qc);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ATA_PROT_ATAPI_DMA:
|
case ATAPI_PROT_DMA:
|
||||||
pdc_fill_sg(qc);
|
pdc_fill_sg(qc);
|
||||||
/*FALLTHROUGH*/
|
/*FALLTHROUGH*/
|
||||||
case ATA_PROT_ATAPI_NODATA:
|
case ATAPI_PROT_NODATA:
|
||||||
pdc_atapi_pkt(qc);
|
pdc_atapi_pkt(qc);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -754,8 +742,8 @@ static inline unsigned int pdc_host_intr(struct ata_port *ap,
|
|||||||
switch (qc->tf.protocol) {
|
switch (qc->tf.protocol) {
|
||||||
case ATA_PROT_DMA:
|
case ATA_PROT_DMA:
|
||||||
case ATA_PROT_NODATA:
|
case ATA_PROT_NODATA:
|
||||||
case ATA_PROT_ATAPI_DMA:
|
case ATAPI_PROT_DMA:
|
||||||
case ATA_PROT_ATAPI_NODATA:
|
case ATAPI_PROT_NODATA:
|
||||||
qc->err_mask |= ac_err_mask(ata_wait_idle(ap));
|
qc->err_mask |= ac_err_mask(ata_wait_idle(ap));
|
||||||
ata_qc_complete(qc);
|
ata_qc_complete(qc);
|
||||||
handled = 1;
|
handled = 1;
|
||||||
@ -900,7 +888,7 @@ static inline void pdc_packet_start(struct ata_queued_cmd *qc)
|
|||||||
static unsigned int pdc_qc_issue_prot(struct ata_queued_cmd *qc)
|
static unsigned int pdc_qc_issue_prot(struct ata_queued_cmd *qc)
|
||||||
{
|
{
|
||||||
switch (qc->tf.protocol) {
|
switch (qc->tf.protocol) {
|
||||||
case ATA_PROT_ATAPI_NODATA:
|
case ATAPI_PROT_NODATA:
|
||||||
if (qc->dev->flags & ATA_DFLAG_CDB_INTR)
|
if (qc->dev->flags & ATA_DFLAG_CDB_INTR)
|
||||||
break;
|
break;
|
||||||
/*FALLTHROUGH*/
|
/*FALLTHROUGH*/
|
||||||
@ -908,7 +896,7 @@ static unsigned int pdc_qc_issue_prot(struct ata_queued_cmd *qc)
|
|||||||
if (qc->tf.flags & ATA_TFLAG_POLLING)
|
if (qc->tf.flags & ATA_TFLAG_POLLING)
|
||||||
break;
|
break;
|
||||||
/*FALLTHROUGH*/
|
/*FALLTHROUGH*/
|
||||||
case ATA_PROT_ATAPI_DMA:
|
case ATAPI_PROT_DMA:
|
||||||
case ATA_PROT_DMA:
|
case ATA_PROT_DMA:
|
||||||
pdc_packet_start(qc);
|
pdc_packet_start(qc);
|
||||||
return 0;
|
return 0;
|
||||||
@ -922,16 +910,14 @@ static unsigned int pdc_qc_issue_prot(struct ata_queued_cmd *qc)
|
|||||||
|
|
||||||
static void pdc_tf_load_mmio(struct ata_port *ap, const struct ata_taskfile *tf)
|
static void pdc_tf_load_mmio(struct ata_port *ap, const struct ata_taskfile *tf)
|
||||||
{
|
{
|
||||||
WARN_ON(tf->protocol == ATA_PROT_DMA ||
|
WARN_ON(tf->protocol == ATA_PROT_DMA || tf->protocol == ATAPI_PROT_DMA);
|
||||||
tf->protocol == ATA_PROT_ATAPI_DMA);
|
|
||||||
ata_tf_load(ap, tf);
|
ata_tf_load(ap, tf);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pdc_exec_command_mmio(struct ata_port *ap,
|
static void pdc_exec_command_mmio(struct ata_port *ap,
|
||||||
const struct ata_taskfile *tf)
|
const struct ata_taskfile *tf)
|
||||||
{
|
{
|
||||||
WARN_ON(tf->protocol == ATA_PROT_DMA ||
|
WARN_ON(tf->protocol == ATA_PROT_DMA || tf->protocol == ATAPI_PROT_DMA);
|
||||||
tf->protocol == ATA_PROT_ATAPI_DMA);
|
|
||||||
ata_exec_command(ap, tf);
|
ata_exec_command(ap, tf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,7 +46,7 @@ static inline unsigned int pdc_pkt_header(struct ata_taskfile *tf,
|
|||||||
unsigned int devno, u8 *buf)
|
unsigned int devno, u8 *buf)
|
||||||
{
|
{
|
||||||
u8 dev_reg;
|
u8 dev_reg;
|
||||||
u32 *buf32 = (u32 *) buf;
|
__le32 *buf32 = (__le32 *) buf;
|
||||||
|
|
||||||
/* set control bits (byte 0), zero delay seq id (byte 3),
|
/* set control bits (byte 0), zero delay seq id (byte 3),
|
||||||
* and seq id (byte 2)
|
* and seq id (byte 2)
|
||||||
|
@ -287,14 +287,10 @@ static unsigned int qs_fill_sg(struct ata_queued_cmd *qc)
|
|||||||
struct scatterlist *sg;
|
struct scatterlist *sg;
|
||||||
struct ata_port *ap = qc->ap;
|
struct ata_port *ap = qc->ap;
|
||||||
struct qs_port_priv *pp = ap->private_data;
|
struct qs_port_priv *pp = ap->private_data;
|
||||||
unsigned int nelem;
|
|
||||||
u8 *prd = pp->pkt + QS_CPB_BYTES;
|
u8 *prd = pp->pkt + QS_CPB_BYTES;
|
||||||
|
unsigned int si;
|
||||||
|
|
||||||
WARN_ON(qc->__sg == NULL);
|
for_each_sg(qc->sg, sg, qc->n_elem, si) {
|
||||||
WARN_ON(qc->n_elem == 0 && qc->pad_len == 0);
|
|
||||||
|
|
||||||
nelem = 0;
|
|
||||||
ata_for_each_sg(sg, qc) {
|
|
||||||
u64 addr;
|
u64 addr;
|
||||||
u32 len;
|
u32 len;
|
||||||
|
|
||||||
@ -306,12 +302,11 @@ static unsigned int qs_fill_sg(struct ata_queued_cmd *qc)
|
|||||||
*(__le32 *)prd = cpu_to_le32(len);
|
*(__le32 *)prd = cpu_to_le32(len);
|
||||||
prd += sizeof(u64);
|
prd += sizeof(u64);
|
||||||
|
|
||||||
VPRINTK("PRD[%u] = (0x%llX, 0x%X)\n", nelem,
|
VPRINTK("PRD[%u] = (0x%llX, 0x%X)\n", si,
|
||||||
(unsigned long long)addr, len);
|
(unsigned long long)addr, len);
|
||||||
nelem++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return nelem;
|
return si;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void qs_qc_prep(struct ata_queued_cmd *qc)
|
static void qs_qc_prep(struct ata_queued_cmd *qc)
|
||||||
@ -376,7 +371,7 @@ static unsigned int qs_qc_issue(struct ata_queued_cmd *qc)
|
|||||||
qs_packet_start(qc);
|
qs_packet_start(qc);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
case ATA_PROT_ATAPI_DMA:
|
case ATAPI_PROT_DMA:
|
||||||
BUG();
|
BUG();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -416,15 +416,14 @@ static void sil_host_intr(struct ata_port *ap, u32 bmdma2)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/* Check the ATA_DFLAG_CDB_INTR flag is enough here.
|
/* Check the ATA_DFLAG_CDB_INTR flag is enough here.
|
||||||
* The flag was turned on only for atapi devices.
|
* The flag was turned on only for atapi devices. No
|
||||||
* No need to check is_atapi_taskfile(&qc->tf) again.
|
* need to check ata_is_atapi(qc->tf.protocol) again.
|
||||||
*/
|
*/
|
||||||
if (!(qc->dev->flags & ATA_DFLAG_CDB_INTR))
|
if (!(qc->dev->flags & ATA_DFLAG_CDB_INTR))
|
||||||
goto err_hsm;
|
goto err_hsm;
|
||||||
break;
|
break;
|
||||||
case HSM_ST_LAST:
|
case HSM_ST_LAST:
|
||||||
if (qc->tf.protocol == ATA_PROT_DMA ||
|
if (ata_is_dma(qc->tf.protocol)) {
|
||||||
qc->tf.protocol == ATA_PROT_ATAPI_DMA) {
|
|
||||||
/* clear DMA-Start bit */
|
/* clear DMA-Start bit */
|
||||||
ap->ops->bmdma_stop(qc);
|
ap->ops->bmdma_stop(qc);
|
||||||
|
|
||||||
@ -451,8 +450,7 @@ static void sil_host_intr(struct ata_port *ap, u32 bmdma2)
|
|||||||
/* kick HSM in the ass */
|
/* kick HSM in the ass */
|
||||||
ata_hsm_move(ap, qc, status, 0);
|
ata_hsm_move(ap, qc, status, 0);
|
||||||
|
|
||||||
if (unlikely(qc->err_mask) && (qc->tf.protocol == ATA_PROT_DMA ||
|
if (unlikely(qc->err_mask) && ata_is_dma(qc->tf.protocol))
|
||||||
qc->tf.protocol == ATA_PROT_ATAPI_DMA))
|
|
||||||
ata_ehi_push_desc(ehi, "BMDMA2 stat 0x%x", bmdma2);
|
ata_ehi_push_desc(ehi, "BMDMA2 stat 0x%x", bmdma2);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
@ -813,8 +813,9 @@ static inline void sil24_fill_sg(struct ata_queued_cmd *qc,
|
|||||||
{
|
{
|
||||||
struct scatterlist *sg;
|
struct scatterlist *sg;
|
||||||
struct sil24_sge *last_sge = NULL;
|
struct sil24_sge *last_sge = NULL;
|
||||||
|
unsigned int si;
|
||||||
|
|
||||||
ata_for_each_sg(sg, qc) {
|
for_each_sg(qc->sg, sg, qc->n_elem, si) {
|
||||||
sge->addr = cpu_to_le64(sg_dma_address(sg));
|
sge->addr = cpu_to_le64(sg_dma_address(sg));
|
||||||
sge->cnt = cpu_to_le32(sg_dma_len(sg));
|
sge->cnt = cpu_to_le32(sg_dma_len(sg));
|
||||||
sge->flags = 0;
|
sge->flags = 0;
|
||||||
@ -823,8 +824,7 @@ static inline void sil24_fill_sg(struct ata_queued_cmd *qc,
|
|||||||
sge++;
|
sge++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (likely(last_sge))
|
last_sge->flags = cpu_to_le32(SGE_TRM);
|
||||||
last_sge->flags = cpu_to_le32(SGE_TRM);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int sil24_qc_defer(struct ata_queued_cmd *qc)
|
static int sil24_qc_defer(struct ata_queued_cmd *qc)
|
||||||
@ -852,9 +852,7 @@ static int sil24_qc_defer(struct ata_queued_cmd *qc)
|
|||||||
* set.
|
* set.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
int is_excl = (prot == ATA_PROT_ATAPI ||
|
int is_excl = (ata_is_atapi(prot) ||
|
||||||
prot == ATA_PROT_ATAPI_NODATA ||
|
|
||||||
prot == ATA_PROT_ATAPI_DMA ||
|
|
||||||
(qc->flags & ATA_QCFLAG_RESULT_TF));
|
(qc->flags & ATA_QCFLAG_RESULT_TF));
|
||||||
|
|
||||||
if (unlikely(ap->excl_link)) {
|
if (unlikely(ap->excl_link)) {
|
||||||
@ -885,35 +883,21 @@ static void sil24_qc_prep(struct ata_queued_cmd *qc)
|
|||||||
|
|
||||||
cb = &pp->cmd_block[sil24_tag(qc->tag)];
|
cb = &pp->cmd_block[sil24_tag(qc->tag)];
|
||||||
|
|
||||||
switch (qc->tf.protocol) {
|
if (!ata_is_atapi(qc->tf.protocol)) {
|
||||||
case ATA_PROT_PIO:
|
|
||||||
case ATA_PROT_DMA:
|
|
||||||
case ATA_PROT_NCQ:
|
|
||||||
case ATA_PROT_NODATA:
|
|
||||||
prb = &cb->ata.prb;
|
prb = &cb->ata.prb;
|
||||||
sge = cb->ata.sge;
|
sge = cb->ata.sge;
|
||||||
break;
|
} else {
|
||||||
|
|
||||||
case ATA_PROT_ATAPI:
|
|
||||||
case ATA_PROT_ATAPI_DMA:
|
|
||||||
case ATA_PROT_ATAPI_NODATA:
|
|
||||||
prb = &cb->atapi.prb;
|
prb = &cb->atapi.prb;
|
||||||
sge = cb->atapi.sge;
|
sge = cb->atapi.sge;
|
||||||
memset(cb->atapi.cdb, 0, 32);
|
memset(cb->atapi.cdb, 0, 32);
|
||||||
memcpy(cb->atapi.cdb, qc->cdb, qc->dev->cdb_len);
|
memcpy(cb->atapi.cdb, qc->cdb, qc->dev->cdb_len);
|
||||||
|
|
||||||
if (qc->tf.protocol != ATA_PROT_ATAPI_NODATA) {
|
if (ata_is_data(qc->tf.protocol)) {
|
||||||
if (qc->tf.flags & ATA_TFLAG_WRITE)
|
if (qc->tf.flags & ATA_TFLAG_WRITE)
|
||||||
ctrl = PRB_CTRL_PACKET_WRITE;
|
ctrl = PRB_CTRL_PACKET_WRITE;
|
||||||
else
|
else
|
||||||
ctrl = PRB_CTRL_PACKET_READ;
|
ctrl = PRB_CTRL_PACKET_READ;
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
prb = NULL; /* shut up, gcc */
|
|
||||||
sge = NULL;
|
|
||||||
BUG();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
prb->ctrl = cpu_to_le16(ctrl);
|
prb->ctrl = cpu_to_le16(ctrl);
|
||||||
|
@ -334,7 +334,7 @@ static inline void pdc20621_ata_sg(struct ata_taskfile *tf, u8 *buf,
|
|||||||
{
|
{
|
||||||
u32 addr;
|
u32 addr;
|
||||||
unsigned int dw = PDC_DIMM_APKT_PRD >> 2;
|
unsigned int dw = PDC_DIMM_APKT_PRD >> 2;
|
||||||
u32 *buf32 = (u32 *) buf;
|
__le32 *buf32 = (__le32 *) buf;
|
||||||
|
|
||||||
/* output ATA packet S/G table */
|
/* output ATA packet S/G table */
|
||||||
addr = PDC_20621_DIMM_BASE + PDC_20621_DIMM_DATA +
|
addr = PDC_20621_DIMM_BASE + PDC_20621_DIMM_DATA +
|
||||||
@ -356,7 +356,7 @@ static inline void pdc20621_host_sg(struct ata_taskfile *tf, u8 *buf,
|
|||||||
{
|
{
|
||||||
u32 addr;
|
u32 addr;
|
||||||
unsigned int dw = PDC_DIMM_HPKT_PRD >> 2;
|
unsigned int dw = PDC_DIMM_HPKT_PRD >> 2;
|
||||||
u32 *buf32 = (u32 *) buf;
|
__le32 *buf32 = (__le32 *) buf;
|
||||||
|
|
||||||
/* output Host DMA packet S/G table */
|
/* output Host DMA packet S/G table */
|
||||||
addr = PDC_20621_DIMM_BASE + PDC_20621_DIMM_DATA +
|
addr = PDC_20621_DIMM_BASE + PDC_20621_DIMM_DATA +
|
||||||
@ -377,7 +377,7 @@ static inline unsigned int pdc20621_ata_pkt(struct ata_taskfile *tf,
|
|||||||
unsigned int portno)
|
unsigned int portno)
|
||||||
{
|
{
|
||||||
unsigned int i, dw;
|
unsigned int i, dw;
|
||||||
u32 *buf32 = (u32 *) buf;
|
__le32 *buf32 = (__le32 *) buf;
|
||||||
u8 dev_reg;
|
u8 dev_reg;
|
||||||
|
|
||||||
unsigned int dimm_sg = PDC_20621_DIMM_BASE +
|
unsigned int dimm_sg = PDC_20621_DIMM_BASE +
|
||||||
@ -429,7 +429,8 @@ static inline void pdc20621_host_pkt(struct ata_taskfile *tf, u8 *buf,
|
|||||||
unsigned int portno)
|
unsigned int portno)
|
||||||
{
|
{
|
||||||
unsigned int dw;
|
unsigned int dw;
|
||||||
u32 tmp, *buf32 = (u32 *) buf;
|
u32 tmp;
|
||||||
|
__le32 *buf32 = (__le32 *) buf;
|
||||||
|
|
||||||
unsigned int host_sg = PDC_20621_DIMM_BASE +
|
unsigned int host_sg = PDC_20621_DIMM_BASE +
|
||||||
(PDC_DIMM_WINDOW_STEP * portno) +
|
(PDC_DIMM_WINDOW_STEP * portno) +
|
||||||
@ -473,7 +474,7 @@ static void pdc20621_dma_prep(struct ata_queued_cmd *qc)
|
|||||||
void __iomem *mmio = ap->host->iomap[PDC_MMIO_BAR];
|
void __iomem *mmio = ap->host->iomap[PDC_MMIO_BAR];
|
||||||
void __iomem *dimm_mmio = ap->host->iomap[PDC_DIMM_BAR];
|
void __iomem *dimm_mmio = ap->host->iomap[PDC_DIMM_BAR];
|
||||||
unsigned int portno = ap->port_no;
|
unsigned int portno = ap->port_no;
|
||||||
unsigned int i, idx, total_len = 0, sgt_len;
|
unsigned int i, si, idx, total_len = 0, sgt_len;
|
||||||
u32 *buf = (u32 *) &pp->dimm_buf[PDC_DIMM_HEADER_SZ];
|
u32 *buf = (u32 *) &pp->dimm_buf[PDC_DIMM_HEADER_SZ];
|
||||||
|
|
||||||
WARN_ON(!(qc->flags & ATA_QCFLAG_DMAMAP));
|
WARN_ON(!(qc->flags & ATA_QCFLAG_DMAMAP));
|
||||||
@ -487,7 +488,7 @@ static void pdc20621_dma_prep(struct ata_queued_cmd *qc)
|
|||||||
* Build S/G table
|
* Build S/G table
|
||||||
*/
|
*/
|
||||||
idx = 0;
|
idx = 0;
|
||||||
ata_for_each_sg(sg, qc) {
|
for_each_sg(qc->sg, sg, qc->n_elem, si) {
|
||||||
buf[idx++] = cpu_to_le32(sg_dma_address(sg));
|
buf[idx++] = cpu_to_le32(sg_dma_address(sg));
|
||||||
buf[idx++] = cpu_to_le32(sg_dma_len(sg));
|
buf[idx++] = cpu_to_le32(sg_dma_len(sg));
|
||||||
total_len += sg_dma_len(sg);
|
total_len += sg_dma_len(sg);
|
||||||
@ -700,7 +701,7 @@ static unsigned int pdc20621_qc_issue_prot(struct ata_queued_cmd *qc)
|
|||||||
pdc20621_packet_start(qc);
|
pdc20621_packet_start(qc);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
case ATA_PROT_ATAPI_DMA:
|
case ATAPI_PROT_DMA:
|
||||||
BUG();
|
BUG();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -5142,6 +5142,7 @@ static void ipr_build_ata_ioadl(struct ipr_cmnd *ipr_cmd,
|
|||||||
struct ipr_ioadl_desc *last_ioadl = NULL;
|
struct ipr_ioadl_desc *last_ioadl = NULL;
|
||||||
int len = qc->nbytes + qc->pad_len;
|
int len = qc->nbytes + qc->pad_len;
|
||||||
struct scatterlist *sg;
|
struct scatterlist *sg;
|
||||||
|
unsigned int si;
|
||||||
|
|
||||||
if (len == 0)
|
if (len == 0)
|
||||||
return;
|
return;
|
||||||
@ -5159,7 +5160,7 @@ static void ipr_build_ata_ioadl(struct ipr_cmnd *ipr_cmd,
|
|||||||
cpu_to_be32(sizeof(struct ipr_ioadl_desc) * ipr_cmd->dma_use_sg);
|
cpu_to_be32(sizeof(struct ipr_ioadl_desc) * ipr_cmd->dma_use_sg);
|
||||||
}
|
}
|
||||||
|
|
||||||
ata_for_each_sg(sg, qc) {
|
for_each_sg(qc->sg, sg, qc->n_elem, si) {
|
||||||
ioadl->flags_and_data_len = cpu_to_be32(ioadl_flags | sg_dma_len(sg));
|
ioadl->flags_and_data_len = cpu_to_be32(ioadl_flags | sg_dma_len(sg));
|
||||||
ioadl->address = cpu_to_be32(sg_dma_address(sg));
|
ioadl->address = cpu_to_be32(sg_dma_address(sg));
|
||||||
|
|
||||||
@ -5222,12 +5223,12 @@ static unsigned int ipr_qc_issue(struct ata_queued_cmd *qc)
|
|||||||
regs->flags |= IPR_ATA_FLAG_XFER_TYPE_DMA;
|
regs->flags |= IPR_ATA_FLAG_XFER_TYPE_DMA;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ATA_PROT_ATAPI:
|
case ATAPI_PROT_PIO:
|
||||||
case ATA_PROT_ATAPI_NODATA:
|
case ATAPI_PROT_NODATA:
|
||||||
regs->flags |= IPR_ATA_FLAG_PACKET_CMD;
|
regs->flags |= IPR_ATA_FLAG_PACKET_CMD;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ATA_PROT_ATAPI_DMA:
|
case ATAPI_PROT_DMA:
|
||||||
regs->flags |= IPR_ATA_FLAG_PACKET_CMD;
|
regs->flags |= IPR_ATA_FLAG_PACKET_CMD;
|
||||||
regs->flags |= IPR_ATA_FLAG_XFER_TYPE_DMA;
|
regs->flags |= IPR_ATA_FLAG_XFER_TYPE_DMA;
|
||||||
break;
|
break;
|
||||||
|
@ -158,8 +158,8 @@ static unsigned int sas_ata_qc_issue(struct ata_queued_cmd *qc)
|
|||||||
struct Scsi_Host *host = sas_ha->core.shost;
|
struct Scsi_Host *host = sas_ha->core.shost;
|
||||||
struct sas_internal *i = to_sas_internal(host->transportt);
|
struct sas_internal *i = to_sas_internal(host->transportt);
|
||||||
struct scatterlist *sg;
|
struct scatterlist *sg;
|
||||||
unsigned int num = 0;
|
|
||||||
unsigned int xfer = 0;
|
unsigned int xfer = 0;
|
||||||
|
unsigned int si;
|
||||||
|
|
||||||
task = sas_alloc_task(GFP_ATOMIC);
|
task = sas_alloc_task(GFP_ATOMIC);
|
||||||
if (!task)
|
if (!task)
|
||||||
@ -176,22 +176,20 @@ static unsigned int sas_ata_qc_issue(struct ata_queued_cmd *qc)
|
|||||||
|
|
||||||
ata_tf_to_fis(&qc->tf, 1, 0, (u8*)&task->ata_task.fis);
|
ata_tf_to_fis(&qc->tf, 1, 0, (u8*)&task->ata_task.fis);
|
||||||
task->uldd_task = qc;
|
task->uldd_task = qc;
|
||||||
if (is_atapi_taskfile(&qc->tf)) {
|
if (ata_is_atapi(qc->tf.protocol)) {
|
||||||
memcpy(task->ata_task.atapi_packet, qc->cdb, qc->dev->cdb_len);
|
memcpy(task->ata_task.atapi_packet, qc->cdb, qc->dev->cdb_len);
|
||||||
task->total_xfer_len = qc->nbytes + qc->pad_len;
|
task->total_xfer_len = qc->nbytes + qc->pad_len;
|
||||||
task->num_scatter = qc->pad_len ? qc->n_elem + 1 : qc->n_elem;
|
task->num_scatter = qc->pad_len ? qc->n_elem + 1 : qc->n_elem;
|
||||||
} else {
|
} else {
|
||||||
ata_for_each_sg(sg, qc) {
|
for_each_sg(qc->sg, sg, qc->n_elem, si)
|
||||||
num++;
|
|
||||||
xfer += sg->length;
|
xfer += sg->length;
|
||||||
}
|
|
||||||
|
|
||||||
task->total_xfer_len = xfer;
|
task->total_xfer_len = xfer;
|
||||||
task->num_scatter = num;
|
task->num_scatter = si;
|
||||||
}
|
}
|
||||||
|
|
||||||
task->data_dir = qc->dma_dir;
|
task->data_dir = qc->dma_dir;
|
||||||
task->scatter = qc->__sg;
|
task->scatter = qc->sg;
|
||||||
task->ata_task.retry_count = 1;
|
task->ata_task.retry_count = 1;
|
||||||
task->task_state_flags = SAS_TASK_STATE_PENDING;
|
task->task_state_flags = SAS_TASK_STATE_PENDING;
|
||||||
qc->lldd_task = task;
|
qc->lldd_task = task;
|
||||||
@ -200,7 +198,7 @@ static unsigned int sas_ata_qc_issue(struct ata_queued_cmd *qc)
|
|||||||
case ATA_PROT_NCQ:
|
case ATA_PROT_NCQ:
|
||||||
task->ata_task.use_ncq = 1;
|
task->ata_task.use_ncq = 1;
|
||||||
/* fall through */
|
/* fall through */
|
||||||
case ATA_PROT_ATAPI_DMA:
|
case ATAPI_PROT_DMA:
|
||||||
case ATA_PROT_DMA:
|
case ATA_PROT_DMA:
|
||||||
task->ata_task.dma_xfer = 1;
|
task->ata_task.dma_xfer = 1;
|
||||||
break;
|
break;
|
||||||
|
@ -286,9 +286,10 @@ enum {
|
|||||||
ATA_CBL_NONE = 0,
|
ATA_CBL_NONE = 0,
|
||||||
ATA_CBL_PATA40 = 1,
|
ATA_CBL_PATA40 = 1,
|
||||||
ATA_CBL_PATA80 = 2,
|
ATA_CBL_PATA80 = 2,
|
||||||
ATA_CBL_PATA40_SHORT = 3, /* 40 wire cable to high UDMA spec */
|
ATA_CBL_PATA40_SHORT = 3, /* 40 wire cable to high UDMA spec */
|
||||||
ATA_CBL_PATA_UNK = 4,
|
ATA_CBL_PATA_UNK = 4, /* don't know, maybe 80c? */
|
||||||
ATA_CBL_SATA = 5,
|
ATA_CBL_PATA_IGN = 5, /* don't know, ignore cable handling */
|
||||||
|
ATA_CBL_SATA = 6,
|
||||||
|
|
||||||
/* SATA Status and Control Registers */
|
/* SATA Status and Control Registers */
|
||||||
SCR_STATUS = 0,
|
SCR_STATUS = 0,
|
||||||
@ -324,6 +325,13 @@ enum {
|
|||||||
ATA_TFLAG_LBA = (1 << 4), /* enable LBA */
|
ATA_TFLAG_LBA = (1 << 4), /* enable LBA */
|
||||||
ATA_TFLAG_FUA = (1 << 5), /* enable FUA */
|
ATA_TFLAG_FUA = (1 << 5), /* enable FUA */
|
||||||
ATA_TFLAG_POLLING = (1 << 6), /* set nIEN to 1 and use polling */
|
ATA_TFLAG_POLLING = (1 << 6), /* set nIEN to 1 and use polling */
|
||||||
|
|
||||||
|
/* protocol flags */
|
||||||
|
ATA_PROT_FLAG_PIO = (1 << 0), /* is PIO */
|
||||||
|
ATA_PROT_FLAG_DMA = (1 << 1), /* is DMA */
|
||||||
|
ATA_PROT_FLAG_DATA = ATA_PROT_FLAG_PIO | ATA_PROT_FLAG_DMA,
|
||||||
|
ATA_PROT_FLAG_NCQ = (1 << 2), /* is NCQ */
|
||||||
|
ATA_PROT_FLAG_ATAPI = (1 << 3), /* is ATAPI */
|
||||||
};
|
};
|
||||||
|
|
||||||
enum ata_tf_protocols {
|
enum ata_tf_protocols {
|
||||||
@ -333,9 +341,9 @@ enum ata_tf_protocols {
|
|||||||
ATA_PROT_PIO, /* PIO data xfer */
|
ATA_PROT_PIO, /* PIO data xfer */
|
||||||
ATA_PROT_DMA, /* DMA */
|
ATA_PROT_DMA, /* DMA */
|
||||||
ATA_PROT_NCQ, /* NCQ */
|
ATA_PROT_NCQ, /* NCQ */
|
||||||
ATA_PROT_ATAPI, /* packet command, PIO data xfer*/
|
ATAPI_PROT_NODATA, /* packet command, no data */
|
||||||
ATA_PROT_ATAPI_NODATA, /* packet command, no data */
|
ATAPI_PROT_PIO, /* packet command, PIO data xfer*/
|
||||||
ATA_PROT_ATAPI_DMA, /* packet command with special DMA sauce */
|
ATAPI_PROT_DMA, /* packet command with special DMA sauce */
|
||||||
};
|
};
|
||||||
|
|
||||||
enum ata_ioctls {
|
enum ata_ioctls {
|
||||||
@ -346,8 +354,8 @@ enum ata_ioctls {
|
|||||||
/* core structures */
|
/* core structures */
|
||||||
|
|
||||||
struct ata_prd {
|
struct ata_prd {
|
||||||
u32 addr;
|
__le32 addr;
|
||||||
u32 flags_len;
|
__le32 flags_len;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ata_taskfile {
|
struct ata_taskfile {
|
||||||
@ -373,13 +381,69 @@ struct ata_taskfile {
|
|||||||
u8 command; /* IO operation */
|
u8 command; /* IO operation */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* protocol tests
|
||||||
|
*/
|
||||||
|
static inline unsigned int ata_prot_flags(u8 prot)
|
||||||
|
{
|
||||||
|
switch (prot) {
|
||||||
|
case ATA_PROT_NODATA:
|
||||||
|
return 0;
|
||||||
|
case ATA_PROT_PIO:
|
||||||
|
return ATA_PROT_FLAG_PIO;
|
||||||
|
case ATA_PROT_DMA:
|
||||||
|
return ATA_PROT_FLAG_DMA;
|
||||||
|
case ATA_PROT_NCQ:
|
||||||
|
return ATA_PROT_FLAG_DMA | ATA_PROT_FLAG_NCQ;
|
||||||
|
case ATAPI_PROT_NODATA:
|
||||||
|
return ATA_PROT_FLAG_ATAPI;
|
||||||
|
case ATAPI_PROT_PIO:
|
||||||
|
return ATA_PROT_FLAG_ATAPI | ATA_PROT_FLAG_PIO;
|
||||||
|
case ATAPI_PROT_DMA:
|
||||||
|
return ATA_PROT_FLAG_ATAPI | ATA_PROT_FLAG_DMA;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int ata_is_atapi(u8 prot)
|
||||||
|
{
|
||||||
|
return ata_prot_flags(prot) & ATA_PROT_FLAG_ATAPI;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int ata_is_nodata(u8 prot)
|
||||||
|
{
|
||||||
|
return !(ata_prot_flags(prot) & ATA_PROT_FLAG_DATA);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int ata_is_pio(u8 prot)
|
||||||
|
{
|
||||||
|
return ata_prot_flags(prot) & ATA_PROT_FLAG_PIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int ata_is_dma(u8 prot)
|
||||||
|
{
|
||||||
|
return ata_prot_flags(prot) & ATA_PROT_FLAG_DMA;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int ata_is_ncq(u8 prot)
|
||||||
|
{
|
||||||
|
return ata_prot_flags(prot) & ATA_PROT_FLAG_NCQ;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int ata_is_data(u8 prot)
|
||||||
|
{
|
||||||
|
return ata_prot_flags(prot) & ATA_PROT_FLAG_DATA;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* id tests
|
||||||
|
*/
|
||||||
#define ata_id_is_ata(id) (((id)[0] & (1 << 15)) == 0)
|
#define ata_id_is_ata(id) (((id)[0] & (1 << 15)) == 0)
|
||||||
#define ata_id_has_lba(id) ((id)[49] & (1 << 9))
|
#define ata_id_has_lba(id) ((id)[49] & (1 << 9))
|
||||||
#define ata_id_has_dma(id) ((id)[49] & (1 << 8))
|
#define ata_id_has_dma(id) ((id)[49] & (1 << 8))
|
||||||
#define ata_id_has_ncq(id) ((id)[76] & (1 << 8))
|
#define ata_id_has_ncq(id) ((id)[76] & (1 << 8))
|
||||||
#define ata_id_queue_depth(id) (((id)[75] & 0x1f) + 1)
|
#define ata_id_queue_depth(id) (((id)[75] & 0x1f) + 1)
|
||||||
#define ata_id_removeable(id) ((id)[0] & (1 << 7))
|
#define ata_id_removeable(id) ((id)[0] & (1 << 7))
|
||||||
#define ata_id_has_dword_io(id) ((id)[48] & (1 << 0))
|
|
||||||
#define ata_id_has_atapi_AN(id) \
|
#define ata_id_has_atapi_AN(id) \
|
||||||
( (((id)[76] != 0x0000) && ((id)[76] != 0xffff)) && \
|
( (((id)[76] != 0x0000) && ((id)[76] != 0xffff)) && \
|
||||||
((id)[78] & (1 << 5)) )
|
((id)[78] & (1 << 5)) )
|
||||||
@ -415,6 +479,7 @@ static inline bool ata_id_has_dipm(const u16 *id)
|
|||||||
return val & (1 << 3);
|
return val & (1 << 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static inline int ata_id_has_fua(const u16 *id)
|
static inline int ata_id_has_fua(const u16 *id)
|
||||||
{
|
{
|
||||||
if ((id[84] & 0xC000) != 0x4000)
|
if ((id[84] & 0xC000) != 0x4000)
|
||||||
@ -519,6 +584,26 @@ static inline int ata_id_is_sata(const u16 *id)
|
|||||||
return ata_id_major_version(id) >= 5 && id[93] == 0;
|
return ata_id_major_version(id) >= 5 && id[93] == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline int ata_id_has_tpm(const u16 *id)
|
||||||
|
{
|
||||||
|
/* The TPM bits are only valid on ATA8 */
|
||||||
|
if (ata_id_major_version(id) < 8)
|
||||||
|
return 0;
|
||||||
|
if ((id[48] & 0xC000) != 0x4000)
|
||||||
|
return 0;
|
||||||
|
return id[48] & (1 << 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int ata_id_has_dword_io(const u16 *id)
|
||||||
|
{
|
||||||
|
/* ATA 8 reuses this flag for "trusted" computing */
|
||||||
|
if (ata_id_major_version(id) > 7)
|
||||||
|
return 0;
|
||||||
|
if (id[48] & (1 << 0))
|
||||||
|
return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static inline int ata_id_current_chs_valid(const u16 *id)
|
static inline int ata_id_current_chs_valid(const u16 *id)
|
||||||
{
|
{
|
||||||
/* For ATA-1 devices, if the INITIALIZE DEVICE PARAMETERS command
|
/* For ATA-1 devices, if the INITIALIZE DEVICE PARAMETERS command
|
||||||
@ -574,13 +659,6 @@ static inline int atapi_command_packet_set(const u16 *dev_id)
|
|||||||
return (dev_id[0] >> 8) & 0x1f;
|
return (dev_id[0] >> 8) & 0x1f;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int is_atapi_taskfile(const struct ata_taskfile *tf)
|
|
||||||
{
|
|
||||||
return (tf->protocol == ATA_PROT_ATAPI) ||
|
|
||||||
(tf->protocol == ATA_PROT_ATAPI_NODATA) ||
|
|
||||||
(tf->protocol == ATA_PROT_ATAPI_DMA);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int is_multi_taskfile(struct ata_taskfile *tf)
|
static inline int is_multi_taskfile(struct ata_taskfile *tf)
|
||||||
{
|
{
|
||||||
return (tf->command == ATA_CMD_READ_MULTI) ||
|
return (tf->command == ATA_CMD_READ_MULTI) ||
|
||||||
|
@ -451,6 +451,7 @@ struct cdrom_generic_command
|
|||||||
#define GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL 0x1e
|
#define GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL 0x1e
|
||||||
#define GPCMD_READ_10 0x28
|
#define GPCMD_READ_10 0x28
|
||||||
#define GPCMD_READ_12 0xa8
|
#define GPCMD_READ_12 0xa8
|
||||||
|
#define GPCMD_READ_BUFFER 0x3c
|
||||||
#define GPCMD_READ_BUFFER_CAPACITY 0x5c
|
#define GPCMD_READ_BUFFER_CAPACITY 0x5c
|
||||||
#define GPCMD_READ_CDVD_CAPACITY 0x25
|
#define GPCMD_READ_CDVD_CAPACITY 0x25
|
||||||
#define GPCMD_READ_CD 0xbe
|
#define GPCMD_READ_CD 0xbe
|
||||||
@ -480,7 +481,9 @@ struct cdrom_generic_command
|
|||||||
#define GPCMD_TEST_UNIT_READY 0x00
|
#define GPCMD_TEST_UNIT_READY 0x00
|
||||||
#define GPCMD_VERIFY_10 0x2f
|
#define GPCMD_VERIFY_10 0x2f
|
||||||
#define GPCMD_WRITE_10 0x2a
|
#define GPCMD_WRITE_10 0x2a
|
||||||
|
#define GPCMD_WRITE_12 0xaa
|
||||||
#define GPCMD_WRITE_AND_VERIFY_10 0x2e
|
#define GPCMD_WRITE_AND_VERIFY_10 0x2e
|
||||||
|
#define GPCMD_WRITE_BUFFER 0x3b
|
||||||
/* This is listed as optional in ATAPI 2.6, but is (curiously)
|
/* This is listed as optional in ATAPI 2.6, but is (curiously)
|
||||||
* missing from Mt. Fuji, Table 57. It _is_ mentioned in Mt. Fuji
|
* missing from Mt. Fuji, Table 57. It _is_ mentioned in Mt. Fuji
|
||||||
* Table 377 as an MMC command for SCSi devices though... Most ATAPI
|
* Table 377 as an MMC command for SCSi devices though... Most ATAPI
|
||||||
|
@ -35,6 +35,7 @@
|
|||||||
#include <linux/workqueue.h>
|
#include <linux/workqueue.h>
|
||||||
#include <scsi/scsi_host.h>
|
#include <scsi/scsi_host.h>
|
||||||
#include <linux/acpi.h>
|
#include <linux/acpi.h>
|
||||||
|
#include <linux/cdrom.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Define if arch has non-standard setup. This is a _PCI_ standard
|
* Define if arch has non-standard setup. This is a _PCI_ standard
|
||||||
@ -143,10 +144,11 @@ enum {
|
|||||||
ATA_DFLAG_NCQ_OFF = (1 << 13), /* device limited to non-NCQ mode */
|
ATA_DFLAG_NCQ_OFF = (1 << 13), /* device limited to non-NCQ mode */
|
||||||
ATA_DFLAG_SPUNDOWN = (1 << 14), /* XXX: for spindown_compat */
|
ATA_DFLAG_SPUNDOWN = (1 << 14), /* XXX: for spindown_compat */
|
||||||
ATA_DFLAG_SLEEPING = (1 << 15), /* device is sleeping */
|
ATA_DFLAG_SLEEPING = (1 << 15), /* device is sleeping */
|
||||||
ATA_DFLAG_INIT_MASK = (1 << 16) - 1,
|
ATA_DFLAG_DUBIOUS_XFER = (1 << 16), /* data transfer not verified */
|
||||||
|
ATA_DFLAG_INIT_MASK = (1 << 24) - 1,
|
||||||
|
|
||||||
ATA_DFLAG_DETACH = (1 << 16),
|
ATA_DFLAG_DETACH = (1 << 24),
|
||||||
ATA_DFLAG_DETACHED = (1 << 17),
|
ATA_DFLAG_DETACHED = (1 << 25),
|
||||||
|
|
||||||
ATA_DEV_UNKNOWN = 0, /* unknown device */
|
ATA_DEV_UNKNOWN = 0, /* unknown device */
|
||||||
ATA_DEV_ATA = 1, /* ATA device */
|
ATA_DEV_ATA = 1, /* ATA device */
|
||||||
@ -217,9 +219,7 @@ enum {
|
|||||||
|
|
||||||
/* struct ata_queued_cmd flags */
|
/* struct ata_queued_cmd flags */
|
||||||
ATA_QCFLAG_ACTIVE = (1 << 0), /* cmd not yet ack'd to scsi lyer */
|
ATA_QCFLAG_ACTIVE = (1 << 0), /* cmd not yet ack'd to scsi lyer */
|
||||||
ATA_QCFLAG_SG = (1 << 1), /* have s/g table? */
|
ATA_QCFLAG_DMAMAP = (1 << 1), /* SG table is DMA mapped */
|
||||||
ATA_QCFLAG_SINGLE = (1 << 2), /* no s/g, just a single buffer */
|
|
||||||
ATA_QCFLAG_DMAMAP = ATA_QCFLAG_SG | ATA_QCFLAG_SINGLE,
|
|
||||||
ATA_QCFLAG_IO = (1 << 3), /* standard IO command */
|
ATA_QCFLAG_IO = (1 << 3), /* standard IO command */
|
||||||
ATA_QCFLAG_RESULT_TF = (1 << 4), /* result TF requested */
|
ATA_QCFLAG_RESULT_TF = (1 << 4), /* result TF requested */
|
||||||
ATA_QCFLAG_CLEAR_EXCL = (1 << 5), /* clear excl_link on completion */
|
ATA_QCFLAG_CLEAR_EXCL = (1 << 5), /* clear excl_link on completion */
|
||||||
@ -266,19 +266,15 @@ enum {
|
|||||||
PORT_DISABLED = 2,
|
PORT_DISABLED = 2,
|
||||||
|
|
||||||
/* encoding various smaller bitmaps into a single
|
/* encoding various smaller bitmaps into a single
|
||||||
* unsigned int bitmap
|
* unsigned long bitmap
|
||||||
*/
|
*/
|
||||||
ATA_BITS_PIO = 7,
|
ATA_NR_PIO_MODES = 7,
|
||||||
ATA_BITS_MWDMA = 5,
|
ATA_NR_MWDMA_MODES = 5,
|
||||||
ATA_BITS_UDMA = 8,
|
ATA_NR_UDMA_MODES = 8,
|
||||||
|
|
||||||
ATA_SHIFT_PIO = 0,
|
ATA_SHIFT_PIO = 0,
|
||||||
ATA_SHIFT_MWDMA = ATA_SHIFT_PIO + ATA_BITS_PIO,
|
ATA_SHIFT_MWDMA = ATA_SHIFT_PIO + ATA_NR_PIO_MODES,
|
||||||
ATA_SHIFT_UDMA = ATA_SHIFT_MWDMA + ATA_BITS_MWDMA,
|
ATA_SHIFT_UDMA = ATA_SHIFT_MWDMA + ATA_NR_MWDMA_MODES,
|
||||||
|
|
||||||
ATA_MASK_PIO = ((1 << ATA_BITS_PIO) - 1) << ATA_SHIFT_PIO,
|
|
||||||
ATA_MASK_MWDMA = ((1 << ATA_BITS_MWDMA) - 1) << ATA_SHIFT_MWDMA,
|
|
||||||
ATA_MASK_UDMA = ((1 << ATA_BITS_UDMA) - 1) << ATA_SHIFT_UDMA,
|
|
||||||
|
|
||||||
/* size of buffer to pad xfers ending on unaligned boundaries */
|
/* size of buffer to pad xfers ending on unaligned boundaries */
|
||||||
ATA_DMA_PAD_SZ = 4,
|
ATA_DMA_PAD_SZ = 4,
|
||||||
@ -349,6 +345,21 @@ enum {
|
|||||||
ATA_DMA_MASK_ATA = (1 << 0), /* DMA on ATA Disk */
|
ATA_DMA_MASK_ATA = (1 << 0), /* DMA on ATA Disk */
|
||||||
ATA_DMA_MASK_ATAPI = (1 << 1), /* DMA on ATAPI */
|
ATA_DMA_MASK_ATAPI = (1 << 1), /* DMA on ATAPI */
|
||||||
ATA_DMA_MASK_CFA = (1 << 2), /* DMA on CF Card */
|
ATA_DMA_MASK_CFA = (1 << 2), /* DMA on CF Card */
|
||||||
|
|
||||||
|
/* ATAPI command types */
|
||||||
|
ATAPI_READ = 0, /* READs */
|
||||||
|
ATAPI_WRITE = 1, /* WRITEs */
|
||||||
|
ATAPI_READ_CD = 2, /* READ CD [MSF] */
|
||||||
|
ATAPI_MISC = 3, /* the rest */
|
||||||
|
};
|
||||||
|
|
||||||
|
enum ata_xfer_mask {
|
||||||
|
ATA_MASK_PIO = ((1LU << ATA_NR_PIO_MODES) - 1)
|
||||||
|
<< ATA_SHIFT_PIO,
|
||||||
|
ATA_MASK_MWDMA = ((1LU << ATA_NR_MWDMA_MODES) - 1)
|
||||||
|
<< ATA_SHIFT_MWDMA,
|
||||||
|
ATA_MASK_UDMA = ((1LU << ATA_NR_UDMA_MODES) - 1)
|
||||||
|
<< ATA_SHIFT_UDMA,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum hsm_task_states {
|
enum hsm_task_states {
|
||||||
@ -447,7 +458,7 @@ struct ata_queued_cmd {
|
|||||||
unsigned int tag;
|
unsigned int tag;
|
||||||
unsigned int n_elem;
|
unsigned int n_elem;
|
||||||
unsigned int n_iter;
|
unsigned int n_iter;
|
||||||
unsigned int orig_n_elem;
|
unsigned int mapped_n_elem;
|
||||||
|
|
||||||
int dma_dir;
|
int dma_dir;
|
||||||
|
|
||||||
@ -455,17 +466,18 @@ struct ata_queued_cmd {
|
|||||||
unsigned int sect_size;
|
unsigned int sect_size;
|
||||||
|
|
||||||
unsigned int nbytes;
|
unsigned int nbytes;
|
||||||
|
unsigned int raw_nbytes;
|
||||||
unsigned int curbytes;
|
unsigned int curbytes;
|
||||||
|
|
||||||
struct scatterlist *cursg;
|
struct scatterlist *cursg;
|
||||||
unsigned int cursg_ofs;
|
unsigned int cursg_ofs;
|
||||||
|
|
||||||
|
struct scatterlist *last_sg;
|
||||||
|
struct scatterlist saved_last_sg;
|
||||||
struct scatterlist sgent;
|
struct scatterlist sgent;
|
||||||
struct scatterlist pad_sgent;
|
struct scatterlist extra_sg[2];
|
||||||
void *buf_virt;
|
|
||||||
|
|
||||||
/* DO NOT iterate over __sg manually, use ata_for_each_sg() */
|
struct scatterlist *sg;
|
||||||
struct scatterlist *__sg;
|
|
||||||
|
|
||||||
unsigned int err_mask;
|
unsigned int err_mask;
|
||||||
struct ata_taskfile result_tf;
|
struct ata_taskfile result_tf;
|
||||||
@ -482,7 +494,7 @@ struct ata_port_stats {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct ata_ering_entry {
|
struct ata_ering_entry {
|
||||||
int is_io;
|
unsigned int eflags;
|
||||||
unsigned int err_mask;
|
unsigned int err_mask;
|
||||||
u64 timestamp;
|
u64 timestamp;
|
||||||
};
|
};
|
||||||
@ -522,9 +534,9 @@ struct ata_device {
|
|||||||
unsigned int cdb_len;
|
unsigned int cdb_len;
|
||||||
|
|
||||||
/* per-dev xfer mask */
|
/* per-dev xfer mask */
|
||||||
unsigned int pio_mask;
|
unsigned long pio_mask;
|
||||||
unsigned int mwdma_mask;
|
unsigned long mwdma_mask;
|
||||||
unsigned int udma_mask;
|
unsigned long udma_mask;
|
||||||
|
|
||||||
/* for CHS addressing */
|
/* for CHS addressing */
|
||||||
u16 cylinders; /* Number of cylinders */
|
u16 cylinders; /* Number of cylinders */
|
||||||
@ -560,6 +572,8 @@ struct ata_eh_context {
|
|||||||
int tries[ATA_MAX_DEVICES];
|
int tries[ATA_MAX_DEVICES];
|
||||||
unsigned int classes[ATA_MAX_DEVICES];
|
unsigned int classes[ATA_MAX_DEVICES];
|
||||||
unsigned int did_probe_mask;
|
unsigned int did_probe_mask;
|
||||||
|
unsigned int saved_ncq_enabled;
|
||||||
|
u8 saved_xfer_mode[ATA_MAX_DEVICES];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ata_acpi_drive
|
struct ata_acpi_drive
|
||||||
@ -686,7 +700,8 @@ struct ata_port_operations {
|
|||||||
void (*bmdma_setup) (struct ata_queued_cmd *qc);
|
void (*bmdma_setup) (struct ata_queued_cmd *qc);
|
||||||
void (*bmdma_start) (struct ata_queued_cmd *qc);
|
void (*bmdma_start) (struct ata_queued_cmd *qc);
|
||||||
|
|
||||||
void (*data_xfer) (struct ata_device *, unsigned char *, unsigned int, int);
|
unsigned int (*data_xfer) (struct ata_device *dev, unsigned char *buf,
|
||||||
|
unsigned int buflen, int rw);
|
||||||
|
|
||||||
int (*qc_defer) (struct ata_queued_cmd *qc);
|
int (*qc_defer) (struct ata_queued_cmd *qc);
|
||||||
void (*qc_prep) (struct ata_queued_cmd *qc);
|
void (*qc_prep) (struct ata_queued_cmd *qc);
|
||||||
@ -832,8 +847,6 @@ extern int ata_busy_sleep(struct ata_port *ap,
|
|||||||
unsigned long timeout_pat, unsigned long timeout);
|
unsigned long timeout_pat, unsigned long timeout);
|
||||||
extern void ata_wait_after_reset(struct ata_port *ap, unsigned long deadline);
|
extern void ata_wait_after_reset(struct ata_port *ap, unsigned long deadline);
|
||||||
extern int ata_wait_ready(struct ata_port *ap, unsigned long deadline);
|
extern int ata_wait_ready(struct ata_port *ap, unsigned long deadline);
|
||||||
extern void ata_port_queue_task(struct ata_port *ap, work_func_t fn,
|
|
||||||
void *data, unsigned long delay);
|
|
||||||
extern u32 ata_wait_register(void __iomem *reg, u32 mask, u32 val,
|
extern u32 ata_wait_register(void __iomem *reg, u32 mask, u32 val,
|
||||||
unsigned long interval_msec,
|
unsigned long interval_msec,
|
||||||
unsigned long timeout_msec);
|
unsigned long timeout_msec);
|
||||||
@ -848,6 +861,16 @@ extern void ata_tf_read(struct ata_port *ap, struct ata_taskfile *tf);
|
|||||||
extern void ata_tf_to_fis(const struct ata_taskfile *tf,
|
extern void ata_tf_to_fis(const struct ata_taskfile *tf,
|
||||||
u8 pmp, int is_cmd, u8 *fis);
|
u8 pmp, int is_cmd, u8 *fis);
|
||||||
extern void ata_tf_from_fis(const u8 *fis, struct ata_taskfile *tf);
|
extern void ata_tf_from_fis(const u8 *fis, struct ata_taskfile *tf);
|
||||||
|
extern unsigned long ata_pack_xfermask(unsigned long pio_mask,
|
||||||
|
unsigned long mwdma_mask, unsigned long udma_mask);
|
||||||
|
extern void ata_unpack_xfermask(unsigned long xfer_mask,
|
||||||
|
unsigned long *pio_mask, unsigned long *mwdma_mask,
|
||||||
|
unsigned long *udma_mask);
|
||||||
|
extern u8 ata_xfer_mask2mode(unsigned long xfer_mask);
|
||||||
|
extern unsigned long ata_xfer_mode2mask(u8 xfer_mode);
|
||||||
|
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 void ata_noop_dev_select(struct ata_port *ap, unsigned int device);
|
||||||
extern void ata_std_dev_select(struct ata_port *ap, unsigned int device);
|
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_check_status(struct ata_port *ap);
|
||||||
@ -856,17 +879,15 @@ extern void ata_exec_command(struct ata_port *ap, const struct ata_taskfile *tf)
|
|||||||
extern int ata_port_start(struct ata_port *ap);
|
extern int ata_port_start(struct ata_port *ap);
|
||||||
extern int ata_sff_port_start(struct ata_port *ap);
|
extern int ata_sff_port_start(struct ata_port *ap);
|
||||||
extern irqreturn_t ata_interrupt(int irq, void *dev_instance);
|
extern irqreturn_t ata_interrupt(int irq, void *dev_instance);
|
||||||
extern void ata_data_xfer(struct ata_device *adev, unsigned char *buf,
|
extern unsigned int ata_data_xfer(struct ata_device *dev,
|
||||||
unsigned int buflen, int write_data);
|
unsigned char *buf, unsigned int buflen, int rw);
|
||||||
extern void ata_data_xfer_noirq(struct ata_device *adev, unsigned char *buf,
|
extern unsigned int ata_data_xfer_noirq(struct ata_device *dev,
|
||||||
unsigned int buflen, int write_data);
|
unsigned char *buf, unsigned int buflen, int rw);
|
||||||
extern int ata_std_qc_defer(struct ata_queued_cmd *qc);
|
extern int ata_std_qc_defer(struct ata_queued_cmd *qc);
|
||||||
extern void ata_dumb_qc_prep(struct ata_queued_cmd *qc);
|
extern void ata_dumb_qc_prep(struct ata_queued_cmd *qc);
|
||||||
extern void ata_qc_prep(struct ata_queued_cmd *qc);
|
extern void ata_qc_prep(struct ata_queued_cmd *qc);
|
||||||
extern void ata_noop_qc_prep(struct ata_queued_cmd *qc);
|
extern void ata_noop_qc_prep(struct ata_queued_cmd *qc);
|
||||||
extern unsigned int ata_qc_issue_prot(struct ata_queued_cmd *qc);
|
extern unsigned int ata_qc_issue_prot(struct ata_queued_cmd *qc);
|
||||||
extern void ata_sg_init_one(struct ata_queued_cmd *qc, void *buf,
|
|
||||||
unsigned int buflen);
|
|
||||||
extern void ata_sg_init(struct ata_queued_cmd *qc, struct scatterlist *sg,
|
extern void ata_sg_init(struct ata_queued_cmd *qc, struct scatterlist *sg,
|
||||||
unsigned int n_elem);
|
unsigned int n_elem);
|
||||||
extern unsigned int ata_dev_classify(const struct ata_taskfile *tf);
|
extern unsigned int ata_dev_classify(const struct ata_taskfile *tf);
|
||||||
@ -875,7 +896,6 @@ extern void ata_id_string(const u16 *id, unsigned char *s,
|
|||||||
unsigned int ofs, unsigned int len);
|
unsigned int ofs, unsigned int len);
|
||||||
extern void ata_id_c_string(const u16 *id, unsigned char *s,
|
extern void ata_id_c_string(const u16 *id, unsigned char *s,
|
||||||
unsigned int ofs, unsigned int len);
|
unsigned int ofs, unsigned int len);
|
||||||
extern void ata_id_to_dma_mode(struct ata_device *dev, u8 unknown);
|
|
||||||
extern void ata_bmdma_setup(struct ata_queued_cmd *qc);
|
extern void ata_bmdma_setup(struct ata_queued_cmd *qc);
|
||||||
extern void ata_bmdma_start(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_bmdma_stop(struct ata_queued_cmd *qc);
|
||||||
@ -910,6 +930,7 @@ extern u8 ata_irq_on(struct ata_port *ap);
|
|||||||
extern int ata_cable_40wire(struct ata_port *ap);
|
extern int ata_cable_40wire(struct ata_port *ap);
|
||||||
extern int ata_cable_80wire(struct ata_port *ap);
|
extern int ata_cable_80wire(struct ata_port *ap);
|
||||||
extern int ata_cable_sata(struct ata_port *ap);
|
extern int ata_cable_sata(struct ata_port *ap);
|
||||||
|
extern int ata_cable_ignore(struct ata_port *ap);
|
||||||
extern int ata_cable_unknown(struct ata_port *ap);
|
extern int ata_cable_unknown(struct ata_port *ap);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -917,11 +938,13 @@ extern int ata_cable_unknown(struct ata_port *ap);
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
extern unsigned int ata_pio_need_iordy(const struct ata_device *);
|
extern unsigned int ata_pio_need_iordy(const struct ata_device *);
|
||||||
|
extern const struct ata_timing *ata_timing_find_mode(u8 xfer_mode);
|
||||||
extern int ata_timing_compute(struct ata_device *, unsigned short,
|
extern int ata_timing_compute(struct ata_device *, unsigned short,
|
||||||
struct ata_timing *, int, int);
|
struct ata_timing *, int, int);
|
||||||
extern void ata_timing_merge(const struct ata_timing *,
|
extern void ata_timing_merge(const struct ata_timing *,
|
||||||
const struct ata_timing *, struct ata_timing *,
|
const struct ata_timing *, struct ata_timing *,
|
||||||
unsigned int);
|
unsigned int);
|
||||||
|
extern u8 ata_timing_cycle2mode(unsigned int xfer_shift, int cycle);
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
ATA_TIMING_SETUP = (1 << 0),
|
ATA_TIMING_SETUP = (1 << 0),
|
||||||
@ -948,15 +971,40 @@ static inline const struct ata_acpi_gtm *ata_acpi_init_gtm(struct ata_port *ap)
|
|||||||
return &ap->__acpi_init_gtm;
|
return &ap->__acpi_init_gtm;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
extern int ata_acpi_cbl_80wire(struct ata_port *ap);
|
|
||||||
int ata_acpi_stm(struct ata_port *ap, const struct ata_acpi_gtm *stm);
|
int ata_acpi_stm(struct ata_port *ap, const struct ata_acpi_gtm *stm);
|
||||||
int ata_acpi_gtm(struct ata_port *ap, struct ata_acpi_gtm *stm);
|
int ata_acpi_gtm(struct ata_port *ap, struct ata_acpi_gtm *stm);
|
||||||
|
unsigned long ata_acpi_gtm_xfermask(struct ata_device *dev,
|
||||||
|
const struct ata_acpi_gtm *gtm);
|
||||||
|
int ata_acpi_cbl_80wire(struct ata_port *ap, const struct ata_acpi_gtm *gtm);
|
||||||
#else
|
#else
|
||||||
static inline const struct ata_acpi_gtm *ata_acpi_init_gtm(struct ata_port *ap)
|
static inline const struct ata_acpi_gtm *ata_acpi_init_gtm(struct ata_port *ap)
|
||||||
{
|
{
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
static inline int ata_acpi_cbl_80wire(struct ata_port *ap) { return 0; }
|
|
||||||
|
static inline int ata_acpi_stm(const struct ata_port *ap,
|
||||||
|
struct ata_acpi_gtm *stm)
|
||||||
|
{
|
||||||
|
return -ENOSYS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int ata_acpi_gtm(const struct ata_port *ap,
|
||||||
|
struct ata_acpi_gtm *stm)
|
||||||
|
{
|
||||||
|
return -ENOSYS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline unsigned int ata_acpi_gtm_xfermask(struct ata_device *dev,
|
||||||
|
const struct ata_acpi_gtm *gtm)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int ata_acpi_cbl_80wire(struct ata_port *ap,
|
||||||
|
const struct ata_acpi_gtm *gtm)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_PCI
|
#ifdef CONFIG_PCI
|
||||||
@ -985,8 +1033,12 @@ extern int ata_pci_init_bmdma(struct ata_host *host);
|
|||||||
extern int ata_pci_prepare_sff_host(struct pci_dev *pdev,
|
extern int ata_pci_prepare_sff_host(struct pci_dev *pdev,
|
||||||
const struct ata_port_info * const * ppi,
|
const struct ata_port_info * const * ppi,
|
||||||
struct ata_host **r_host);
|
struct ata_host **r_host);
|
||||||
|
extern int ata_pci_activate_sff_host(struct ata_host *host,
|
||||||
|
irq_handler_t irq_handler,
|
||||||
|
struct scsi_host_template *sht);
|
||||||
extern int pci_test_config_bits(struct pci_dev *pdev, const struct pci_bits *bits);
|
extern int pci_test_config_bits(struct pci_dev *pdev, const struct pci_bits *bits);
|
||||||
extern unsigned long ata_pci_default_filter(struct ata_device *, unsigned long);
|
extern unsigned long ata_pci_default_filter(struct ata_device *dev,
|
||||||
|
unsigned long xfer_mask);
|
||||||
#endif /* CONFIG_PCI */
|
#endif /* CONFIG_PCI */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1074,35 +1126,6 @@ extern void ata_port_pbar_desc(struct ata_port *ap, int bar, ssize_t offset,
|
|||||||
const char *name);
|
const char *name);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
|
||||||
* qc helpers
|
|
||||||
*/
|
|
||||||
static inline struct scatterlist *
|
|
||||||
ata_qc_first_sg(struct ata_queued_cmd *qc)
|
|
||||||
{
|
|
||||||
qc->n_iter = 0;
|
|
||||||
if (qc->n_elem)
|
|
||||||
return qc->__sg;
|
|
||||||
if (qc->pad_len)
|
|
||||||
return &qc->pad_sgent;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline struct scatterlist *
|
|
||||||
ata_qc_next_sg(struct scatterlist *sg, struct ata_queued_cmd *qc)
|
|
||||||
{
|
|
||||||
if (sg == &qc->pad_sgent)
|
|
||||||
return NULL;
|
|
||||||
if (++qc->n_iter < qc->n_elem)
|
|
||||||
return sg_next(sg);
|
|
||||||
if (qc->pad_len)
|
|
||||||
return &qc->pad_sgent;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define ata_for_each_sg(sg, qc) \
|
|
||||||
for (sg = ata_qc_first_sg(qc); sg; sg = ata_qc_next_sg(sg, qc))
|
|
||||||
|
|
||||||
static inline unsigned int ata_tag_valid(unsigned int tag)
|
static inline unsigned int ata_tag_valid(unsigned int tag)
|
||||||
{
|
{
|
||||||
return (tag < ATA_MAX_QUEUE) ? 1 : 0;
|
return (tag < ATA_MAX_QUEUE) ? 1 : 0;
|
||||||
@ -1337,15 +1360,17 @@ static inline void ata_tf_init(struct ata_device *dev, struct ata_taskfile *tf)
|
|||||||
static inline void ata_qc_reinit(struct ata_queued_cmd *qc)
|
static inline void ata_qc_reinit(struct ata_queued_cmd *qc)
|
||||||
{
|
{
|
||||||
qc->dma_dir = DMA_NONE;
|
qc->dma_dir = DMA_NONE;
|
||||||
qc->__sg = NULL;
|
qc->sg = NULL;
|
||||||
qc->flags = 0;
|
qc->flags = 0;
|
||||||
qc->cursg = NULL;
|
qc->cursg = NULL;
|
||||||
qc->cursg_ofs = 0;
|
qc->cursg_ofs = 0;
|
||||||
qc->nbytes = qc->curbytes = 0;
|
qc->nbytes = qc->raw_nbytes = qc->curbytes = 0;
|
||||||
qc->n_elem = 0;
|
qc->n_elem = 0;
|
||||||
|
qc->mapped_n_elem = 0;
|
||||||
qc->n_iter = 0;
|
qc->n_iter = 0;
|
||||||
qc->err_mask = 0;
|
qc->err_mask = 0;
|
||||||
qc->pad_len = 0;
|
qc->pad_len = 0;
|
||||||
|
qc->last_sg = NULL;
|
||||||
qc->sect_size = ATA_SECT_SIZE;
|
qc->sect_size = ATA_SECT_SIZE;
|
||||||
|
|
||||||
ata_tf_init(qc->dev, &qc->tf);
|
ata_tf_init(qc->dev, &qc->tf);
|
||||||
@ -1362,6 +1387,27 @@ static inline int ata_try_flush_cache(const struct ata_device *dev)
|
|||||||
ata_id_has_flush_ext(dev->id);
|
ata_id_has_flush_ext(dev->id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline int atapi_cmd_type(u8 opcode)
|
||||||
|
{
|
||||||
|
switch (opcode) {
|
||||||
|
case GPCMD_READ_10:
|
||||||
|
case GPCMD_READ_12:
|
||||||
|
return ATAPI_READ;
|
||||||
|
|
||||||
|
case GPCMD_WRITE_10:
|
||||||
|
case GPCMD_WRITE_12:
|
||||||
|
case GPCMD_WRITE_AND_VERIFY_10:
|
||||||
|
return ATAPI_WRITE;
|
||||||
|
|
||||||
|
case GPCMD_READ_CD:
|
||||||
|
case GPCMD_READ_CD_MSF:
|
||||||
|
return ATAPI_READ_CD;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return ATAPI_MISC;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static inline unsigned int ac_err_mask(u8 status)
|
static inline unsigned int ac_err_mask(u8 status)
|
||||||
{
|
{
|
||||||
if (status & (ATA_BUSY | ATA_DRQ))
|
if (status & (ATA_BUSY | ATA_DRQ))
|
||||||
|
@ -2066,6 +2066,9 @@
|
|||||||
#define PCI_VENDOR_ID_NETCELL 0x169c
|
#define PCI_VENDOR_ID_NETCELL 0x169c
|
||||||
#define PCI_DEVICE_ID_REVOLUTION 0x0044
|
#define PCI_DEVICE_ID_REVOLUTION 0x0044
|
||||||
|
|
||||||
|
#define PCI_VENDOR_ID_CENATEK 0x16CA
|
||||||
|
#define PCI_DEVICE_ID_CENATEK_IDE 0x0001
|
||||||
|
|
||||||
#define PCI_VENDOR_ID_VITESSE 0x1725
|
#define PCI_VENDOR_ID_VITESSE 0x1725
|
||||||
#define PCI_DEVICE_ID_VITESSE_VSC7174 0x7174
|
#define PCI_DEVICE_ID_VITESSE_VSC7174 0x7174
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user