mirror of
https://github.com/adulau/aha.git
synced 2025-01-02 14:13:18 +00:00
Merge branch 'upstream-linus' of master.kernel.org:/pub/scm/linux/kernel/git/jgarzik/libata-dev
* 'upstream-linus' of master.kernel.org:/pub/scm/linux/kernel/git/jgarzik/libata-dev: (112 commits) [libata] sata_mv: fix irq port status usage [PATCH] libata: move IDENTIFY info printing from ata_dev_read_id() to ata_dev_configure() [PATCH] libata: use local *id instead of dev->id in ata_dev_configure() [PATCH] libata: check Word 88 validity in ata_id_xfer_mask() [PATCH] libata: fix class handling in ata_bus_probe() [PATCH] ahci: enable prefetching for PACKET commands libata: turn on ATAPI by default [PATCH] sata_sil24: lengthen softreset timeout [PATCH] sata_sil24: exit early from softreset if SStatus reports no device [PATCH] libata: fix missing classes[] initialization in ata_bus_probe() [PATCH] libata: kill unused xfer_mode functions [PATCH] libata: reimplement ata_set_mode() using xfer_mask helpers [PATCH] libata: use xfer_mask helpers in ata_dev_set_mode() [PATCH] libata: use ata_id_xfermask() in ata_dev_configure() [PATCH] libata: add xfer_mask handling functions [PATCH] libata: improve xfer mask constants and update ata_mode_string() [PATCH] libata: rename ATA_FLAG_FLUSH_PIO_TASK to ATA_FLAG_FLUSH_PORT_TASK [PATCH] libata: kill unused pio_task and packet_task [PATCH] libata: convert pio_task and packet_task to port_task [PATCH] libata: implement port_task ...
This commit is contained in:
commit
cbe037b46f
24 changed files with 3229 additions and 2029 deletions
|
@ -163,7 +163,7 @@ ncr53c8xx-flags-$(CONFIG_SCSI_ZALON) \
|
|||
CFLAGS_ncr53c8xx.o := $(ncr53c8xx-flags-y) $(ncr53c8xx-flags-m)
|
||||
zalon7xx-objs := zalon.o ncr53c8xx.o
|
||||
NCR_Q720_mod-objs := NCR_Q720.o ncr53c8xx.o
|
||||
libata-objs := libata-core.o libata-scsi.o
|
||||
libata-objs := libata-core.o libata-scsi.o libata-bmdma.o
|
||||
oktagon_esp_mod-objs := oktagon_esp.o oktagon_io.o
|
||||
|
||||
# Files generated that shall be removed upon make clean
|
||||
|
|
|
@ -66,6 +66,9 @@ enum {
|
|||
AHCI_IRQ_ON_SG = (1 << 31),
|
||||
AHCI_CMD_ATAPI = (1 << 5),
|
||||
AHCI_CMD_WRITE = (1 << 6),
|
||||
AHCI_CMD_PREFETCH = (1 << 7),
|
||||
AHCI_CMD_RESET = (1 << 8),
|
||||
AHCI_CMD_CLR_BUSY = (1 << 10),
|
||||
|
||||
RX_FIS_D2H_REG = 0x40, /* offset of D2H Register FIS data */
|
||||
|
||||
|
@ -85,6 +88,7 @@ enum {
|
|||
|
||||
/* HOST_CAP bits */
|
||||
HOST_CAP_64 = (1 << 31), /* PCI DAC (64-bit DMA) support */
|
||||
HOST_CAP_CLO = (1 << 24), /* Command List Override support */
|
||||
|
||||
/* registers for each SATA port */
|
||||
PORT_LST_ADDR = 0x00, /* command list DMA addr */
|
||||
|
@ -138,6 +142,7 @@ enum {
|
|||
PORT_CMD_LIST_ON = (1 << 15), /* cmd list DMA engine running */
|
||||
PORT_CMD_FIS_ON = (1 << 14), /* FIS DMA engine running */
|
||||
PORT_CMD_FIS_RX = (1 << 4), /* Enable FIS receive DMA engine */
|
||||
PORT_CMD_CLO = (1 << 3), /* Command list override */
|
||||
PORT_CMD_POWER_ON = (1 << 2), /* Power up device */
|
||||
PORT_CMD_SPIN_UP = (1 << 1), /* Spin up device */
|
||||
PORT_CMD_START = (1 << 0), /* Enable port DMA engine */
|
||||
|
@ -184,9 +189,9 @@ struct ahci_port_priv {
|
|||
static u32 ahci_scr_read (struct ata_port *ap, unsigned int sc_reg);
|
||||
static void ahci_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val);
|
||||
static int ahci_init_one (struct pci_dev *pdev, const struct pci_device_id *ent);
|
||||
static int ahci_qc_issue(struct ata_queued_cmd *qc);
|
||||
static unsigned int ahci_qc_issue(struct ata_queued_cmd *qc);
|
||||
static irqreturn_t ahci_interrupt (int irq, void *dev_instance, struct pt_regs *regs);
|
||||
static void ahci_phy_reset(struct ata_port *ap);
|
||||
static int ahci_probe_reset(struct ata_port *ap, unsigned int *classes);
|
||||
static void ahci_irq_clear(struct ata_port *ap);
|
||||
static void ahci_eng_timeout(struct ata_port *ap);
|
||||
static int ahci_port_start(struct ata_port *ap);
|
||||
|
@ -202,11 +207,11 @@ static struct scsi_host_template ahci_sht = {
|
|||
.name = DRV_NAME,
|
||||
.ioctl = ata_scsi_ioctl,
|
||||
.queuecommand = ata_scsi_queuecmd,
|
||||
.eh_timed_out = ata_scsi_timed_out,
|
||||
.eh_strategy_handler = ata_scsi_error,
|
||||
.can_queue = ATA_DEF_QUEUE,
|
||||
.this_id = ATA_SHT_THIS_ID,
|
||||
.sg_tablesize = AHCI_MAX_SG,
|
||||
.max_sectors = ATA_MAX_SECTORS,
|
||||
.cmd_per_lun = ATA_SHT_CMD_PER_LUN,
|
||||
.emulated = ATA_SHT_EMULATED,
|
||||
.use_clustering = AHCI_USE_CLUSTERING,
|
||||
|
@ -225,7 +230,7 @@ static const struct ata_port_operations ahci_ops = {
|
|||
|
||||
.tf_read = ahci_tf_read,
|
||||
|
||||
.phy_reset = ahci_phy_reset,
|
||||
.probe_reset = ahci_probe_reset,
|
||||
|
||||
.qc_prep = ahci_qc_prep,
|
||||
.qc_issue = ahci_qc_issue,
|
||||
|
@ -247,8 +252,7 @@ static const struct ata_port_info ahci_port_info[] = {
|
|||
{
|
||||
.sht = &ahci_sht,
|
||||
.host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
|
||||
ATA_FLAG_SATA_RESET | ATA_FLAG_MMIO |
|
||||
ATA_FLAG_PIO_DMA,
|
||||
ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA,
|
||||
.pio_mask = 0x1f, /* pio0-4 */
|
||||
.udma_mask = 0x7f, /* udma0-6 ; FIXME */
|
||||
.port_ops = &ahci_ops,
|
||||
|
@ -450,17 +454,48 @@ static void ahci_scr_write (struct ata_port *ap, unsigned int sc_reg_in,
|
|||
writel(val, (void __iomem *) ap->ioaddr.scr_addr + (sc_reg * 4));
|
||||
}
|
||||
|
||||
static void ahci_phy_reset(struct ata_port *ap)
|
||||
static int ahci_stop_engine(struct ata_port *ap)
|
||||
{
|
||||
void __iomem *mmio = ap->host_set->mmio_base;
|
||||
void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
|
||||
int work;
|
||||
u32 tmp;
|
||||
|
||||
tmp = readl(port_mmio + PORT_CMD);
|
||||
tmp &= ~PORT_CMD_START;
|
||||
writel(tmp, port_mmio + PORT_CMD);
|
||||
|
||||
/* wait for engine to stop. TODO: this could be
|
||||
* as long as 500 msec
|
||||
*/
|
||||
work = 1000;
|
||||
while (work-- > 0) {
|
||||
tmp = readl(port_mmio + PORT_CMD);
|
||||
if ((tmp & PORT_CMD_LIST_ON) == 0)
|
||||
return 0;
|
||||
udelay(10);
|
||||
}
|
||||
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
static void ahci_start_engine(struct ata_port *ap)
|
||||
{
|
||||
void __iomem *mmio = ap->host_set->mmio_base;
|
||||
void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
|
||||
u32 tmp;
|
||||
|
||||
tmp = readl(port_mmio + PORT_CMD);
|
||||
tmp |= PORT_CMD_START;
|
||||
writel(tmp, port_mmio + PORT_CMD);
|
||||
readl(port_mmio + PORT_CMD); /* flush */
|
||||
}
|
||||
|
||||
static unsigned int ahci_dev_classify(struct ata_port *ap)
|
||||
{
|
||||
void __iomem *port_mmio = (void __iomem *) ap->ioaddr.cmd_addr;
|
||||
struct ata_taskfile tf;
|
||||
struct ata_device *dev = &ap->device[0];
|
||||
u32 new_tmp, tmp;
|
||||
|
||||
__sata_phy_reset(ap);
|
||||
|
||||
if (ap->flags & ATA_FLAG_PORT_DISABLED)
|
||||
return;
|
||||
u32 tmp;
|
||||
|
||||
tmp = readl(port_mmio + PORT_SIG);
|
||||
tf.lbah = (tmp >> 24) & 0xff;
|
||||
|
@ -468,15 +503,46 @@ static void ahci_phy_reset(struct ata_port *ap)
|
|||
tf.lbal = (tmp >> 8) & 0xff;
|
||||
tf.nsect = (tmp) & 0xff;
|
||||
|
||||
dev->class = ata_dev_classify(&tf);
|
||||
if (!ata_dev_present(dev)) {
|
||||
ata_port_disable(ap);
|
||||
return;
|
||||
}
|
||||
return ata_dev_classify(&tf);
|
||||
}
|
||||
|
||||
static void ahci_fill_cmd_slot(struct ahci_port_priv *pp, u32 opts)
|
||||
{
|
||||
pp->cmd_slot[0].opts = cpu_to_le32(opts);
|
||||
pp->cmd_slot[0].status = 0;
|
||||
pp->cmd_slot[0].tbl_addr = cpu_to_le32(pp->cmd_tbl_dma & 0xffffffff);
|
||||
pp->cmd_slot[0].tbl_addr_hi = cpu_to_le32((pp->cmd_tbl_dma >> 16) >> 16);
|
||||
}
|
||||
|
||||
static int ahci_hardreset(struct ata_port *ap, int verbose, unsigned int *class)
|
||||
{
|
||||
int rc;
|
||||
|
||||
DPRINTK("ENTER\n");
|
||||
|
||||
ahci_stop_engine(ap);
|
||||
rc = sata_std_hardreset(ap, verbose, class);
|
||||
ahci_start_engine(ap);
|
||||
|
||||
if (rc == 0)
|
||||
*class = ahci_dev_classify(ap);
|
||||
if (*class == ATA_DEV_UNKNOWN)
|
||||
*class = ATA_DEV_NONE;
|
||||
|
||||
DPRINTK("EXIT, rc=%d, class=%u\n", rc, *class);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void ahci_postreset(struct ata_port *ap, unsigned int *class)
|
||||
{
|
||||
void __iomem *port_mmio = (void __iomem *) ap->ioaddr.cmd_addr;
|
||||
u32 new_tmp, tmp;
|
||||
|
||||
ata_std_postreset(ap, class);
|
||||
|
||||
/* Make sure port's ATAPI bit is set appropriately */
|
||||
new_tmp = tmp = readl(port_mmio + PORT_CMD);
|
||||
if (dev->class == ATA_DEV_ATAPI)
|
||||
if (*class == ATA_DEV_ATAPI)
|
||||
new_tmp |= PORT_CMD_ATAPI;
|
||||
else
|
||||
new_tmp &= ~PORT_CMD_ATAPI;
|
||||
|
@ -486,6 +552,12 @@ static void ahci_phy_reset(struct ata_port *ap)
|
|||
}
|
||||
}
|
||||
|
||||
static int ahci_probe_reset(struct ata_port *ap, unsigned int *classes)
|
||||
{
|
||||
return ata_drive_probe_reset(ap, NULL, NULL, ahci_hardreset,
|
||||
ahci_postreset, classes);
|
||||
}
|
||||
|
||||
static u8 ahci_check_status(struct ata_port *ap)
|
||||
{
|
||||
void __iomem *mmio = (void __iomem *) ap->ioaddr.cmd_addr;
|
||||
|
@ -533,42 +605,36 @@ static void ahci_qc_prep(struct ata_queued_cmd *qc)
|
|||
{
|
||||
struct ata_port *ap = qc->ap;
|
||||
struct ahci_port_priv *pp = ap->private_data;
|
||||
int is_atapi = is_atapi_taskfile(&qc->tf);
|
||||
u32 opts;
|
||||
const u32 cmd_fis_len = 5; /* five dwords */
|
||||
unsigned int n_elem;
|
||||
|
||||
/*
|
||||
* Fill in command slot information (currently only one slot,
|
||||
* slot 0, is currently since we don't do queueing)
|
||||
*/
|
||||
|
||||
opts = cmd_fis_len;
|
||||
if (qc->tf.flags & ATA_TFLAG_WRITE)
|
||||
opts |= AHCI_CMD_WRITE;
|
||||
if (is_atapi_taskfile(&qc->tf))
|
||||
opts |= AHCI_CMD_ATAPI;
|
||||
|
||||
pp->cmd_slot[0].opts = cpu_to_le32(opts);
|
||||
pp->cmd_slot[0].status = 0;
|
||||
pp->cmd_slot[0].tbl_addr = cpu_to_le32(pp->cmd_tbl_dma & 0xffffffff);
|
||||
pp->cmd_slot[0].tbl_addr_hi = cpu_to_le32((pp->cmd_tbl_dma >> 16) >> 16);
|
||||
|
||||
/*
|
||||
* Fill in command table information. First, the header,
|
||||
* a SATA Register - Host to Device command FIS.
|
||||
*/
|
||||
ata_tf_to_fis(&qc->tf, pp->cmd_tbl, 0);
|
||||
if (opts & AHCI_CMD_ATAPI) {
|
||||
if (is_atapi) {
|
||||
memset(pp->cmd_tbl + AHCI_CMD_TBL_CDB, 0, 32);
|
||||
memcpy(pp->cmd_tbl + AHCI_CMD_TBL_CDB, qc->cdb, ap->cdb_len);
|
||||
memcpy(pp->cmd_tbl + AHCI_CMD_TBL_CDB, qc->cdb,
|
||||
qc->dev->cdb_len);
|
||||
}
|
||||
|
||||
if (!(qc->flags & ATA_QCFLAG_DMAMAP))
|
||||
return;
|
||||
n_elem = 0;
|
||||
if (qc->flags & ATA_QCFLAG_DMAMAP)
|
||||
n_elem = ahci_fill_sg(qc);
|
||||
|
||||
n_elem = ahci_fill_sg(qc);
|
||||
/*
|
||||
* Fill in command slot information.
|
||||
*/
|
||||
opts = cmd_fis_len | n_elem << 16;
|
||||
if (qc->tf.flags & ATA_TFLAG_WRITE)
|
||||
opts |= AHCI_CMD_WRITE;
|
||||
if (is_atapi)
|
||||
opts |= AHCI_CMD_ATAPI | AHCI_CMD_PREFETCH;
|
||||
|
||||
pp->cmd_slot[0].opts |= cpu_to_le32(n_elem << 16);
|
||||
ahci_fill_cmd_slot(pp, opts);
|
||||
}
|
||||
|
||||
static void ahci_restart_port(struct ata_port *ap, u32 irq_stat)
|
||||
|
@ -576,7 +642,6 @@ static void ahci_restart_port(struct ata_port *ap, u32 irq_stat)
|
|||
void __iomem *mmio = ap->host_set->mmio_base;
|
||||
void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
|
||||
u32 tmp;
|
||||
int work;
|
||||
|
||||
if ((ap->device[0].class != ATA_DEV_ATAPI) ||
|
||||
((irq_stat & PORT_IRQ_TF_ERR) == 0))
|
||||
|
@ -592,20 +657,7 @@ static void ahci_restart_port(struct ata_port *ap, u32 irq_stat)
|
|||
readl(port_mmio + PORT_SCR_ERR));
|
||||
|
||||
/* stop DMA */
|
||||
tmp = readl(port_mmio + PORT_CMD);
|
||||
tmp &= ~PORT_CMD_START;
|
||||
writel(tmp, port_mmio + PORT_CMD);
|
||||
|
||||
/* wait for engine to stop. TODO: this could be
|
||||
* as long as 500 msec
|
||||
*/
|
||||
work = 1000;
|
||||
while (work-- > 0) {
|
||||
tmp = readl(port_mmio + PORT_CMD);
|
||||
if ((tmp & PORT_CMD_LIST_ON) == 0)
|
||||
break;
|
||||
udelay(10);
|
||||
}
|
||||
ahci_stop_engine(ap);
|
||||
|
||||
/* clear SATA phy error, if any */
|
||||
tmp = readl(port_mmio + PORT_SCR_ERR);
|
||||
|
@ -624,10 +676,7 @@ static void ahci_restart_port(struct ata_port *ap, u32 irq_stat)
|
|||
}
|
||||
|
||||
/* re-start DMA */
|
||||
tmp = readl(port_mmio + PORT_CMD);
|
||||
tmp |= PORT_CMD_START;
|
||||
writel(tmp, port_mmio + PORT_CMD);
|
||||
readl(port_mmio + PORT_CMD); /* flush */
|
||||
ahci_start_engine(ap);
|
||||
}
|
||||
|
||||
static void ahci_eng_timeout(struct ata_port *ap)
|
||||
|
@ -642,25 +691,13 @@ static void ahci_eng_timeout(struct ata_port *ap)
|
|||
|
||||
spin_lock_irqsave(&host_set->lock, flags);
|
||||
|
||||
ahci_restart_port(ap, readl(port_mmio + PORT_IRQ_STAT));
|
||||
qc = ata_qc_from_tag(ap, ap->active_tag);
|
||||
if (!qc) {
|
||||
printk(KERN_ERR "ata%u: BUG: timeout without command\n",
|
||||
ap->id);
|
||||
} else {
|
||||
ahci_restart_port(ap, readl(port_mmio + PORT_IRQ_STAT));
|
||||
|
||||
/* hack alert! We cannot use the supplied completion
|
||||
* function from inside the ->eh_strategy_handler() thread.
|
||||
* libata is the only user of ->eh_strategy_handler() in
|
||||
* any kernel, so the default scsi_done() assumes it is
|
||||
* not being called from the SCSI EH.
|
||||
*/
|
||||
qc->scsidone = scsi_finish_command;
|
||||
qc->err_mask |= AC_ERR_OTHER;
|
||||
ata_qc_complete(qc);
|
||||
}
|
||||
qc->err_mask |= AC_ERR_TIMEOUT;
|
||||
|
||||
spin_unlock_irqrestore(&host_set->lock, flags);
|
||||
|
||||
ata_eh_qc_complete(qc);
|
||||
}
|
||||
|
||||
static inline int ahci_host_intr(struct ata_port *ap, struct ata_queued_cmd *qc)
|
||||
|
@ -678,7 +715,7 @@ static inline int ahci_host_intr(struct ata_port *ap, struct ata_queued_cmd *qc)
|
|||
ci = readl(port_mmio + PORT_CMD_ISSUE);
|
||||
if (likely((ci & 0x1) == 0)) {
|
||||
if (qc) {
|
||||
assert(qc->err_mask == 0);
|
||||
WARN_ON(qc->err_mask);
|
||||
ata_qc_complete(qc);
|
||||
qc = NULL;
|
||||
}
|
||||
|
@ -697,7 +734,7 @@ static inline int ahci_host_intr(struct ata_port *ap, struct ata_queued_cmd *qc)
|
|||
ahci_restart_port(ap, status);
|
||||
|
||||
if (qc) {
|
||||
qc->err_mask |= AC_ERR_OTHER;
|
||||
qc->err_mask |= err_mask;
|
||||
ata_qc_complete(qc);
|
||||
}
|
||||
}
|
||||
|
@ -770,7 +807,7 @@ static irqreturn_t ahci_interrupt (int irq, void *dev_instance, struct pt_regs *
|
|||
return IRQ_RETVAL(handled);
|
||||
}
|
||||
|
||||
static int ahci_qc_issue(struct ata_queued_cmd *qc)
|
||||
static unsigned int ahci_qc_issue(struct ata_queued_cmd *qc)
|
||||
{
|
||||
struct ata_port *ap = qc->ap;
|
||||
void __iomem *port_mmio = (void __iomem *) ap->ioaddr.cmd_addr;
|
||||
|
|
|
@ -101,36 +101,54 @@ enum {
|
|||
ICH5_PCS = 0x92, /* port control and status */
|
||||
PIIX_SCC = 0x0A, /* sub-class code register */
|
||||
|
||||
PIIX_FLAG_AHCI = (1 << 28), /* AHCI possible */
|
||||
PIIX_FLAG_CHECKINTR = (1 << 29), /* make sure PCI INTx enabled */
|
||||
PIIX_FLAG_COMBINED = (1 << 30), /* combined mode possible */
|
||||
PIIX_FLAG_IGNORE_PCS = (1 << 25), /* ignore PCS present bits */
|
||||
PIIX_FLAG_SCR = (1 << 26), /* SCR available */
|
||||
PIIX_FLAG_AHCI = (1 << 27), /* AHCI possible */
|
||||
PIIX_FLAG_CHECKINTR = (1 << 28), /* make sure PCI INTx enabled */
|
||||
PIIX_FLAG_COMBINED = (1 << 29), /* combined mode possible */
|
||||
/* ICH6/7 use different scheme for map value */
|
||||
PIIX_FLAG_COMBINED_ICH6 = PIIX_FLAG_COMBINED | (1 << 30),
|
||||
|
||||
/* combined mode. if set, PATA is channel 0.
|
||||
* if clear, PATA is channel 1.
|
||||
*/
|
||||
PIIX_COMB_PATA_P0 = (1 << 1),
|
||||
PIIX_COMB = (1 << 2), /* combined mode enabled? */
|
||||
|
||||
PIIX_PORT_ENABLED = (1 << 0),
|
||||
PIIX_PORT_PRESENT = (1 << 4),
|
||||
|
||||
PIIX_80C_PRI = (1 << 5) | (1 << 4),
|
||||
PIIX_80C_SEC = (1 << 7) | (1 << 6),
|
||||
|
||||
ich5_pata = 0,
|
||||
ich5_sata = 1,
|
||||
piix4_pata = 2,
|
||||
ich6_sata = 3,
|
||||
ich6_sata_ahci = 4,
|
||||
/* controller IDs */
|
||||
piix4_pata = 0,
|
||||
ich5_pata = 1,
|
||||
ich5_sata = 2,
|
||||
esb_sata = 3,
|
||||
ich6_sata = 4,
|
||||
ich6_sata_ahci = 5,
|
||||
ich6m_sata_ahci = 6,
|
||||
|
||||
/* constants for mapping table */
|
||||
P0 = 0, /* port 0 */
|
||||
P1 = 1, /* port 1 */
|
||||
P2 = 2, /* port 2 */
|
||||
P3 = 3, /* port 3 */
|
||||
IDE = -1, /* IDE */
|
||||
NA = -2, /* not avaliable */
|
||||
RV = -3, /* reserved */
|
||||
|
||||
PIIX_AHCI_DEVICE = 6,
|
||||
};
|
||||
|
||||
struct piix_map_db {
|
||||
const u32 mask;
|
||||
const int map[][4];
|
||||
};
|
||||
|
||||
static int piix_init_one (struct pci_dev *pdev,
|
||||
const struct pci_device_id *ent);
|
||||
|
||||
static void piix_pata_phy_reset(struct ata_port *ap);
|
||||
static void piix_sata_phy_reset(struct ata_port *ap);
|
||||
static int piix_pata_probe_reset(struct ata_port *ap, unsigned int *classes);
|
||||
static int piix_sata_probe_reset(struct ata_port *ap, unsigned int *classes);
|
||||
static void piix_set_piomode (struct ata_port *ap, struct ata_device *adev);
|
||||
static void piix_set_dmamode (struct ata_port *ap, struct ata_device *adev);
|
||||
|
||||
|
@ -147,19 +165,32 @@ static const struct pci_device_id piix_pci_tbl[] = {
|
|||
* list in drivers/pci/quirks.c.
|
||||
*/
|
||||
|
||||
/* 82801EB (ICH5) */
|
||||
{ 0x8086, 0x24d1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich5_sata },
|
||||
/* 82801EB (ICH5) */
|
||||
{ 0x8086, 0x24df, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich5_sata },
|
||||
{ 0x8086, 0x25a3, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich5_sata },
|
||||
{ 0x8086, 0x25b0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich5_sata },
|
||||
/* 6300ESB (ICH5 variant with broken PCS present bits) */
|
||||
{ 0x8086, 0x25a3, PCI_ANY_ID, PCI_ANY_ID, 0, 0, esb_sata },
|
||||
/* 6300ESB pretending RAID */
|
||||
{ 0x8086, 0x25b0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, esb_sata },
|
||||
/* 82801FB/FW (ICH6/ICH6W) */
|
||||
{ 0x8086, 0x2651, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata },
|
||||
/* 82801FR/FRW (ICH6R/ICH6RW) */
|
||||
{ 0x8086, 0x2652, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata_ahci },
|
||||
{ 0x8086, 0x2653, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata_ahci },
|
||||
/* 82801FBM ICH6M (ICH6R with only port 0 and 2 implemented) */
|
||||
{ 0x8086, 0x2653, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6m_sata_ahci },
|
||||
/* 82801GB/GR/GH (ICH7, identical to ICH6) */
|
||||
{ 0x8086, 0x27c0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata_ahci },
|
||||
{ 0x8086, 0x27c4, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata_ahci },
|
||||
/* 2801GBM/GHM (ICH7M, identical to ICH6M) */
|
||||
{ 0x8086, 0x27c4, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6m_sata_ahci },
|
||||
/* Enterprise Southbridge 2 (where's the datasheet?) */
|
||||
{ 0x8086, 0x2680, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata_ahci },
|
||||
/* SATA Controller 1 IDE (ICH8, no datasheet yet) */
|
||||
{ 0x8086, 0x2820, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata_ahci },
|
||||
/* SATA Controller 2 IDE (ICH8, ditto) */
|
||||
{ 0x8086, 0x2825, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata_ahci },
|
||||
{ 0x8086, 0x2828, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata_ahci },
|
||||
/* Mobile SATA Controller IDE (ICH8M, ditto) */
|
||||
{ 0x8086, 0x2828, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6m_sata_ahci },
|
||||
|
||||
{ } /* terminate list */
|
||||
};
|
||||
|
@ -178,11 +209,11 @@ static struct scsi_host_template piix_sht = {
|
|||
.name = DRV_NAME,
|
||||
.ioctl = ata_scsi_ioctl,
|
||||
.queuecommand = ata_scsi_queuecmd,
|
||||
.eh_timed_out = ata_scsi_timed_out,
|
||||
.eh_strategy_handler = ata_scsi_error,
|
||||
.can_queue = ATA_DEF_QUEUE,
|
||||
.this_id = ATA_SHT_THIS_ID,
|
||||
.sg_tablesize = LIBATA_MAX_PRD,
|
||||
.max_sectors = ATA_MAX_SECTORS,
|
||||
.cmd_per_lun = ATA_SHT_CMD_PER_LUN,
|
||||
.emulated = ATA_SHT_EMULATED,
|
||||
.use_clustering = ATA_SHT_USE_CLUSTERING,
|
||||
|
@ -205,7 +236,7 @@ static const struct ata_port_operations piix_pata_ops = {
|
|||
.exec_command = ata_exec_command,
|
||||
.dev_select = ata_std_dev_select,
|
||||
|
||||
.phy_reset = piix_pata_phy_reset,
|
||||
.probe_reset = piix_pata_probe_reset,
|
||||
|
||||
.bmdma_setup = ata_bmdma_setup,
|
||||
.bmdma_start = ata_bmdma_start,
|
||||
|
@ -233,7 +264,7 @@ static const struct ata_port_operations piix_sata_ops = {
|
|||
.exec_command = ata_exec_command,
|
||||
.dev_select = ata_std_dev_select,
|
||||
|
||||
.phy_reset = piix_sata_phy_reset,
|
||||
.probe_reset = piix_sata_probe_reset,
|
||||
|
||||
.bmdma_setup = ata_bmdma_setup,
|
||||
.bmdma_start = ata_bmdma_start,
|
||||
|
@ -252,12 +283,62 @@ static const struct ata_port_operations piix_sata_ops = {
|
|||
.host_stop = ata_host_stop,
|
||||
};
|
||||
|
||||
static struct piix_map_db ich5_map_db = {
|
||||
.mask = 0x7,
|
||||
.map = {
|
||||
/* PM PS SM SS MAP */
|
||||
{ P0, NA, P1, NA }, /* 000b */
|
||||
{ P1, NA, P0, NA }, /* 001b */
|
||||
{ RV, RV, RV, RV },
|
||||
{ RV, RV, RV, RV },
|
||||
{ P0, P1, IDE, IDE }, /* 100b */
|
||||
{ P1, P0, IDE, IDE }, /* 101b */
|
||||
{ IDE, IDE, P0, P1 }, /* 110b */
|
||||
{ IDE, IDE, P1, P0 }, /* 111b */
|
||||
},
|
||||
};
|
||||
|
||||
static struct piix_map_db ich6_map_db = {
|
||||
.mask = 0x3,
|
||||
.map = {
|
||||
/* PM PS SM SS MAP */
|
||||
{ P0, P1, P2, P3 }, /* 00b */
|
||||
{ IDE, IDE, P1, P3 }, /* 01b */
|
||||
{ P0, P2, IDE, IDE }, /* 10b */
|
||||
{ RV, RV, RV, RV },
|
||||
},
|
||||
};
|
||||
|
||||
static struct piix_map_db ich6m_map_db = {
|
||||
.mask = 0x3,
|
||||
.map = {
|
||||
/* PM PS SM SS MAP */
|
||||
{ P0, P1, P2, P3 }, /* 00b */
|
||||
{ RV, RV, RV, RV },
|
||||
{ P0, P2, IDE, IDE }, /* 10b */
|
||||
{ RV, RV, RV, RV },
|
||||
},
|
||||
};
|
||||
|
||||
static struct ata_port_info piix_port_info[] = {
|
||||
/* piix4_pata */
|
||||
{
|
||||
.sht = &piix_sht,
|
||||
.host_flags = ATA_FLAG_SLAVE_POSS,
|
||||
.pio_mask = 0x1f, /* pio0-4 */
|
||||
#if 0
|
||||
.mwdma_mask = 0x06, /* mwdma1-2 */
|
||||
#else
|
||||
.mwdma_mask = 0x00, /* mwdma broken */
|
||||
#endif
|
||||
.udma_mask = ATA_UDMA_MASK_40C,
|
||||
.port_ops = &piix_pata_ops,
|
||||
},
|
||||
|
||||
/* ich5_pata */
|
||||
{
|
||||
.sht = &piix_sht,
|
||||
.host_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST |
|
||||
PIIX_FLAG_CHECKINTR,
|
||||
.host_flags = ATA_FLAG_SLAVE_POSS | PIIX_FLAG_CHECKINTR,
|
||||
.pio_mask = 0x1f, /* pio0-4 */
|
||||
#if 0
|
||||
.mwdma_mask = 0x06, /* mwdma1-2 */
|
||||
|
@ -271,50 +352,63 @@ static struct ata_port_info piix_port_info[] = {
|
|||
/* ich5_sata */
|
||||
{
|
||||
.sht = &piix_sht,
|
||||
.host_flags = ATA_FLAG_SATA | ATA_FLAG_SRST |
|
||||
PIIX_FLAG_COMBINED | PIIX_FLAG_CHECKINTR,
|
||||
.host_flags = ATA_FLAG_SATA | PIIX_FLAG_COMBINED |
|
||||
PIIX_FLAG_CHECKINTR,
|
||||
.pio_mask = 0x1f, /* pio0-4 */
|
||||
.mwdma_mask = 0x07, /* mwdma0-2 */
|
||||
.udma_mask = 0x7f, /* udma0-6 */
|
||||
.port_ops = &piix_sata_ops,
|
||||
.private_data = &ich5_map_db,
|
||||
},
|
||||
|
||||
/* piix4_pata */
|
||||
/* i6300esb_sata */
|
||||
{
|
||||
.sht = &piix_sht,
|
||||
.host_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
|
||||
.host_flags = ATA_FLAG_SATA | PIIX_FLAG_COMBINED |
|
||||
PIIX_FLAG_CHECKINTR | PIIX_FLAG_IGNORE_PCS,
|
||||
.pio_mask = 0x1f, /* pio0-4 */
|
||||
#if 0
|
||||
.mwdma_mask = 0x06, /* mwdma1-2 */
|
||||
#else
|
||||
.mwdma_mask = 0x00, /* mwdma broken */
|
||||
#endif
|
||||
.udma_mask = ATA_UDMA_MASK_40C,
|
||||
.port_ops = &piix_pata_ops,
|
||||
.mwdma_mask = 0x07, /* mwdma0-2 */
|
||||
.udma_mask = 0x7f, /* udma0-6 */
|
||||
.port_ops = &piix_sata_ops,
|
||||
.private_data = &ich5_map_db,
|
||||
},
|
||||
|
||||
/* ich6_sata */
|
||||
{
|
||||
.sht = &piix_sht,
|
||||
.host_flags = ATA_FLAG_SATA | ATA_FLAG_SRST |
|
||||
PIIX_FLAG_COMBINED | PIIX_FLAG_CHECKINTR |
|
||||
ATA_FLAG_SLAVE_POSS,
|
||||
.host_flags = ATA_FLAG_SATA | PIIX_FLAG_COMBINED_ICH6 |
|
||||
PIIX_FLAG_CHECKINTR | PIIX_FLAG_SCR,
|
||||
.pio_mask = 0x1f, /* pio0-4 */
|
||||
.mwdma_mask = 0x07, /* mwdma0-2 */
|
||||
.udma_mask = 0x7f, /* udma0-6 */
|
||||
.port_ops = &piix_sata_ops,
|
||||
.private_data = &ich6_map_db,
|
||||
},
|
||||
|
||||
/* ich6_sata_ahci */
|
||||
{
|
||||
.sht = &piix_sht,
|
||||
.host_flags = ATA_FLAG_SATA | ATA_FLAG_SRST |
|
||||
PIIX_FLAG_COMBINED | PIIX_FLAG_CHECKINTR |
|
||||
ATA_FLAG_SLAVE_POSS | PIIX_FLAG_AHCI,
|
||||
.host_flags = ATA_FLAG_SATA | PIIX_FLAG_COMBINED_ICH6 |
|
||||
PIIX_FLAG_CHECKINTR | PIIX_FLAG_SCR |
|
||||
PIIX_FLAG_AHCI,
|
||||
.pio_mask = 0x1f, /* pio0-4 */
|
||||
.mwdma_mask = 0x07, /* mwdma0-2 */
|
||||
.udma_mask = 0x7f, /* udma0-6 */
|
||||
.port_ops = &piix_sata_ops,
|
||||
.private_data = &ich6_map_db,
|
||||
},
|
||||
|
||||
/* ich6m_sata_ahci */
|
||||
{
|
||||
.sht = &piix_sht,
|
||||
.host_flags = ATA_FLAG_SATA | PIIX_FLAG_COMBINED_ICH6 |
|
||||
PIIX_FLAG_CHECKINTR | PIIX_FLAG_SCR |
|
||||
PIIX_FLAG_AHCI,
|
||||
.pio_mask = 0x1f, /* pio0-4 */
|
||||
.mwdma_mask = 0x07, /* mwdma0-2 */
|
||||
.udma_mask = 0x7f, /* udma0-6 */
|
||||
.port_ops = &piix_sata_ops,
|
||||
.private_data = &ich6m_map_db,
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -363,102 +457,123 @@ cbl40:
|
|||
}
|
||||
|
||||
/**
|
||||
* piix_pata_phy_reset - Probe specified port on PATA host controller
|
||||
* @ap: Port to probe
|
||||
* piix_pata_probeinit - probeinit for PATA host controller
|
||||
* @ap: Target port
|
||||
*
|
||||
* Probe PATA phy.
|
||||
* Probeinit including cable detection.
|
||||
*
|
||||
* LOCKING:
|
||||
* None (inherited from caller).
|
||||
*/
|
||||
static void piix_pata_probeinit(struct ata_port *ap)
|
||||
{
|
||||
piix_pata_cbl_detect(ap);
|
||||
ata_std_probeinit(ap);
|
||||
}
|
||||
|
||||
static void piix_pata_phy_reset(struct ata_port *ap)
|
||||
/**
|
||||
* piix_pata_probe_reset - Perform reset on PATA port and classify
|
||||
* @ap: Port to reset
|
||||
* @classes: Resulting classes of attached devices
|
||||
*
|
||||
* Reset PATA phy and classify attached devices.
|
||||
*
|
||||
* LOCKING:
|
||||
* None (inherited from caller).
|
||||
*/
|
||||
static int piix_pata_probe_reset(struct ata_port *ap, unsigned int *classes)
|
||||
{
|
||||
struct pci_dev *pdev = to_pci_dev(ap->host_set->dev);
|
||||
|
||||
if (!pci_test_config_bits(pdev, &piix_enable_bits[ap->hard_port_no])) {
|
||||
ata_port_disable(ap);
|
||||
printk(KERN_INFO "ata%u: port disabled. ignoring.\n", ap->id);
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
|
||||
piix_pata_cbl_detect(ap);
|
||||
|
||||
ata_port_probe(ap);
|
||||
|
||||
ata_bus_reset(ap);
|
||||
return ata_drive_probe_reset(ap, piix_pata_probeinit,
|
||||
ata_std_softreset, NULL,
|
||||
ata_std_postreset, classes);
|
||||
}
|
||||
|
||||
/**
|
||||
* piix_sata_probe - Probe PCI device for present SATA devices
|
||||
* @ap: Port associated with the PCI device we wish to probe
|
||||
*
|
||||
* Reads SATA PCI device's PCI config register Port Configuration
|
||||
* and Status (PCS) to determine port and device availability.
|
||||
* Reads and configures SATA PCI device's PCI config register
|
||||
* Port Configuration and Status (PCS) to determine port and
|
||||
* device availability.
|
||||
*
|
||||
* LOCKING:
|
||||
* None (inherited from caller).
|
||||
*
|
||||
* RETURNS:
|
||||
* Non-zero if port is enabled, it may or may not have a device
|
||||
* attached in that case (PRESENT bit would only be set if BIOS probe
|
||||
* was done). Zero is returned if port is disabled.
|
||||
* Mask of avaliable devices on the port.
|
||||
*/
|
||||
static int piix_sata_probe (struct ata_port *ap)
|
||||
static unsigned int piix_sata_probe (struct ata_port *ap)
|
||||
{
|
||||
struct pci_dev *pdev = to_pci_dev(ap->host_set->dev);
|
||||
int combined = (ap->flags & ATA_FLAG_SLAVE_POSS);
|
||||
int orig_mask, mask, i;
|
||||
const unsigned int *map = ap->host_set->private_data;
|
||||
int base = 2 * ap->hard_port_no;
|
||||
unsigned int present_mask = 0;
|
||||
int port, i;
|
||||
u8 pcs;
|
||||
|
||||
mask = (PIIX_PORT_PRESENT << ap->hard_port_no) |
|
||||
(PIIX_PORT_ENABLED << ap->hard_port_no);
|
||||
|
||||
pci_read_config_byte(pdev, ICH5_PCS, &pcs);
|
||||
orig_mask = (int) pcs & 0xff;
|
||||
DPRINTK("ata%u: ENTER, pcs=0x%x base=%d\n", ap->id, pcs, base);
|
||||
|
||||
/* TODO: this is vaguely wrong for ICH6 combined mode,
|
||||
* where only two of the four SATA ports are mapped
|
||||
* onto a single ATA channel. It is also vaguely inaccurate
|
||||
* for ICH5, which has only two ports. However, this is ok,
|
||||
* as further device presence detection code will handle
|
||||
* any false positives produced here.
|
||||
*/
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
mask = (PIIX_PORT_ENABLED << i);
|
||||
|
||||
if ((orig_mask & mask) == mask)
|
||||
if (combined || (i == ap->hard_port_no))
|
||||
return 1;
|
||||
/* enable all ports on this ap and wait for them to settle */
|
||||
for (i = 0; i < 2; i++) {
|
||||
port = map[base + i];
|
||||
if (port >= 0)
|
||||
pcs |= 1 << port;
|
||||
}
|
||||
|
||||
return 0;
|
||||
pci_write_config_byte(pdev, ICH5_PCS, pcs);
|
||||
msleep(100);
|
||||
|
||||
/* let's see which devices are present */
|
||||
pci_read_config_byte(pdev, ICH5_PCS, &pcs);
|
||||
|
||||
for (i = 0; i < 2; i++) {
|
||||
port = map[base + i];
|
||||
if (port < 0)
|
||||
continue;
|
||||
if (ap->flags & PIIX_FLAG_IGNORE_PCS || pcs & 1 << (4 + port))
|
||||
present_mask |= 1 << i;
|
||||
else
|
||||
pcs &= ~(1 << port);
|
||||
}
|
||||
|
||||
/* disable offline ports on non-AHCI controllers */
|
||||
if (!(ap->flags & PIIX_FLAG_AHCI))
|
||||
pci_write_config_byte(pdev, ICH5_PCS, pcs);
|
||||
|
||||
DPRINTK("ata%u: LEAVE, pcs=0x%x present_mask=0x%x\n",
|
||||
ap->id, pcs, present_mask);
|
||||
|
||||
return present_mask;
|
||||
}
|
||||
|
||||
/**
|
||||
* piix_sata_phy_reset - Probe specified port on SATA host controller
|
||||
* @ap: Port to probe
|
||||
* piix_sata_probe_reset - Perform reset on SATA port and classify
|
||||
* @ap: Port to reset
|
||||
* @classes: Resulting classes of attached devices
|
||||
*
|
||||
* Probe SATA phy.
|
||||
* Reset SATA phy and classify attached devices.
|
||||
*
|
||||
* LOCKING:
|
||||
* None (inherited from caller).
|
||||
*/
|
||||
|
||||
static void piix_sata_phy_reset(struct ata_port *ap)
|
||||
static int piix_sata_probe_reset(struct ata_port *ap, unsigned int *classes)
|
||||
{
|
||||
if (!piix_sata_probe(ap)) {
|
||||
ata_port_disable(ap);
|
||||
printk(KERN_INFO "ata%u: SATA port has no device.\n", ap->id);
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
|
||||
ap->cbl = ATA_CBL_SATA;
|
||||
|
||||
ata_port_probe(ap);
|
||||
|
||||
ata_bus_reset(ap);
|
||||
return ata_drive_probe_reset(ap, ata_std_probeinit,
|
||||
ata_std_softreset, NULL,
|
||||
ata_std_postreset, classes);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -627,6 +742,7 @@ static int piix_disable_ahci(struct pci_dev *pdev)
|
|||
|
||||
/**
|
||||
* piix_check_450nx_errata - Check for problem 450NX setup
|
||||
* @ata_dev: the PCI device to check
|
||||
*
|
||||
* Check for the present of 450NX errata #19 and errata #25. If
|
||||
* they are found return an error code so we can turn off DMA
|
||||
|
@ -659,6 +775,54 @@ static int __devinit piix_check_450nx_errata(struct pci_dev *ata_dev)
|
|||
return no_piix_dma;
|
||||
}
|
||||
|
||||
static void __devinit piix_init_sata_map(struct pci_dev *pdev,
|
||||
struct ata_port_info *pinfo)
|
||||
{
|
||||
struct piix_map_db *map_db = pinfo[0].private_data;
|
||||
const unsigned int *map;
|
||||
int i, invalid_map = 0;
|
||||
u8 map_value;
|
||||
|
||||
pci_read_config_byte(pdev, ICH5_PMR, &map_value);
|
||||
|
||||
map = map_db->map[map_value & map_db->mask];
|
||||
|
||||
dev_printk(KERN_INFO, &pdev->dev, "MAP [");
|
||||
for (i = 0; i < 4; i++) {
|
||||
switch (map[i]) {
|
||||
case RV:
|
||||
invalid_map = 1;
|
||||
printk(" XX");
|
||||
break;
|
||||
|
||||
case NA:
|
||||
printk(" --");
|
||||
break;
|
||||
|
||||
case IDE:
|
||||
WARN_ON((i & 1) || map[i + 1] != IDE);
|
||||
pinfo[i / 2] = piix_port_info[ich5_pata];
|
||||
i++;
|
||||
printk(" IDE IDE");
|
||||
break;
|
||||
|
||||
default:
|
||||
printk(" P%d", map[i]);
|
||||
if (i & 1)
|
||||
pinfo[i / 2].host_flags |= ATA_FLAG_SLAVE_POSS;
|
||||
break;
|
||||
}
|
||||
}
|
||||
printk(" ]\n");
|
||||
|
||||
if (invalid_map)
|
||||
dev_printk(KERN_ERR, &pdev->dev,
|
||||
"invalid MAP value %u\n", map_value);
|
||||
|
||||
pinfo[0].private_data = (void *)map;
|
||||
pinfo[1].private_data = (void *)map;
|
||||
}
|
||||
|
||||
/**
|
||||
* piix_init_one - Register PIIX ATA PCI device with kernel services
|
||||
* @pdev: PCI device to register
|
||||
|
@ -677,9 +841,9 @@ static int __devinit piix_check_450nx_errata(struct pci_dev *ata_dev)
|
|||
static int piix_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
{
|
||||
static int printed_version;
|
||||
struct ata_port_info *port_info[2];
|
||||
unsigned int combined = 0;
|
||||
unsigned int pata_chan = 0, sata_chan = 0;
|
||||
struct ata_port_info port_info[2];
|
||||
struct ata_port_info *ppinfo[2] = { &port_info[0], &port_info[1] };
|
||||
unsigned long host_flags;
|
||||
|
||||
if (!printed_version++)
|
||||
dev_printk(KERN_DEBUG, &pdev->dev,
|
||||
|
@ -689,10 +853,12 @@ static int piix_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
|
|||
if (!in_module_init)
|
||||
return -ENODEV;
|
||||
|
||||
port_info[0] = &piix_port_info[ent->driver_data];
|
||||
port_info[1] = &piix_port_info[ent->driver_data];
|
||||
port_info[0] = piix_port_info[ent->driver_data];
|
||||
port_info[1] = piix_port_info[ent->driver_data];
|
||||
|
||||
if (port_info[0]->host_flags & PIIX_FLAG_AHCI) {
|
||||
host_flags = port_info[0].host_flags;
|
||||
|
||||
if (host_flags & PIIX_FLAG_AHCI) {
|
||||
u8 tmp;
|
||||
pci_read_config_byte(pdev, PIIX_SCC, &tmp);
|
||||
if (tmp == PIIX_AHCI_DEVICE) {
|
||||
|
@ -702,18 +868,9 @@ static int piix_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
|
|||
}
|
||||
}
|
||||
|
||||
if (port_info[0]->host_flags & PIIX_FLAG_COMBINED) {
|
||||
u8 tmp;
|
||||
pci_read_config_byte(pdev, ICH5_PMR, &tmp);
|
||||
|
||||
if (tmp & PIIX_COMB) {
|
||||
combined = 1;
|
||||
if (tmp & PIIX_COMB_PATA_P0)
|
||||
sata_chan = 1;
|
||||
else
|
||||
pata_chan = 1;
|
||||
}
|
||||
}
|
||||
/* Initialize SATA map */
|
||||
if (host_flags & ATA_FLAG_SATA)
|
||||
piix_init_sata_map(pdev, port_info);
|
||||
|
||||
/* On ICH5, some BIOSen disable the interrupt using the
|
||||
* PCI_COMMAND_INTX_DISABLE bit added in PCI 2.3.
|
||||
|
@ -721,28 +878,19 @@ static int piix_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
|
|||
* MSI is disabled (and it is disabled, as we don't use
|
||||
* message-signalled interrupts currently).
|
||||
*/
|
||||
if (port_info[0]->host_flags & PIIX_FLAG_CHECKINTR)
|
||||
if (host_flags & PIIX_FLAG_CHECKINTR)
|
||||
pci_intx(pdev, 1);
|
||||
|
||||
if (combined) {
|
||||
port_info[sata_chan] = &piix_port_info[ent->driver_data];
|
||||
port_info[sata_chan]->host_flags |= ATA_FLAG_SLAVE_POSS;
|
||||
port_info[pata_chan] = &piix_port_info[ich5_pata];
|
||||
|
||||
dev_printk(KERN_WARNING, &pdev->dev,
|
||||
"combined mode detected (p=%u, s=%u)\n",
|
||||
pata_chan, sata_chan);
|
||||
}
|
||||
if (piix_check_450nx_errata(pdev)) {
|
||||
/* This writes into the master table but it does not
|
||||
really matter for this errata as we will apply it to
|
||||
all the PIIX devices on the board */
|
||||
port_info[0]->mwdma_mask = 0;
|
||||
port_info[0]->udma_mask = 0;
|
||||
port_info[1]->mwdma_mask = 0;
|
||||
port_info[1]->udma_mask = 0;
|
||||
port_info[0].mwdma_mask = 0;
|
||||
port_info[0].udma_mask = 0;
|
||||
port_info[1].mwdma_mask = 0;
|
||||
port_info[1].udma_mask = 0;
|
||||
}
|
||||
return ata_pci_init_one(pdev, port_info, 2);
|
||||
return ata_pci_init_one(pdev, ppinfo, 2);
|
||||
}
|
||||
|
||||
static int __init piix_init(void)
|
||||
|
|
703
drivers/scsi/libata-bmdma.c
Normal file
703
drivers/scsi/libata-bmdma.c
Normal file
|
@ -0,0 +1,703 @@
|
|||
/*
|
||||
* libata-bmdma.c - helper library for PCI IDE BMDMA
|
||||
*
|
||||
* Maintained by: Jeff Garzik <jgarzik@pobox.com>
|
||||
* Please ALWAYS copy linux-ide@vger.kernel.org
|
||||
* on emails.
|
||||
*
|
||||
* Copyright 2003-2006 Red Hat, Inc. All rights reserved.
|
||||
* Copyright 2003-2006 Jeff Garzik
|
||||
*
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
*
|
||||
* libata documentation is available via 'make {ps|pdf}docs',
|
||||
* as Documentation/DocBook/libata.*
|
||||
*
|
||||
* Hardware documentation available from http://www.t13.org/ and
|
||||
* http://www.sata-io.org/
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/config.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/libata.h>
|
||||
|
||||
#include "libata.h"
|
||||
|
||||
/**
|
||||
* ata_tf_load_pio - send taskfile registers to host controller
|
||||
* @ap: Port to which output is sent
|
||||
* @tf: ATA taskfile register set
|
||||
*
|
||||
* Outputs ATA taskfile to standard ATA host controller.
|
||||
*
|
||||
* LOCKING:
|
||||
* Inherited from caller.
|
||||
*/
|
||||
|
||||
static void ata_tf_load_pio(struct ata_port *ap, const struct ata_taskfile *tf)
|
||||
{
|
||||
struct ata_ioports *ioaddr = &ap->ioaddr;
|
||||
unsigned int is_addr = tf->flags & ATA_TFLAG_ISADDR;
|
||||
|
||||
if (tf->ctl != ap->last_ctl) {
|
||||
outb(tf->ctl, ioaddr->ctl_addr);
|
||||
ap->last_ctl = tf->ctl;
|
||||
ata_wait_idle(ap);
|
||||
}
|
||||
|
||||
if (is_addr && (tf->flags & ATA_TFLAG_LBA48)) {
|
||||
outb(tf->hob_feature, ioaddr->feature_addr);
|
||||
outb(tf->hob_nsect, ioaddr->nsect_addr);
|
||||
outb(tf->hob_lbal, ioaddr->lbal_addr);
|
||||
outb(tf->hob_lbam, ioaddr->lbam_addr);
|
||||
outb(tf->hob_lbah, ioaddr->lbah_addr);
|
||||
VPRINTK("hob: feat 0x%X nsect 0x%X, lba 0x%X 0x%X 0x%X\n",
|
||||
tf->hob_feature,
|
||||
tf->hob_nsect,
|
||||
tf->hob_lbal,
|
||||
tf->hob_lbam,
|
||||
tf->hob_lbah);
|
||||
}
|
||||
|
||||
if (is_addr) {
|
||||
outb(tf->feature, ioaddr->feature_addr);
|
||||
outb(tf->nsect, ioaddr->nsect_addr);
|
||||
outb(tf->lbal, ioaddr->lbal_addr);
|
||||
outb(tf->lbam, ioaddr->lbam_addr);
|
||||
outb(tf->lbah, ioaddr->lbah_addr);
|
||||
VPRINTK("feat 0x%X nsect 0x%X lba 0x%X 0x%X 0x%X\n",
|
||||
tf->feature,
|
||||
tf->nsect,
|
||||
tf->lbal,
|
||||
tf->lbam,
|
||||
tf->lbah);
|
||||
}
|
||||
|
||||
if (tf->flags & ATA_TFLAG_DEVICE) {
|
||||
outb(tf->device, ioaddr->device_addr);
|
||||
VPRINTK("device 0x%X\n", tf->device);
|
||||
}
|
||||
|
||||
ata_wait_idle(ap);
|
||||
}
|
||||
|
||||
/**
|
||||
* ata_tf_load_mmio - send taskfile registers to host controller
|
||||
* @ap: Port to which output is sent
|
||||
* @tf: ATA taskfile register set
|
||||
*
|
||||
* Outputs ATA taskfile to standard ATA host controller using MMIO.
|
||||
*
|
||||
* LOCKING:
|
||||
* Inherited from caller.
|
||||
*/
|
||||
|
||||
static void ata_tf_load_mmio(struct ata_port *ap, const struct ata_taskfile *tf)
|
||||
{
|
||||
struct ata_ioports *ioaddr = &ap->ioaddr;
|
||||
unsigned int is_addr = tf->flags & ATA_TFLAG_ISADDR;
|
||||
|
||||
if (tf->ctl != ap->last_ctl) {
|
||||
writeb(tf->ctl, (void __iomem *) ap->ioaddr.ctl_addr);
|
||||
ap->last_ctl = tf->ctl;
|
||||
ata_wait_idle(ap);
|
||||
}
|
||||
|
||||
if (is_addr && (tf->flags & ATA_TFLAG_LBA48)) {
|
||||
writeb(tf->hob_feature, (void __iomem *) ioaddr->feature_addr);
|
||||
writeb(tf->hob_nsect, (void __iomem *) ioaddr->nsect_addr);
|
||||
writeb(tf->hob_lbal, (void __iomem *) ioaddr->lbal_addr);
|
||||
writeb(tf->hob_lbam, (void __iomem *) ioaddr->lbam_addr);
|
||||
writeb(tf->hob_lbah, (void __iomem *) ioaddr->lbah_addr);
|
||||
VPRINTK("hob: feat 0x%X nsect 0x%X, lba 0x%X 0x%X 0x%X\n",
|
||||
tf->hob_feature,
|
||||
tf->hob_nsect,
|
||||
tf->hob_lbal,
|
||||
tf->hob_lbam,
|
||||
tf->hob_lbah);
|
||||
}
|
||||
|
||||
if (is_addr) {
|
||||
writeb(tf->feature, (void __iomem *) ioaddr->feature_addr);
|
||||
writeb(tf->nsect, (void __iomem *) ioaddr->nsect_addr);
|
||||
writeb(tf->lbal, (void __iomem *) ioaddr->lbal_addr);
|
||||
writeb(tf->lbam, (void __iomem *) ioaddr->lbam_addr);
|
||||
writeb(tf->lbah, (void __iomem *) ioaddr->lbah_addr);
|
||||
VPRINTK("feat 0x%X nsect 0x%X lba 0x%X 0x%X 0x%X\n",
|
||||
tf->feature,
|
||||
tf->nsect,
|
||||
tf->lbal,
|
||||
tf->lbam,
|
||||
tf->lbah);
|
||||
}
|
||||
|
||||
if (tf->flags & ATA_TFLAG_DEVICE) {
|
||||
writeb(tf->device, (void __iomem *) ioaddr->device_addr);
|
||||
VPRINTK("device 0x%X\n", tf->device);
|
||||
}
|
||||
|
||||
ata_wait_idle(ap);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* ata_tf_load - send taskfile registers to host controller
|
||||
* @ap: Port to which output is sent
|
||||
* @tf: ATA taskfile register set
|
||||
*
|
||||
* Outputs ATA taskfile to standard ATA host controller using MMIO
|
||||
* or PIO as indicated by the ATA_FLAG_MMIO flag.
|
||||
* Writes the control, feature, nsect, lbal, lbam, and lbah registers.
|
||||
* Optionally (ATA_TFLAG_LBA48) writes hob_feature, hob_nsect,
|
||||
* hob_lbal, hob_lbam, and hob_lbah.
|
||||
*
|
||||
* This function waits for idle (!BUSY and !DRQ) after writing
|
||||
* registers. If the control register has a new value, this
|
||||
* function also waits for idle after writing control and before
|
||||
* writing the remaining registers.
|
||||
*
|
||||
* May be used as the tf_load() entry in ata_port_operations.
|
||||
*
|
||||
* LOCKING:
|
||||
* Inherited from caller.
|
||||
*/
|
||||
void ata_tf_load(struct ata_port *ap, const struct ata_taskfile *tf)
|
||||
{
|
||||
if (ap->flags & ATA_FLAG_MMIO)
|
||||
ata_tf_load_mmio(ap, tf);
|
||||
else
|
||||
ata_tf_load_pio(ap, tf);
|
||||
}
|
||||
|
||||
/**
|
||||
* ata_exec_command_pio - issue ATA command to host controller
|
||||
* @ap: port to which command is being issued
|
||||
* @tf: ATA taskfile register set
|
||||
*
|
||||
* Issues PIO write to ATA command register, with proper
|
||||
* synchronization with interrupt handler / other threads.
|
||||
*
|
||||
* LOCKING:
|
||||
* spin_lock_irqsave(host_set lock)
|
||||
*/
|
||||
|
||||
static void ata_exec_command_pio(struct ata_port *ap, const struct ata_taskfile *tf)
|
||||
{
|
||||
DPRINTK("ata%u: cmd 0x%X\n", ap->id, tf->command);
|
||||
|
||||
outb(tf->command, ap->ioaddr.command_addr);
|
||||
ata_pause(ap);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* ata_exec_command_mmio - issue ATA command to host controller
|
||||
* @ap: port to which command is being issued
|
||||
* @tf: ATA taskfile register set
|
||||
*
|
||||
* Issues MMIO write to ATA command register, with proper
|
||||
* synchronization with interrupt handler / other threads.
|
||||
*
|
||||
* LOCKING:
|
||||
* spin_lock_irqsave(host_set lock)
|
||||
*/
|
||||
|
||||
static void ata_exec_command_mmio(struct ata_port *ap, const struct ata_taskfile *tf)
|
||||
{
|
||||
DPRINTK("ata%u: cmd 0x%X\n", ap->id, tf->command);
|
||||
|
||||
writeb(tf->command, (void __iomem *) ap->ioaddr.command_addr);
|
||||
ata_pause(ap);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* ata_exec_command - issue ATA command to host controller
|
||||
* @ap: port to which command is being issued
|
||||
* @tf: ATA taskfile register set
|
||||
*
|
||||
* Issues PIO/MMIO write to ATA command register, with proper
|
||||
* synchronization with interrupt handler / other threads.
|
||||
*
|
||||
* LOCKING:
|
||||
* spin_lock_irqsave(host_set lock)
|
||||
*/
|
||||
void ata_exec_command(struct ata_port *ap, const struct ata_taskfile *tf)
|
||||
{
|
||||
if (ap->flags & ATA_FLAG_MMIO)
|
||||
ata_exec_command_mmio(ap, tf);
|
||||
else
|
||||
ata_exec_command_pio(ap, tf);
|
||||
}
|
||||
|
||||
/**
|
||||
* ata_tf_read_pio - input device's ATA taskfile shadow registers
|
||||
* @ap: Port from which input is read
|
||||
* @tf: ATA taskfile register set for storing input
|
||||
*
|
||||
* Reads ATA taskfile registers for currently-selected device
|
||||
* into @tf.
|
||||
*
|
||||
* LOCKING:
|
||||
* Inherited from caller.
|
||||
*/
|
||||
|
||||
static void ata_tf_read_pio(struct ata_port *ap, struct ata_taskfile *tf)
|
||||
{
|
||||
struct ata_ioports *ioaddr = &ap->ioaddr;
|
||||
|
||||
tf->command = ata_check_status(ap);
|
||||
tf->feature = inb(ioaddr->error_addr);
|
||||
tf->nsect = inb(ioaddr->nsect_addr);
|
||||
tf->lbal = inb(ioaddr->lbal_addr);
|
||||
tf->lbam = inb(ioaddr->lbam_addr);
|
||||
tf->lbah = inb(ioaddr->lbah_addr);
|
||||
tf->device = inb(ioaddr->device_addr);
|
||||
|
||||
if (tf->flags & ATA_TFLAG_LBA48) {
|
||||
outb(tf->ctl | ATA_HOB, ioaddr->ctl_addr);
|
||||
tf->hob_feature = inb(ioaddr->error_addr);
|
||||
tf->hob_nsect = inb(ioaddr->nsect_addr);
|
||||
tf->hob_lbal = inb(ioaddr->lbal_addr);
|
||||
tf->hob_lbam = inb(ioaddr->lbam_addr);
|
||||
tf->hob_lbah = inb(ioaddr->lbah_addr);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* ata_tf_read_mmio - input device's ATA taskfile shadow registers
|
||||
* @ap: Port from which input is read
|
||||
* @tf: ATA taskfile register set for storing input
|
||||
*
|
||||
* Reads ATA taskfile registers for currently-selected device
|
||||
* into @tf via MMIO.
|
||||
*
|
||||
* LOCKING:
|
||||
* Inherited from caller.
|
||||
*/
|
||||
|
||||
static void ata_tf_read_mmio(struct ata_port *ap, struct ata_taskfile *tf)
|
||||
{
|
||||
struct ata_ioports *ioaddr = &ap->ioaddr;
|
||||
|
||||
tf->command = ata_check_status(ap);
|
||||
tf->feature = readb((void __iomem *)ioaddr->error_addr);
|
||||
tf->nsect = readb((void __iomem *)ioaddr->nsect_addr);
|
||||
tf->lbal = readb((void __iomem *)ioaddr->lbal_addr);
|
||||
tf->lbam = readb((void __iomem *)ioaddr->lbam_addr);
|
||||
tf->lbah = readb((void __iomem *)ioaddr->lbah_addr);
|
||||
tf->device = readb((void __iomem *)ioaddr->device_addr);
|
||||
|
||||
if (tf->flags & ATA_TFLAG_LBA48) {
|
||||
writeb(tf->ctl | ATA_HOB, (void __iomem *) ap->ioaddr.ctl_addr);
|
||||
tf->hob_feature = readb((void __iomem *)ioaddr->error_addr);
|
||||
tf->hob_nsect = readb((void __iomem *)ioaddr->nsect_addr);
|
||||
tf->hob_lbal = readb((void __iomem *)ioaddr->lbal_addr);
|
||||
tf->hob_lbam = readb((void __iomem *)ioaddr->lbam_addr);
|
||||
tf->hob_lbah = readb((void __iomem *)ioaddr->lbah_addr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* ata_tf_read - input device's ATA taskfile shadow registers
|
||||
* @ap: Port from which input is read
|
||||
* @tf: ATA taskfile register set for storing input
|
||||
*
|
||||
* Reads ATA taskfile registers for currently-selected device
|
||||
* into @tf.
|
||||
*
|
||||
* Reads nsect, lbal, lbam, lbah, and device. If ATA_TFLAG_LBA48
|
||||
* is set, also reads the hob registers.
|
||||
*
|
||||
* May be used as the tf_read() entry in ata_port_operations.
|
||||
*
|
||||
* LOCKING:
|
||||
* Inherited from caller.
|
||||
*/
|
||||
void ata_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
|
||||
{
|
||||
if (ap->flags & ATA_FLAG_MMIO)
|
||||
ata_tf_read_mmio(ap, tf);
|
||||
else
|
||||
ata_tf_read_pio(ap, tf);
|
||||
}
|
||||
|
||||
/**
|
||||
* ata_check_status_pio - Read device status reg & clear interrupt
|
||||
* @ap: port where the device is
|
||||
*
|
||||
* Reads ATA taskfile status register for currently-selected device
|
||||
* and return its value. This also clears pending interrupts
|
||||
* from this device
|
||||
*
|
||||
* LOCKING:
|
||||
* Inherited from caller.
|
||||
*/
|
||||
static u8 ata_check_status_pio(struct ata_port *ap)
|
||||
{
|
||||
return inb(ap->ioaddr.status_addr);
|
||||
}
|
||||
|
||||
/**
|
||||
* ata_check_status_mmio - Read device status reg & clear interrupt
|
||||
* @ap: port where the device is
|
||||
*
|
||||
* Reads ATA taskfile status register for currently-selected device
|
||||
* via MMIO and return its value. This also clears pending interrupts
|
||||
* from this device
|
||||
*
|
||||
* LOCKING:
|
||||
* Inherited from caller.
|
||||
*/
|
||||
static u8 ata_check_status_mmio(struct ata_port *ap)
|
||||
{
|
||||
return readb((void __iomem *) ap->ioaddr.status_addr);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* ata_check_status - Read device status reg & clear interrupt
|
||||
* @ap: port where the device is
|
||||
*
|
||||
* Reads ATA taskfile status register for currently-selected device
|
||||
* and return its value. This also clears pending interrupts
|
||||
* from this device
|
||||
*
|
||||
* May be used as the check_status() entry in ata_port_operations.
|
||||
*
|
||||
* LOCKING:
|
||||
* Inherited from caller.
|
||||
*/
|
||||
u8 ata_check_status(struct ata_port *ap)
|
||||
{
|
||||
if (ap->flags & ATA_FLAG_MMIO)
|
||||
return ata_check_status_mmio(ap);
|
||||
return ata_check_status_pio(ap);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* ata_altstatus - Read device alternate status reg
|
||||
* @ap: port where the device is
|
||||
*
|
||||
* Reads ATA taskfile alternate status register for
|
||||
* currently-selected device and return its value.
|
||||
*
|
||||
* Note: may NOT be used as the check_altstatus() entry in
|
||||
* ata_port_operations.
|
||||
*
|
||||
* LOCKING:
|
||||
* Inherited from caller.
|
||||
*/
|
||||
u8 ata_altstatus(struct ata_port *ap)
|
||||
{
|
||||
if (ap->ops->check_altstatus)
|
||||
return ap->ops->check_altstatus(ap);
|
||||
|
||||
if (ap->flags & ATA_FLAG_MMIO)
|
||||
return readb((void __iomem *)ap->ioaddr.altstatus_addr);
|
||||
return inb(ap->ioaddr.altstatus_addr);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PCI
|
||||
static struct ata_probe_ent *
|
||||
ata_probe_ent_alloc(struct device *dev, const struct ata_port_info *port)
|
||||
{
|
||||
struct ata_probe_ent *probe_ent;
|
||||
|
||||
probe_ent = kzalloc(sizeof(*probe_ent), GFP_KERNEL);
|
||||
if (!probe_ent) {
|
||||
printk(KERN_ERR DRV_NAME "(%s): out of memory\n",
|
||||
kobject_name(&(dev->kobj)));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
INIT_LIST_HEAD(&probe_ent->node);
|
||||
probe_ent->dev = dev;
|
||||
|
||||
probe_ent->sht = port->sht;
|
||||
probe_ent->host_flags = port->host_flags;
|
||||
probe_ent->pio_mask = port->pio_mask;
|
||||
probe_ent->mwdma_mask = port->mwdma_mask;
|
||||
probe_ent->udma_mask = port->udma_mask;
|
||||
probe_ent->port_ops = port->port_ops;
|
||||
|
||||
return probe_ent;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* ata_pci_init_native_mode - Initialize native-mode driver
|
||||
* @pdev: pci device to be initialized
|
||||
* @port: array[2] of pointers to port info structures.
|
||||
* @ports: bitmap of ports present
|
||||
*
|
||||
* Utility function which allocates and initializes an
|
||||
* ata_probe_ent structure for a standard dual-port
|
||||
* PIO-based IDE controller. The returned ata_probe_ent
|
||||
* structure can be passed to ata_device_add(). The returned
|
||||
* ata_probe_ent structure should then be freed with kfree().
|
||||
*
|
||||
* The caller need only pass the address of the primary port, the
|
||||
* secondary will be deduced automatically. If the device has non
|
||||
* standard secondary port mappings this function can be called twice,
|
||||
* once for each interface.
|
||||
*/
|
||||
|
||||
struct ata_probe_ent *
|
||||
ata_pci_init_native_mode(struct pci_dev *pdev, struct ata_port_info **port, int ports)
|
||||
{
|
||||
struct ata_probe_ent *probe_ent =
|
||||
ata_probe_ent_alloc(pci_dev_to_dev(pdev), port[0]);
|
||||
int p = 0;
|
||||
|
||||
if (!probe_ent)
|
||||
return NULL;
|
||||
|
||||
probe_ent->irq = pdev->irq;
|
||||
probe_ent->irq_flags = SA_SHIRQ;
|
||||
probe_ent->private_data = port[0]->private_data;
|
||||
|
||||
if (ports & ATA_PORT_PRIMARY) {
|
||||
probe_ent->port[p].cmd_addr = pci_resource_start(pdev, 0);
|
||||
probe_ent->port[p].altstatus_addr =
|
||||
probe_ent->port[p].ctl_addr =
|
||||
pci_resource_start(pdev, 1) | ATA_PCI_CTL_OFS;
|
||||
probe_ent->port[p].bmdma_addr = pci_resource_start(pdev, 4);
|
||||
ata_std_ports(&probe_ent->port[p]);
|
||||
p++;
|
||||
}
|
||||
|
||||
if (ports & ATA_PORT_SECONDARY) {
|
||||
probe_ent->port[p].cmd_addr = pci_resource_start(pdev, 2);
|
||||
probe_ent->port[p].altstatus_addr =
|
||||
probe_ent->port[p].ctl_addr =
|
||||
pci_resource_start(pdev, 3) | ATA_PCI_CTL_OFS;
|
||||
probe_ent->port[p].bmdma_addr = pci_resource_start(pdev, 4) + 8;
|
||||
ata_std_ports(&probe_ent->port[p]);
|
||||
p++;
|
||||
}
|
||||
|
||||
probe_ent->n_ports = p;
|
||||
return probe_ent;
|
||||
}
|
||||
|
||||
|
||||
static struct ata_probe_ent *ata_pci_init_legacy_port(struct pci_dev *pdev,
|
||||
struct ata_port_info *port, int port_num)
|
||||
{
|
||||
struct ata_probe_ent *probe_ent;
|
||||
|
||||
probe_ent = ata_probe_ent_alloc(pci_dev_to_dev(pdev), port);
|
||||
if (!probe_ent)
|
||||
return NULL;
|
||||
|
||||
probe_ent->legacy_mode = 1;
|
||||
probe_ent->n_ports = 1;
|
||||
probe_ent->hard_port_no = port_num;
|
||||
probe_ent->private_data = port->private_data;
|
||||
|
||||
switch(port_num)
|
||||
{
|
||||
case 0:
|
||||
probe_ent->irq = 14;
|
||||
probe_ent->port[0].cmd_addr = 0x1f0;
|
||||
probe_ent->port[0].altstatus_addr =
|
||||
probe_ent->port[0].ctl_addr = 0x3f6;
|
||||
break;
|
||||
case 1:
|
||||
probe_ent->irq = 15;
|
||||
probe_ent->port[0].cmd_addr = 0x170;
|
||||
probe_ent->port[0].altstatus_addr =
|
||||
probe_ent->port[0].ctl_addr = 0x376;
|
||||
break;
|
||||
}
|
||||
|
||||
probe_ent->port[0].bmdma_addr =
|
||||
pci_resource_start(pdev, 4) + 8 * port_num;
|
||||
ata_std_ports(&probe_ent->port[0]);
|
||||
|
||||
return probe_ent;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* ata_pci_init_one - Initialize/register PCI IDE host controller
|
||||
* @pdev: Controller to be initialized
|
||||
* @port_info: Information from low-level host driver
|
||||
* @n_ports: Number of ports attached to host controller
|
||||
*
|
||||
* This is a helper function which can be called from a driver's
|
||||
* xxx_init_one() probe function if the hardware uses traditional
|
||||
* IDE taskfile registers.
|
||||
*
|
||||
* This function calls pci_enable_device(), reserves its register
|
||||
* regions, sets the dma mask, enables bus master mode, and calls
|
||||
* ata_device_add()
|
||||
*
|
||||
* LOCKING:
|
||||
* Inherited from PCI layer (may sleep).
|
||||
*
|
||||
* RETURNS:
|
||||
* Zero on success, negative on errno-based value on error.
|
||||
*/
|
||||
|
||||
int ata_pci_init_one (struct pci_dev *pdev, struct ata_port_info **port_info,
|
||||
unsigned int n_ports)
|
||||
{
|
||||
struct ata_probe_ent *probe_ent = NULL, *probe_ent2 = NULL;
|
||||
struct ata_port_info *port[2];
|
||||
u8 tmp8, mask;
|
||||
unsigned int legacy_mode = 0;
|
||||
int disable_dev_on_err = 1;
|
||||
int rc;
|
||||
|
||||
DPRINTK("ENTER\n");
|
||||
|
||||
port[0] = port_info[0];
|
||||
if (n_ports > 1)
|
||||
port[1] = port_info[1];
|
||||
else
|
||||
port[1] = port[0];
|
||||
|
||||
if ((port[0]->host_flags & ATA_FLAG_NO_LEGACY) == 0
|
||||
&& (pdev->class >> 8) == PCI_CLASS_STORAGE_IDE) {
|
||||
/* 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 << 3);
|
||||
}
|
||||
|
||||
/* FIXME... */
|
||||
if ((!legacy_mode) && (n_ports > 2)) {
|
||||
printk(KERN_ERR "ata: BUG: native mode, n_ports > 2\n");
|
||||
n_ports = 2;
|
||||
/* For now */
|
||||
}
|
||||
|
||||
/* 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 = pci_enable_device(pdev);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
rc = pci_request_regions(pdev, DRV_NAME);
|
||||
if (rc) {
|
||||
disable_dev_on_err = 0;
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
/* FIXME: Should use platform specific mappers for legacy port ranges */
|
||||
if (legacy_mode) {
|
||||
if (!request_region(0x1f0, 8, "libata")) {
|
||||
struct resource *conflict, res;
|
||||
res.start = 0x1f0;
|
||||
res.end = 0x1f0 + 8 - 1;
|
||||
conflict = ____request_resource(&ioport_resource, &res);
|
||||
if (!strcmp(conflict->name, "libata"))
|
||||
legacy_mode |= (1 << 0);
|
||||
else {
|
||||
disable_dev_on_err = 0;
|
||||
printk(KERN_WARNING "ata: 0x1f0 IDE port busy\n");
|
||||
}
|
||||
} else
|
||||
legacy_mode |= (1 << 0);
|
||||
|
||||
if (!request_region(0x170, 8, "libata")) {
|
||||
struct resource *conflict, res;
|
||||
res.start = 0x170;
|
||||
res.end = 0x170 + 8 - 1;
|
||||
conflict = ____request_resource(&ioport_resource, &res);
|
||||
if (!strcmp(conflict->name, "libata"))
|
||||
legacy_mode |= (1 << 1);
|
||||
else {
|
||||
disable_dev_on_err = 0;
|
||||
printk(KERN_WARNING "ata: 0x170 IDE port busy\n");
|
||||
}
|
||||
} else
|
||||
legacy_mode |= (1 << 1);
|
||||
}
|
||||
|
||||
/* we have legacy mode, but all ports are unavailable */
|
||||
if (legacy_mode == (1 << 3)) {
|
||||
rc = -EBUSY;
|
||||
goto err_out_regions;
|
||||
}
|
||||
|
||||
rc = pci_set_dma_mask(pdev, ATA_DMA_MASK);
|
||||
if (rc)
|
||||
goto err_out_regions;
|
||||
rc = pci_set_consistent_dma_mask(pdev, ATA_DMA_MASK);
|
||||
if (rc)
|
||||
goto err_out_regions;
|
||||
|
||||
if (legacy_mode) {
|
||||
if (legacy_mode & (1 << 0))
|
||||
probe_ent = ata_pci_init_legacy_port(pdev, port[0], 0);
|
||||
if (legacy_mode & (1 << 1))
|
||||
probe_ent2 = ata_pci_init_legacy_port(pdev, port[1], 1);
|
||||
} else {
|
||||
if (n_ports == 2)
|
||||
probe_ent = ata_pci_init_native_mode(pdev, port, ATA_PORT_PRIMARY | ATA_PORT_SECONDARY);
|
||||
else
|
||||
probe_ent = ata_pci_init_native_mode(pdev, port, ATA_PORT_PRIMARY);
|
||||
}
|
||||
if (!probe_ent && !probe_ent2) {
|
||||
rc = -ENOMEM;
|
||||
goto err_out_regions;
|
||||
}
|
||||
|
||||
pci_set_master(pdev);
|
||||
|
||||
/* FIXME: check ata_device_add return */
|
||||
if (legacy_mode) {
|
||||
if (legacy_mode & (1 << 0))
|
||||
ata_device_add(probe_ent);
|
||||
if (legacy_mode & (1 << 1))
|
||||
ata_device_add(probe_ent2);
|
||||
} else
|
||||
ata_device_add(probe_ent);
|
||||
|
||||
kfree(probe_ent);
|
||||
kfree(probe_ent2);
|
||||
|
||||
return 0;
|
||||
|
||||
err_out_regions:
|
||||
if (legacy_mode & (1 << 0))
|
||||
release_region(0x1f0, 8);
|
||||
if (legacy_mode & (1 << 1))
|
||||
release_region(0x170, 8);
|
||||
pci_release_regions(pdev);
|
||||
err_out:
|
||||
if (disable_dev_on_err)
|
||||
pci_disable_device(pdev);
|
||||
return rc;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_PCI */
|
||||
|
File diff suppressed because it is too large
Load diff
|
@ -151,7 +151,7 @@ int ata_cmd_ioctl(struct scsi_device *scsidev, void __user *arg)
|
|||
struct scsi_sense_hdr sshdr;
|
||||
enum dma_data_direction data_dir;
|
||||
|
||||
if (NULL == (void *)arg)
|
||||
if (arg == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
if (copy_from_user(args, arg, sizeof(args)))
|
||||
|
@ -201,7 +201,7 @@ int ata_cmd_ioctl(struct scsi_device *scsidev, void __user *arg)
|
|||
/* Need code to retrieve data from check condition? */
|
||||
|
||||
if ((argbuf)
|
||||
&& copy_to_user((void *)(arg + sizeof(args)), argbuf, argsize))
|
||||
&& copy_to_user(arg + sizeof(args), argbuf, argsize))
|
||||
rc = -EFAULT;
|
||||
error:
|
||||
if (argbuf)
|
||||
|
@ -228,7 +228,7 @@ int ata_task_ioctl(struct scsi_device *scsidev, void __user *arg)
|
|||
u8 args[7];
|
||||
struct scsi_sense_hdr sshdr;
|
||||
|
||||
if (NULL == (void *)arg)
|
||||
if (arg == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
if (copy_from_user(args, arg, sizeof(args)))
|
||||
|
@ -553,7 +553,7 @@ void ata_gen_ata_desc_sense(struct ata_queued_cmd *qc)
|
|||
/*
|
||||
* Read the controller registers.
|
||||
*/
|
||||
assert(NULL != qc->ap->ops->tf_read);
|
||||
WARN_ON(qc->ap->ops->tf_read == NULL);
|
||||
qc->ap->ops->tf_read(qc->ap, tf);
|
||||
|
||||
/*
|
||||
|
@ -628,7 +628,7 @@ void ata_gen_fixed_sense(struct ata_queued_cmd *qc)
|
|||
/*
|
||||
* Read the controller registers.
|
||||
*/
|
||||
assert(NULL != qc->ap->ops->tf_read);
|
||||
WARN_ON(qc->ap->ops->tf_read == NULL);
|
||||
qc->ap->ops->tf_read(qc->ap, tf);
|
||||
|
||||
/*
|
||||
|
@ -684,23 +684,23 @@ int ata_scsi_slave_config(struct scsi_device *sdev)
|
|||
if (sdev->id < ATA_MAX_DEVICES) {
|
||||
struct ata_port *ap;
|
||||
struct ata_device *dev;
|
||||
unsigned int max_sectors;
|
||||
|
||||
ap = (struct ata_port *) &sdev->host->hostdata[0];
|
||||
dev = &ap->device[sdev->id];
|
||||
|
||||
/* TODO: 1024 is an arbitrary number, not the
|
||||
/* TODO: 2048 is an arbitrary number, not the
|
||||
* hardware maximum. This should be increased to
|
||||
* 65534 when Jens Axboe's patch for dynamically
|
||||
* determining max_sectors is merged.
|
||||
*/
|
||||
if ((dev->flags & ATA_DFLAG_LBA48) &&
|
||||
((dev->flags & ATA_DFLAG_LOCK_SECTORS) == 0)) {
|
||||
/*
|
||||
* do not overwrite sdev->host->max_sectors, since
|
||||
* other drives on this host may not support LBA48
|
||||
*/
|
||||
blk_queue_max_sectors(sdev->request_queue, 2048);
|
||||
}
|
||||
max_sectors = ATA_MAX_SECTORS;
|
||||
if (dev->flags & ATA_DFLAG_LBA48)
|
||||
max_sectors = 2048;
|
||||
if (dev->max_sectors)
|
||||
max_sectors = dev->max_sectors;
|
||||
|
||||
blk_queue_max_sectors(sdev->request_queue, max_sectors);
|
||||
|
||||
/*
|
||||
* SATA DMA transfers must be multiples of 4 byte, so
|
||||
|
@ -716,6 +716,47 @@ int ata_scsi_slave_config(struct scsi_device *sdev)
|
|||
return 0; /* scsi layer doesn't check return value, sigh */
|
||||
}
|
||||
|
||||
/**
|
||||
* ata_scsi_timed_out - SCSI layer time out callback
|
||||
* @cmd: timed out SCSI command
|
||||
*
|
||||
* Handles SCSI layer timeout. We race with normal completion of
|
||||
* the qc for @cmd. If the qc is already gone, we lose and let
|
||||
* the scsi command finish (EH_HANDLED). Otherwise, the qc has
|
||||
* timed out and EH should be invoked. Prevent ata_qc_complete()
|
||||
* from finishing it by setting EH_SCHEDULED and return
|
||||
* EH_NOT_HANDLED.
|
||||
*
|
||||
* LOCKING:
|
||||
* Called from timer context
|
||||
*
|
||||
* RETURNS:
|
||||
* EH_HANDLED or EH_NOT_HANDLED
|
||||
*/
|
||||
enum scsi_eh_timer_return ata_scsi_timed_out(struct scsi_cmnd *cmd)
|
||||
{
|
||||
struct Scsi_Host *host = cmd->device->host;
|
||||
struct ata_port *ap = (struct ata_port *) &host->hostdata[0];
|
||||
unsigned long flags;
|
||||
struct ata_queued_cmd *qc;
|
||||
enum scsi_eh_timer_return ret = EH_HANDLED;
|
||||
|
||||
DPRINTK("ENTER\n");
|
||||
|
||||
spin_lock_irqsave(&ap->host_set->lock, flags);
|
||||
qc = ata_qc_from_tag(ap, ap->active_tag);
|
||||
if (qc) {
|
||||
WARN_ON(qc->scsicmd != cmd);
|
||||
qc->flags |= ATA_QCFLAG_EH_SCHEDULED;
|
||||
qc->err_mask |= AC_ERR_TIMEOUT;
|
||||
ret = EH_NOT_HANDLED;
|
||||
}
|
||||
spin_unlock_irqrestore(&ap->host_set->lock, flags);
|
||||
|
||||
DPRINTK("EXIT, ret=%d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* ata_scsi_error - SCSI layer error handler callback
|
||||
* @host: SCSI host on which error occurred
|
||||
|
@ -732,23 +773,84 @@ int ata_scsi_slave_config(struct scsi_device *sdev)
|
|||
int ata_scsi_error(struct Scsi_Host *host)
|
||||
{
|
||||
struct ata_port *ap;
|
||||
unsigned long flags;
|
||||
|
||||
DPRINTK("ENTER\n");
|
||||
|
||||
ap = (struct ata_port *) &host->hostdata[0];
|
||||
|
||||
spin_lock_irqsave(&ap->host_set->lock, flags);
|
||||
WARN_ON(ap->flags & ATA_FLAG_IN_EH);
|
||||
ap->flags |= ATA_FLAG_IN_EH;
|
||||
WARN_ON(ata_qc_from_tag(ap, ap->active_tag) == NULL);
|
||||
spin_unlock_irqrestore(&ap->host_set->lock, flags);
|
||||
|
||||
ata_port_flush_task(ap);
|
||||
|
||||
ap->ops->eng_timeout(ap);
|
||||
|
||||
/* TODO: this is per-command; when queueing is supported
|
||||
* this code will either change or move to a more
|
||||
* appropriate place
|
||||
*/
|
||||
host->host_failed--;
|
||||
INIT_LIST_HEAD(&host->eh_cmd_q);
|
||||
WARN_ON(host->host_failed || !list_empty(&host->eh_cmd_q));
|
||||
|
||||
scsi_eh_flush_done_q(&ap->eh_done_q);
|
||||
|
||||
spin_lock_irqsave(&ap->host_set->lock, flags);
|
||||
ap->flags &= ~ATA_FLAG_IN_EH;
|
||||
spin_unlock_irqrestore(&ap->host_set->lock, flags);
|
||||
|
||||
DPRINTK("EXIT\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ata_eh_scsidone(struct scsi_cmnd *scmd)
|
||||
{
|
||||
/* nada */
|
||||
}
|
||||
|
||||
static void __ata_eh_qc_complete(struct ata_queued_cmd *qc)
|
||||
{
|
||||
struct ata_port *ap = qc->ap;
|
||||
struct scsi_cmnd *scmd = qc->scsicmd;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&ap->host_set->lock, flags);
|
||||
qc->scsidone = ata_eh_scsidone;
|
||||
__ata_qc_complete(qc);
|
||||
WARN_ON(ata_tag_valid(qc->tag));
|
||||
spin_unlock_irqrestore(&ap->host_set->lock, flags);
|
||||
|
||||
scsi_eh_finish_cmd(scmd, &ap->eh_done_q);
|
||||
}
|
||||
|
||||
/**
|
||||
* ata_eh_qc_complete - Complete an active ATA command from EH
|
||||
* @qc: Command to complete
|
||||
*
|
||||
* Indicate to the mid and upper layers that an ATA command has
|
||||
* completed. To be used from EH.
|
||||
*/
|
||||
void ata_eh_qc_complete(struct ata_queued_cmd *qc)
|
||||
{
|
||||
struct scsi_cmnd *scmd = qc->scsicmd;
|
||||
scmd->retries = scmd->allowed;
|
||||
__ata_eh_qc_complete(qc);
|
||||
}
|
||||
|
||||
/**
|
||||
* ata_eh_qc_retry - Tell midlayer to retry an ATA command after EH
|
||||
* @qc: Command to retry
|
||||
*
|
||||
* Indicate to the mid and upper layers that an ATA command
|
||||
* should be retried. To be used from EH.
|
||||
*
|
||||
* SCSI midlayer limits the number of retries to scmd->allowed.
|
||||
* This function might need to adjust scmd->retries for commands
|
||||
* which get retried due to unrelated NCQ failures.
|
||||
*/
|
||||
void ata_eh_qc_retry(struct ata_queued_cmd *qc)
|
||||
{
|
||||
__ata_eh_qc_complete(qc);
|
||||
}
|
||||
|
||||
/**
|
||||
* ata_scsi_start_stop_xlat - Translate SCSI START STOP UNIT command
|
||||
* @qc: Storage for translated ATA taskfile
|
||||
|
@ -985,9 +1087,13 @@ static unsigned int ata_scsi_verify_xlat(struct ata_queued_cmd *qc, const u8 *sc
|
|||
if (dev->flags & ATA_DFLAG_LBA) {
|
||||
tf->flags |= ATA_TFLAG_LBA;
|
||||
|
||||
if (dev->flags & ATA_DFLAG_LBA48) {
|
||||
if (n_block > (64 * 1024))
|
||||
goto invalid_fld;
|
||||
if (lba_28_ok(block, n_block)) {
|
||||
/* use LBA28 */
|
||||
tf->command = ATA_CMD_VERIFY;
|
||||
tf->device |= (block >> 24) & 0xf;
|
||||
} else if (lba_48_ok(block, n_block)) {
|
||||
if (!(dev->flags & ATA_DFLAG_LBA48))
|
||||
goto out_of_range;
|
||||
|
||||
/* use LBA48 */
|
||||
tf->flags |= ATA_TFLAG_LBA48;
|
||||
|
@ -998,15 +1104,9 @@ static unsigned int ata_scsi_verify_xlat(struct ata_queued_cmd *qc, const u8 *sc
|
|||
tf->hob_lbah = (block >> 40) & 0xff;
|
||||
tf->hob_lbam = (block >> 32) & 0xff;
|
||||
tf->hob_lbal = (block >> 24) & 0xff;
|
||||
} else {
|
||||
if (n_block > 256)
|
||||
goto invalid_fld;
|
||||
|
||||
/* use LBA28 */
|
||||
tf->command = ATA_CMD_VERIFY;
|
||||
|
||||
tf->device |= (block >> 24) & 0xf;
|
||||
}
|
||||
} else
|
||||
/* request too large even for LBA48 */
|
||||
goto out_of_range;
|
||||
|
||||
tf->nsect = n_block & 0xff;
|
||||
|
||||
|
@ -1019,8 +1119,8 @@ static unsigned int ata_scsi_verify_xlat(struct ata_queued_cmd *qc, const u8 *sc
|
|||
/* CHS */
|
||||
u32 sect, head, cyl, track;
|
||||
|
||||
if (n_block > 256)
|
||||
goto invalid_fld;
|
||||
if (!lba_28_ok(block, n_block))
|
||||
goto out_of_range;
|
||||
|
||||
/* Convert LBA to CHS */
|
||||
track = (u32)block / dev->sectors;
|
||||
|
@ -1139,9 +1239,11 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, const u8 *scsicm
|
|||
if (dev->flags & ATA_DFLAG_LBA) {
|
||||
tf->flags |= ATA_TFLAG_LBA;
|
||||
|
||||
if (dev->flags & ATA_DFLAG_LBA48) {
|
||||
/* The request -may- be too large for LBA48. */
|
||||
if ((block >> 48) || (n_block > 65536))
|
||||
if (lba_28_ok(block, n_block)) {
|
||||
/* use LBA28 */
|
||||
tf->device |= (block >> 24) & 0xf;
|
||||
} else if (lba_48_ok(block, n_block)) {
|
||||
if (!(dev->flags & ATA_DFLAG_LBA48))
|
||||
goto out_of_range;
|
||||
|
||||
/* use LBA48 */
|
||||
|
@ -1152,15 +1254,9 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, const u8 *scsicm
|
|||
tf->hob_lbah = (block >> 40) & 0xff;
|
||||
tf->hob_lbam = (block >> 32) & 0xff;
|
||||
tf->hob_lbal = (block >> 24) & 0xff;
|
||||
} else {
|
||||
/* use LBA28 */
|
||||
|
||||
/* The request -may- be too large for LBA28. */
|
||||
if ((block >> 28) || (n_block > 256))
|
||||
goto out_of_range;
|
||||
|
||||
tf->device |= (block >> 24) & 0xf;
|
||||
}
|
||||
} else
|
||||
/* request too large even for LBA48 */
|
||||
goto out_of_range;
|
||||
|
||||
if (unlikely(ata_rwcmd_protocol(qc) < 0))
|
||||
goto invalid_fld;
|
||||
|
@ -1178,7 +1274,7 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, const u8 *scsicm
|
|||
u32 sect, head, cyl, track;
|
||||
|
||||
/* The request -may- be too large for CHS addressing. */
|
||||
if ((block >> 28) || (n_block > 256))
|
||||
if (!lba_28_ok(block, n_block))
|
||||
goto out_of_range;
|
||||
|
||||
if (unlikely(ata_rwcmd_protocol(qc) < 0))
|
||||
|
@ -1225,7 +1321,7 @@ nothing_to_do:
|
|||
return 1;
|
||||
}
|
||||
|
||||
static int ata_scsi_qc_complete(struct ata_queued_cmd *qc)
|
||||
static void ata_scsi_qc_complete(struct ata_queued_cmd *qc)
|
||||
{
|
||||
struct scsi_cmnd *cmd = qc->scsicmd;
|
||||
u8 *cdb = cmd->cmnd;
|
||||
|
@ -1262,7 +1358,7 @@ static int ata_scsi_qc_complete(struct ata_queued_cmd *qc)
|
|||
|
||||
qc->scsidone(cmd);
|
||||
|
||||
return 0;
|
||||
ata_qc_free(qc);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1328,8 +1424,9 @@ static void ata_scsi_translate(struct ata_port *ap, struct ata_device *dev,
|
|||
goto early_finish;
|
||||
|
||||
/* select device, send command to hardware */
|
||||
if (ata_qc_issue(qc))
|
||||
goto err_did;
|
||||
qc->err_mask = ata_qc_issue(qc);
|
||||
if (qc->err_mask)
|
||||
ata_qc_complete(qc);
|
||||
|
||||
VPRINTK("EXIT\n");
|
||||
return;
|
||||
|
@ -1472,8 +1569,8 @@ unsigned int ata_scsiop_inq_std(struct ata_scsi_args *args, u8 *rbuf,
|
|||
|
||||
if (buflen > 35) {
|
||||
memcpy(&rbuf[8], "ATA ", 8);
|
||||
ata_dev_id_string(args->id, &rbuf[16], ATA_ID_PROD_OFS, 16);
|
||||
ata_dev_id_string(args->id, &rbuf[32], ATA_ID_FW_REV_OFS, 4);
|
||||
ata_id_string(args->id, &rbuf[16], ATA_ID_PROD_OFS, 16);
|
||||
ata_id_string(args->id, &rbuf[32], ATA_ID_FW_REV_OFS, 4);
|
||||
if (rbuf[32] == 0 || rbuf[32] == ' ')
|
||||
memcpy(&rbuf[32], "n/a ", 4);
|
||||
}
|
||||
|
@ -1547,8 +1644,8 @@ unsigned int ata_scsiop_inq_80(struct ata_scsi_args *args, u8 *rbuf,
|
|||
memcpy(rbuf, hdr, sizeof(hdr));
|
||||
|
||||
if (buflen > (ATA_SERNO_LEN + 4 - 1))
|
||||
ata_dev_id_string(args->id, (unsigned char *) &rbuf[4],
|
||||
ATA_ID_SERNO_OFS, ATA_SERNO_LEN);
|
||||
ata_id_string(args->id, (unsigned char *) &rbuf[4],
|
||||
ATA_ID_SERNO_OFS, ATA_SERNO_LEN);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1713,15 +1810,12 @@ static int ata_dev_supports_fua(u16 *id)
|
|||
if (!ata_id_has_fua(id))
|
||||
return 0;
|
||||
|
||||
model[40] = '\0';
|
||||
fw[8] = '\0';
|
||||
ata_id_c_string(id, model, ATA_ID_PROD_OFS, sizeof(model));
|
||||
ata_id_c_string(id, fw, ATA_ID_FW_REV_OFS, sizeof(fw));
|
||||
|
||||
ata_dev_id_string(id, model, ATA_ID_PROD_OFS, sizeof(model) - 1);
|
||||
ata_dev_id_string(id, fw, ATA_ID_FW_REV_OFS, sizeof(fw) - 1);
|
||||
|
||||
if (strncmp(model, "Maxtor", 6))
|
||||
if (strcmp(model, "Maxtor"))
|
||||
return 1;
|
||||
if (strncmp(fw, "BANC1G10", 8))
|
||||
if (strcmp(fw, "BANC1G10"))
|
||||
return 1;
|
||||
|
||||
return 0; /* blacklisted */
|
||||
|
@ -2015,7 +2109,7 @@ void ata_scsi_badcmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *), u8
|
|||
done(cmd);
|
||||
}
|
||||
|
||||
static int atapi_sense_complete(struct ata_queued_cmd *qc)
|
||||
static void atapi_sense_complete(struct ata_queued_cmd *qc)
|
||||
{
|
||||
if (qc->err_mask && ((qc->err_mask & AC_ERR_DEV) == 0))
|
||||
/* FIXME: not quite right; we don't want the
|
||||
|
@ -2026,7 +2120,7 @@ static int atapi_sense_complete(struct ata_queued_cmd *qc)
|
|||
ata_gen_ata_desc_sense(qc);
|
||||
|
||||
qc->scsidone(qc->scsicmd);
|
||||
return 0;
|
||||
ata_qc_free(qc);
|
||||
}
|
||||
|
||||
/* is it pointless to prefer PIO for "safety reasons"? */
|
||||
|
@ -2056,7 +2150,7 @@ static void atapi_request_sense(struct ata_queued_cmd *qc)
|
|||
ata_sg_init_one(qc, cmd->sense_buffer, sizeof(cmd->sense_buffer));
|
||||
qc->dma_dir = DMA_FROM_DEVICE;
|
||||
|
||||
memset(&qc->cdb, 0, ap->cdb_len);
|
||||
memset(&qc->cdb, 0, qc->dev->cdb_len);
|
||||
qc->cdb[0] = REQUEST_SENSE;
|
||||
qc->cdb[4] = SCSI_SENSE_BUFFERSIZE;
|
||||
|
||||
|
@ -2075,15 +2169,14 @@ static void atapi_request_sense(struct ata_queued_cmd *qc)
|
|||
|
||||
qc->complete_fn = atapi_sense_complete;
|
||||
|
||||
if (ata_qc_issue(qc)) {
|
||||
qc->err_mask |= AC_ERR_OTHER;
|
||||
qc->err_mask = ata_qc_issue(qc);
|
||||
if (qc->err_mask)
|
||||
ata_qc_complete(qc);
|
||||
}
|
||||
|
||||
DPRINTK("EXIT\n");
|
||||
}
|
||||
|
||||
static int atapi_qc_complete(struct ata_queued_cmd *qc)
|
||||
static void atapi_qc_complete(struct ata_queued_cmd *qc)
|
||||
{
|
||||
struct scsi_cmnd *cmd = qc->scsicmd;
|
||||
unsigned int err_mask = qc->err_mask;
|
||||
|
@ -2093,7 +2186,7 @@ static int atapi_qc_complete(struct ata_queued_cmd *qc)
|
|||
if (unlikely(err_mask & AC_ERR_DEV)) {
|
||||
cmd->result = SAM_STAT_CHECK_CONDITION;
|
||||
atapi_request_sense(qc);
|
||||
return 1;
|
||||
return;
|
||||
}
|
||||
|
||||
else if (unlikely(err_mask))
|
||||
|
@ -2133,7 +2226,7 @@ static int atapi_qc_complete(struct ata_queued_cmd *qc)
|
|||
}
|
||||
|
||||
qc->scsidone(cmd);
|
||||
return 0;
|
||||
ata_qc_free(qc);
|
||||
}
|
||||
/**
|
||||
* atapi_xlat - Initialize PACKET taskfile
|
||||
|
@ -2159,7 +2252,7 @@ static unsigned int atapi_xlat(struct ata_queued_cmd *qc, const u8 *scsicmd)
|
|||
if (ata_check_atapi_dma(qc))
|
||||
using_pio = 1;
|
||||
|
||||
memcpy(&qc->cdb, scsicmd, qc->ap->cdb_len);
|
||||
memcpy(&qc->cdb, scsicmd, dev->cdb_len);
|
||||
|
||||
qc->complete_fn = atapi_qc_complete;
|
||||
|
||||
|
@ -2519,7 +2612,8 @@ out_unlock:
|
|||
|
||||
/**
|
||||
* ata_scsi_simulate - simulate SCSI command on ATA device
|
||||
* @id: current IDENTIFY data for target device.
|
||||
* @ap: port the device is connected to
|
||||
* @dev: the target device
|
||||
* @cmd: SCSI command being sent to device.
|
||||
* @done: SCSI command completion function.
|
||||
*
|
||||
|
|
|
@ -45,8 +45,9 @@ extern int libata_fua;
|
|||
extern struct ata_queued_cmd *ata_qc_new_init(struct ata_port *ap,
|
||||
struct ata_device *dev);
|
||||
extern int ata_rwcmd_protocol(struct ata_queued_cmd *qc);
|
||||
extern void ata_port_flush_task(struct ata_port *ap);
|
||||
extern void ata_qc_free(struct ata_queued_cmd *qc);
|
||||
extern int ata_qc_issue(struct ata_queued_cmd *qc);
|
||||
extern unsigned int ata_qc_issue(struct ata_queued_cmd *qc);
|
||||
extern int ata_check_atapi_dma(struct ata_queued_cmd *qc);
|
||||
extern void ata_dev_select(struct ata_port *ap, unsigned int device,
|
||||
unsigned int wait, unsigned int can_sleep);
|
||||
|
|
|
@ -131,7 +131,7 @@ static void adma_host_stop(struct ata_host_set *host_set);
|
|||
static void adma_port_stop(struct ata_port *ap);
|
||||
static void adma_phy_reset(struct ata_port *ap);
|
||||
static void adma_qc_prep(struct ata_queued_cmd *qc);
|
||||
static int adma_qc_issue(struct ata_queued_cmd *qc);
|
||||
static unsigned int adma_qc_issue(struct ata_queued_cmd *qc);
|
||||
static int adma_check_atapi_dma(struct ata_queued_cmd *qc);
|
||||
static void adma_bmdma_stop(struct ata_queued_cmd *qc);
|
||||
static u8 adma_bmdma_status(struct ata_port *ap);
|
||||
|
@ -143,11 +143,11 @@ static struct scsi_host_template adma_ata_sht = {
|
|||
.name = DRV_NAME,
|
||||
.ioctl = ata_scsi_ioctl,
|
||||
.queuecommand = ata_scsi_queuecmd,
|
||||
.eh_timed_out = ata_scsi_timed_out,
|
||||
.eh_strategy_handler = ata_scsi_error,
|
||||
.can_queue = ATA_DEF_QUEUE,
|
||||
.this_id = ATA_SHT_THIS_ID,
|
||||
.sg_tablesize = LIBATA_MAX_PRD,
|
||||
.max_sectors = ATA_MAX_SECTORS,
|
||||
.cmd_per_lun = ATA_SHT_CMD_PER_LUN,
|
||||
.emulated = ATA_SHT_EMULATED,
|
||||
.use_clustering = ENABLE_CLUSTERING,
|
||||
|
@ -419,7 +419,7 @@ static inline void adma_packet_start(struct ata_queued_cmd *qc)
|
|||
writew(aPIOMD4 | aGO, chan + ADMA_CONTROL);
|
||||
}
|
||||
|
||||
static int adma_qc_issue(struct ata_queued_cmd *qc)
|
||||
static unsigned int adma_qc_issue(struct ata_queued_cmd *qc)
|
||||
{
|
||||
struct adma_port_priv *pp = qc->ap->private_data;
|
||||
|
||||
|
|
|
@ -37,7 +37,7 @@
|
|||
#include <asm/io.h>
|
||||
|
||||
#define DRV_NAME "sata_mv"
|
||||
#define DRV_VERSION "0.5"
|
||||
#define DRV_VERSION "0.6"
|
||||
|
||||
enum {
|
||||
/* BAR's are enumerated in terms of pci_resource_start() terms */
|
||||
|
@ -228,7 +228,9 @@ enum {
|
|||
MV_HP_ERRATA_50XXB2 = (1 << 2),
|
||||
MV_HP_ERRATA_60X1B2 = (1 << 3),
|
||||
MV_HP_ERRATA_60X1C0 = (1 << 4),
|
||||
MV_HP_50XX = (1 << 5),
|
||||
MV_HP_ERRATA_XX42A0 = (1 << 5),
|
||||
MV_HP_50XX = (1 << 6),
|
||||
MV_HP_GEN_IIE = (1 << 7),
|
||||
|
||||
/* Port private flags (pp_flags) */
|
||||
MV_PP_FLAG_EDMA_EN = (1 << 0),
|
||||
|
@ -237,6 +239,9 @@ enum {
|
|||
|
||||
#define IS_50XX(hpriv) ((hpriv)->hp_flags & MV_HP_50XX)
|
||||
#define IS_60XX(hpriv) (((hpriv)->hp_flags & MV_HP_50XX) == 0)
|
||||
#define IS_GEN_I(hpriv) IS_50XX(hpriv)
|
||||
#define IS_GEN_II(hpriv) IS_60XX(hpriv)
|
||||
#define IS_GEN_IIE(hpriv) ((hpriv)->hp_flags & MV_HP_GEN_IIE)
|
||||
|
||||
enum {
|
||||
/* Our DMA boundary is determined by an ePRD being unable to handle
|
||||
|
@ -255,6 +260,8 @@ enum chip_type {
|
|||
chip_5080,
|
||||
chip_604x,
|
||||
chip_608x,
|
||||
chip_6042,
|
||||
chip_7042,
|
||||
};
|
||||
|
||||
/* Command ReQuest Block: 32B */
|
||||
|
@ -265,6 +272,14 @@ struct mv_crqb {
|
|||
u16 ata_cmd[11];
|
||||
};
|
||||
|
||||
struct mv_crqb_iie {
|
||||
u32 addr;
|
||||
u32 addr_hi;
|
||||
u32 flags;
|
||||
u32 len;
|
||||
u32 ata_cmd[4];
|
||||
};
|
||||
|
||||
/* Command ResPonse Block: 8B */
|
||||
struct mv_crpb {
|
||||
u16 id;
|
||||
|
@ -328,7 +343,8 @@ static void mv_host_stop(struct ata_host_set *host_set);
|
|||
static int mv_port_start(struct ata_port *ap);
|
||||
static void mv_port_stop(struct ata_port *ap);
|
||||
static void mv_qc_prep(struct ata_queued_cmd *qc);
|
||||
static int mv_qc_issue(struct ata_queued_cmd *qc);
|
||||
static void mv_qc_prep_iie(struct ata_queued_cmd *qc);
|
||||
static unsigned int mv_qc_issue(struct ata_queued_cmd *qc);
|
||||
static irqreturn_t mv_interrupt(int irq, void *dev_instance,
|
||||
struct pt_regs *regs);
|
||||
static void mv_eng_timeout(struct ata_port *ap);
|
||||
|
@ -362,11 +378,11 @@ static struct scsi_host_template mv_sht = {
|
|||
.name = DRV_NAME,
|
||||
.ioctl = ata_scsi_ioctl,
|
||||
.queuecommand = ata_scsi_queuecmd,
|
||||
.eh_timed_out = ata_scsi_timed_out,
|
||||
.eh_strategy_handler = ata_scsi_error,
|
||||
.can_queue = MV_USE_Q_DEPTH,
|
||||
.this_id = ATA_SHT_THIS_ID,
|
||||
.sg_tablesize = MV_MAX_SG_CT / 2,
|
||||
.max_sectors = ATA_MAX_SECTORS,
|
||||
.cmd_per_lun = ATA_SHT_CMD_PER_LUN,
|
||||
.emulated = ATA_SHT_EMULATED,
|
||||
.use_clustering = ATA_SHT_USE_CLUSTERING,
|
||||
|
@ -430,6 +446,33 @@ static const struct ata_port_operations mv6_ops = {
|
|||
.host_stop = mv_host_stop,
|
||||
};
|
||||
|
||||
static const struct ata_port_operations mv_iie_ops = {
|
||||
.port_disable = ata_port_disable,
|
||||
|
||||
.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,
|
||||
|
||||
.phy_reset = mv_phy_reset,
|
||||
|
||||
.qc_prep = mv_qc_prep_iie,
|
||||
.qc_issue = mv_qc_issue,
|
||||
|
||||
.eng_timeout = mv_eng_timeout,
|
||||
|
||||
.irq_handler = mv_interrupt,
|
||||
.irq_clear = mv_irq_clear,
|
||||
|
||||
.scr_read = mv_scr_read,
|
||||
.scr_write = mv_scr_write,
|
||||
|
||||
.port_start = mv_port_start,
|
||||
.port_stop = mv_port_stop,
|
||||
.host_stop = mv_host_stop,
|
||||
};
|
||||
|
||||
static const struct ata_port_info mv_port_info[] = {
|
||||
{ /* chip_504x */
|
||||
.sht = &mv_sht,
|
||||
|
@ -467,6 +510,21 @@ static const struct ata_port_info mv_port_info[] = {
|
|||
.udma_mask = 0x7f, /* udma0-6 */
|
||||
.port_ops = &mv6_ops,
|
||||
},
|
||||
{ /* chip_6042 */
|
||||
.sht = &mv_sht,
|
||||
.host_flags = (MV_COMMON_FLAGS | MV_6XXX_FLAGS),
|
||||
.pio_mask = 0x1f, /* pio0-4 */
|
||||
.udma_mask = 0x7f, /* udma0-6 */
|
||||
.port_ops = &mv_iie_ops,
|
||||
},
|
||||
{ /* chip_7042 */
|
||||
.sht = &mv_sht,
|
||||
.host_flags = (MV_COMMON_FLAGS | MV_6XXX_FLAGS |
|
||||
MV_FLAG_DUAL_HC),
|
||||
.pio_mask = 0x1f, /* pio0-4 */
|
||||
.udma_mask = 0x7f, /* udma0-6 */
|
||||
.port_ops = &mv_iie_ops,
|
||||
},
|
||||
};
|
||||
|
||||
static const struct pci_device_id mv_pci_tbl[] = {
|
||||
|
@ -477,6 +535,7 @@ static const struct pci_device_id mv_pci_tbl[] = {
|
|||
|
||||
{PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x6040), 0, 0, chip_604x},
|
||||
{PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x6041), 0, 0, chip_604x},
|
||||
{PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x6042), 0, 0, chip_6042},
|
||||
{PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x6080), 0, 0, chip_608x},
|
||||
{PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x6081), 0, 0, chip_608x},
|
||||
|
||||
|
@ -572,8 +631,8 @@ static void mv_irq_clear(struct ata_port *ap)
|
|||
* @base: port base address
|
||||
* @pp: port private data
|
||||
*
|
||||
* Verify the local cache of the eDMA state is accurate with an
|
||||
* assert.
|
||||
* Verify the local cache of the eDMA state is accurate with a
|
||||
* WARN_ON.
|
||||
*
|
||||
* LOCKING:
|
||||
* Inherited from caller.
|
||||
|
@ -584,15 +643,15 @@ static void mv_start_dma(void __iomem *base, struct mv_port_priv *pp)
|
|||
writelfl(EDMA_EN, base + EDMA_CMD_OFS);
|
||||
pp->pp_flags |= MV_PP_FLAG_EDMA_EN;
|
||||
}
|
||||
assert(EDMA_EN & readl(base + EDMA_CMD_OFS));
|
||||
WARN_ON(!(EDMA_EN & readl(base + EDMA_CMD_OFS)));
|
||||
}
|
||||
|
||||
/**
|
||||
* mv_stop_dma - Disable eDMA engine
|
||||
* @ap: ATA channel to manipulate
|
||||
*
|
||||
* Verify the local cache of the eDMA state is accurate with an
|
||||
* assert.
|
||||
* Verify the local cache of the eDMA state is accurate with a
|
||||
* WARN_ON.
|
||||
*
|
||||
* LOCKING:
|
||||
* Inherited from caller.
|
||||
|
@ -610,7 +669,7 @@ static void mv_stop_dma(struct ata_port *ap)
|
|||
writelfl(EDMA_DS, port_mmio + EDMA_CMD_OFS);
|
||||
pp->pp_flags &= ~MV_PP_FLAG_EDMA_EN;
|
||||
} else {
|
||||
assert(!(EDMA_EN & readl(port_mmio + EDMA_CMD_OFS)));
|
||||
WARN_ON(EDMA_EN & readl(port_mmio + EDMA_CMD_OFS));
|
||||
}
|
||||
|
||||
/* now properly wait for the eDMA to stop */
|
||||
|
@ -773,6 +832,33 @@ static inline void mv_priv_free(struct mv_port_priv *pp, struct device *dev)
|
|||
dma_free_coherent(dev, MV_PORT_PRIV_DMA_SZ, pp->crpb, pp->crpb_dma);
|
||||
}
|
||||
|
||||
static void mv_edma_cfg(struct mv_host_priv *hpriv, void __iomem *port_mmio)
|
||||
{
|
||||
u32 cfg = readl(port_mmio + EDMA_CFG_OFS);
|
||||
|
||||
/* set up non-NCQ EDMA configuration */
|
||||
cfg &= ~0x1f; /* clear queue depth */
|
||||
cfg &= ~EDMA_CFG_NCQ; /* clear NCQ mode */
|
||||
cfg &= ~(1 << 9); /* disable equeue */
|
||||
|
||||
if (IS_GEN_I(hpriv))
|
||||
cfg |= (1 << 8); /* enab config burst size mask */
|
||||
|
||||
else if (IS_GEN_II(hpriv))
|
||||
cfg |= EDMA_CFG_RD_BRST_EXT | EDMA_CFG_WR_BUFF_LEN;
|
||||
|
||||
else if (IS_GEN_IIE(hpriv)) {
|
||||
cfg |= (1 << 23); /* dis RX PM port mask */
|
||||
cfg &= ~(1 << 16); /* dis FIS-based switching (for now) */
|
||||
cfg &= ~(1 << 19); /* dis 128-entry queue (for now?) */
|
||||
cfg |= (1 << 18); /* enab early completion */
|
||||
cfg |= (1 << 17); /* enab host q cache */
|
||||
cfg |= (1 << 22); /* enab cutthrough */
|
||||
}
|
||||
|
||||
writelfl(cfg, port_mmio + EDMA_CFG_OFS);
|
||||
}
|
||||
|
||||
/**
|
||||
* mv_port_start - Port specific init/start routine.
|
||||
* @ap: ATA channel to manipulate
|
||||
|
@ -786,6 +872,7 @@ static inline void mv_priv_free(struct mv_port_priv *pp, struct device *dev)
|
|||
static int mv_port_start(struct ata_port *ap)
|
||||
{
|
||||
struct device *dev = ap->host_set->dev;
|
||||
struct mv_host_priv *hpriv = ap->host_set->private_data;
|
||||
struct mv_port_priv *pp;
|
||||
void __iomem *port_mmio = mv_ap_base(ap);
|
||||
void *mem;
|
||||
|
@ -829,17 +916,26 @@ static int mv_port_start(struct ata_port *ap)
|
|||
pp->sg_tbl = mem;
|
||||
pp->sg_tbl_dma = mem_dma;
|
||||
|
||||
writelfl(EDMA_CFG_Q_DEPTH | EDMA_CFG_RD_BRST_EXT |
|
||||
EDMA_CFG_WR_BUFF_LEN, port_mmio + EDMA_CFG_OFS);
|
||||
mv_edma_cfg(hpriv, port_mmio);
|
||||
|
||||
writel((pp->crqb_dma >> 16) >> 16, port_mmio + EDMA_REQ_Q_BASE_HI_OFS);
|
||||
writelfl(pp->crqb_dma & EDMA_REQ_Q_BASE_LO_MASK,
|
||||
port_mmio + EDMA_REQ_Q_IN_PTR_OFS);
|
||||
|
||||
writelfl(0, port_mmio + EDMA_REQ_Q_OUT_PTR_OFS);
|
||||
writelfl(0, port_mmio + EDMA_RSP_Q_IN_PTR_OFS);
|
||||
if (hpriv->hp_flags & MV_HP_ERRATA_XX42A0)
|
||||
writelfl(pp->crqb_dma & 0xffffffff,
|
||||
port_mmio + EDMA_REQ_Q_OUT_PTR_OFS);
|
||||
else
|
||||
writelfl(0, port_mmio + EDMA_REQ_Q_OUT_PTR_OFS);
|
||||
|
||||
writel((pp->crpb_dma >> 16) >> 16, port_mmio + EDMA_RSP_Q_BASE_HI_OFS);
|
||||
|
||||
if (hpriv->hp_flags & MV_HP_ERRATA_XX42A0)
|
||||
writelfl(pp->crpb_dma & 0xffffffff,
|
||||
port_mmio + EDMA_RSP_Q_IN_PTR_OFS);
|
||||
else
|
||||
writelfl(0, port_mmio + EDMA_RSP_Q_IN_PTR_OFS);
|
||||
|
||||
writelfl(pp->crpb_dma & EDMA_RSP_Q_BASE_LO_MASK,
|
||||
port_mmio + EDMA_RSP_Q_OUT_PTR_OFS);
|
||||
|
||||
|
@ -960,21 +1056,19 @@ static void mv_qc_prep(struct ata_queued_cmd *qc)
|
|||
struct ata_taskfile *tf;
|
||||
u16 flags = 0;
|
||||
|
||||
if (ATA_PROT_DMA != qc->tf.protocol) {
|
||||
if (ATA_PROT_DMA != qc->tf.protocol)
|
||||
return;
|
||||
}
|
||||
|
||||
/* the req producer index should be the same as we remember it */
|
||||
assert(((readl(mv_ap_base(qc->ap) + EDMA_REQ_Q_IN_PTR_OFS) >>
|
||||
EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK) ==
|
||||
pp->req_producer);
|
||||
WARN_ON(((readl(mv_ap_base(qc->ap) + EDMA_REQ_Q_IN_PTR_OFS) >>
|
||||
EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK) !=
|
||||
pp->req_producer);
|
||||
|
||||
/* Fill in command request block
|
||||
*/
|
||||
if (!(qc->tf.flags & ATA_TFLAG_WRITE)) {
|
||||
if (!(qc->tf.flags & ATA_TFLAG_WRITE))
|
||||
flags |= CRQB_FLAG_READ;
|
||||
}
|
||||
assert(MV_MAX_Q_DEPTH > qc->tag);
|
||||
WARN_ON(MV_MAX_Q_DEPTH <= qc->tag);
|
||||
flags |= qc->tag << CRQB_TAG_SHIFT;
|
||||
|
||||
pp->crqb[pp->req_producer].sg_addr =
|
||||
|
@ -1029,9 +1123,76 @@ static void mv_qc_prep(struct ata_queued_cmd *qc)
|
|||
mv_crqb_pack_cmd(cw++, tf->device, ATA_REG_DEVICE, 0);
|
||||
mv_crqb_pack_cmd(cw++, tf->command, ATA_REG_CMD, 1); /* last */
|
||||
|
||||
if (!(qc->flags & ATA_QCFLAG_DMAMAP)) {
|
||||
if (!(qc->flags & ATA_QCFLAG_DMAMAP))
|
||||
return;
|
||||
mv_fill_sg(qc);
|
||||
}
|
||||
|
||||
/**
|
||||
* mv_qc_prep_iie - Host specific command preparation.
|
||||
* @qc: queued command to prepare
|
||||
*
|
||||
* This routine simply redirects to the general purpose routine
|
||||
* if command is not DMA. Else, it handles prep of the CRQB
|
||||
* (command request block), does some sanity checking, and calls
|
||||
* the SG load routine.
|
||||
*
|
||||
* LOCKING:
|
||||
* Inherited from caller.
|
||||
*/
|
||||
static void mv_qc_prep_iie(struct ata_queued_cmd *qc)
|
||||
{
|
||||
struct ata_port *ap = qc->ap;
|
||||
struct mv_port_priv *pp = ap->private_data;
|
||||
struct mv_crqb_iie *crqb;
|
||||
struct ata_taskfile *tf;
|
||||
u32 flags = 0;
|
||||
|
||||
if (ATA_PROT_DMA != qc->tf.protocol)
|
||||
return;
|
||||
|
||||
/* the req producer index should be the same as we remember it */
|
||||
WARN_ON(((readl(mv_ap_base(qc->ap) + EDMA_REQ_Q_IN_PTR_OFS) >>
|
||||
EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK) !=
|
||||
pp->req_producer);
|
||||
|
||||
/* Fill in Gen IIE command request block
|
||||
*/
|
||||
if (!(qc->tf.flags & ATA_TFLAG_WRITE))
|
||||
flags |= CRQB_FLAG_READ;
|
||||
|
||||
WARN_ON(MV_MAX_Q_DEPTH <= qc->tag);
|
||||
flags |= qc->tag << CRQB_TAG_SHIFT;
|
||||
|
||||
crqb = (struct mv_crqb_iie *) &pp->crqb[pp->req_producer];
|
||||
crqb->addr = cpu_to_le32(pp->sg_tbl_dma & 0xffffffff);
|
||||
crqb->addr_hi = cpu_to_le32((pp->sg_tbl_dma >> 16) >> 16);
|
||||
crqb->flags = cpu_to_le32(flags);
|
||||
|
||||
tf = &qc->tf;
|
||||
crqb->ata_cmd[0] = cpu_to_le32(
|
||||
(tf->command << 16) |
|
||||
(tf->feature << 24)
|
||||
);
|
||||
crqb->ata_cmd[1] = cpu_to_le32(
|
||||
(tf->lbal << 0) |
|
||||
(tf->lbam << 8) |
|
||||
(tf->lbah << 16) |
|
||||
(tf->device << 24)
|
||||
);
|
||||
crqb->ata_cmd[2] = cpu_to_le32(
|
||||
(tf->hob_lbal << 0) |
|
||||
(tf->hob_lbam << 8) |
|
||||
(tf->hob_lbah << 16) |
|
||||
(tf->hob_feature << 24)
|
||||
);
|
||||
crqb->ata_cmd[3] = cpu_to_le32(
|
||||
(tf->nsect << 0) |
|
||||
(tf->hob_nsect << 8)
|
||||
);
|
||||
|
||||
if (!(qc->flags & ATA_QCFLAG_DMAMAP))
|
||||
return;
|
||||
}
|
||||
mv_fill_sg(qc);
|
||||
}
|
||||
|
||||
|
@ -1047,7 +1208,7 @@ static void mv_qc_prep(struct ata_queued_cmd *qc)
|
|||
* LOCKING:
|
||||
* Inherited from caller.
|
||||
*/
|
||||
static int mv_qc_issue(struct ata_queued_cmd *qc)
|
||||
static unsigned int mv_qc_issue(struct ata_queued_cmd *qc)
|
||||
{
|
||||
void __iomem *port_mmio = mv_ap_base(qc->ap);
|
||||
struct mv_port_priv *pp = qc->ap->private_data;
|
||||
|
@ -1065,12 +1226,12 @@ static int mv_qc_issue(struct ata_queued_cmd *qc)
|
|||
in_ptr = readl(port_mmio + EDMA_REQ_Q_IN_PTR_OFS);
|
||||
|
||||
/* the req producer index should be the same as we remember it */
|
||||
assert(((in_ptr >> EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK) ==
|
||||
pp->req_producer);
|
||||
WARN_ON(((in_ptr >> EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK) !=
|
||||
pp->req_producer);
|
||||
/* until we do queuing, the queue should be empty at this point */
|
||||
assert(((in_ptr >> EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK) ==
|
||||
((readl(port_mmio + EDMA_REQ_Q_OUT_PTR_OFS) >>
|
||||
EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK));
|
||||
WARN_ON(((in_ptr >> EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK) !=
|
||||
((readl(port_mmio + EDMA_REQ_Q_OUT_PTR_OFS) >>
|
||||
EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK));
|
||||
|
||||
mv_inc_q_index(&pp->req_producer); /* now incr producer index */
|
||||
|
||||
|
@ -1090,7 +1251,7 @@ static int mv_qc_issue(struct ata_queued_cmd *qc)
|
|||
*
|
||||
* This routine is for use when the port is in DMA mode, when it
|
||||
* will be using the CRPB (command response block) method of
|
||||
* returning command completion information. We assert indices
|
||||
* returning command completion information. We check indices
|
||||
* are good, grab status, and bump the response consumer index to
|
||||
* prove that we're up to date.
|
||||
*
|
||||
|
@ -1106,16 +1267,16 @@ static u8 mv_get_crpb_status(struct ata_port *ap)
|
|||
out_ptr = readl(port_mmio + EDMA_RSP_Q_OUT_PTR_OFS);
|
||||
|
||||
/* the response consumer index should be the same as we remember it */
|
||||
assert(((out_ptr >> EDMA_RSP_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK) ==
|
||||
pp->rsp_consumer);
|
||||
WARN_ON(((out_ptr >> EDMA_RSP_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK) !=
|
||||
pp->rsp_consumer);
|
||||
|
||||
/* increment our consumer index... */
|
||||
pp->rsp_consumer = mv_inc_q_index(&pp->rsp_consumer);
|
||||
|
||||
/* and, until we do NCQ, there should only be 1 CRPB waiting */
|
||||
assert(((readl(port_mmio + EDMA_RSP_Q_IN_PTR_OFS) >>
|
||||
EDMA_RSP_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK) ==
|
||||
pp->rsp_consumer);
|
||||
WARN_ON(((readl(port_mmio + EDMA_RSP_Q_IN_PTR_OFS) >>
|
||||
EDMA_RSP_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK) !=
|
||||
pp->rsp_consumer);
|
||||
|
||||
/* write out our inc'd consumer index so EDMA knows we're caught up */
|
||||
out_ptr &= EDMA_RSP_Q_BASE_LO_MASK;
|
||||
|
@ -1192,7 +1353,6 @@ static void mv_host_intr(struct ata_host_set *host_set, u32 relevant,
|
|||
u32 hc_irq_cause;
|
||||
int shift, port, port0, hard_port, handled;
|
||||
unsigned int err_mask;
|
||||
u8 ata_status = 0;
|
||||
|
||||
if (hc == 0) {
|
||||
port0 = 0;
|
||||
|
@ -1210,6 +1370,7 @@ static void mv_host_intr(struct ata_host_set *host_set, u32 relevant,
|
|||
hc,relevant,hc_irq_cause);
|
||||
|
||||
for (port = port0; port < port0 + MV_PORTS_PER_HC; port++) {
|
||||
u8 ata_status = 0;
|
||||
ap = host_set->ports[port];
|
||||
hard_port = port & MV_PORT_MASK; /* range 0-3 */
|
||||
handled = 0; /* ensure ata_status is set if handled++ */
|
||||
|
@ -1681,6 +1842,12 @@ static void mv6_phy_errata(struct mv_host_priv *hpriv, void __iomem *mmio,
|
|||
m2 |= hpriv->signal[port].pre;
|
||||
m2 &= ~(1 << 16);
|
||||
|
||||
/* according to mvSata 3.6.1, some IIE values are fixed */
|
||||
if (IS_GEN_IIE(hpriv)) {
|
||||
m2 &= ~0xC30FF01F;
|
||||
m2 |= 0x0000900F;
|
||||
}
|
||||
|
||||
writel(m2, port_mmio + PHY_MODE2);
|
||||
}
|
||||
|
||||
|
@ -1846,7 +2013,6 @@ static void mv_phy_reset(struct ata_port *ap)
|
|||
static void mv_eng_timeout(struct ata_port *ap)
|
||||
{
|
||||
struct ata_queued_cmd *qc;
|
||||
unsigned long flags;
|
||||
|
||||
printk(KERN_ERR "ata%u: Entering mv_eng_timeout\n",ap->id);
|
||||
DPRINTK("All regs @ start of eng_timeout\n");
|
||||
|
@ -1861,22 +2027,8 @@ static void mv_eng_timeout(struct ata_port *ap)
|
|||
mv_err_intr(ap);
|
||||
mv_stop_and_reset(ap);
|
||||
|
||||
if (!qc) {
|
||||
printk(KERN_ERR "ata%u: BUG: timeout without command\n",
|
||||
ap->id);
|
||||
} else {
|
||||
/* hack alert! We cannot use the supplied completion
|
||||
* function from inside the ->eh_strategy_handler() thread.
|
||||
* libata is the only user of ->eh_strategy_handler() in
|
||||
* any kernel, so the default scsi_done() assumes it is
|
||||
* not being called from the SCSI EH.
|
||||
*/
|
||||
spin_lock_irqsave(&ap->host_set->lock, flags);
|
||||
qc->scsidone = scsi_finish_command;
|
||||
qc->err_mask |= AC_ERR_OTHER;
|
||||
ata_qc_complete(qc);
|
||||
spin_unlock_irqrestore(&ap->host_set->lock, flags);
|
||||
}
|
||||
qc->err_mask |= AC_ERR_TIMEOUT;
|
||||
ata_eh_qc_complete(qc);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1995,6 +2147,27 @@ static int mv_chip_id(struct pci_dev *pdev, struct mv_host_priv *hpriv,
|
|||
}
|
||||
break;
|
||||
|
||||
case chip_7042:
|
||||
case chip_6042:
|
||||
hpriv->ops = &mv6xxx_ops;
|
||||
|
||||
hp_flags |= MV_HP_GEN_IIE;
|
||||
|
||||
switch (rev_id) {
|
||||
case 0x0:
|
||||
hp_flags |= MV_HP_ERRATA_XX42A0;
|
||||
break;
|
||||
case 0x1:
|
||||
hp_flags |= MV_HP_ERRATA_60X1C0;
|
||||
break;
|
||||
default:
|
||||
dev_printk(KERN_WARNING, &pdev->dev,
|
||||
"Applying 60X1C0 workarounds to unknown rev\n");
|
||||
hp_flags |= MV_HP_ERRATA_60X1C0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
printk(KERN_ERR DRV_NAME ": BUG: invalid board index %u\n", board_idx);
|
||||
return 1;
|
||||
|
|
|
@ -229,11 +229,11 @@ static struct scsi_host_template nv_sht = {
|
|||
.name = DRV_NAME,
|
||||
.ioctl = ata_scsi_ioctl,
|
||||
.queuecommand = ata_scsi_queuecmd,
|
||||
.eh_timed_out = ata_scsi_timed_out,
|
||||
.eh_strategy_handler = ata_scsi_error,
|
||||
.can_queue = ATA_DEF_QUEUE,
|
||||
.this_id = ATA_SHT_THIS_ID,
|
||||
.sg_tablesize = LIBATA_MAX_PRD,
|
||||
.max_sectors = ATA_MAX_SECTORS,
|
||||
.cmd_per_lun = ATA_SHT_CMD_PER_LUN,
|
||||
.emulated = ATA_SHT_EMULATED,
|
||||
.use_clustering = ATA_SHT_USE_CLUSTERING,
|
||||
|
|
|
@ -46,7 +46,7 @@
|
|||
#include "sata_promise.h"
|
||||
|
||||
#define DRV_NAME "sata_promise"
|
||||
#define DRV_VERSION "1.03"
|
||||
#define DRV_VERSION "1.04"
|
||||
|
||||
|
||||
enum {
|
||||
|
@ -58,6 +58,7 @@ enum {
|
|||
PDC_GLOBAL_CTL = 0x48, /* Global control/status (per port) */
|
||||
PDC_CTLSTAT = 0x60, /* IDE control and status (per port) */
|
||||
PDC_SATA_PLUG_CSR = 0x6C, /* SATA Plug control/status reg */
|
||||
PDC2_SATA_PLUG_CSR = 0x60, /* SATAII Plug control/status reg */
|
||||
PDC_SLEW_CTL = 0x470, /* slew rate control reg */
|
||||
|
||||
PDC_ERR_MASK = (1<<19) | (1<<20) | (1<<21) | (1<<22) |
|
||||
|
@ -67,8 +68,10 @@ enum {
|
|||
board_20319 = 1, /* FastTrak S150 TX4 */
|
||||
board_20619 = 2, /* FastTrak TX4000 */
|
||||
board_20771 = 3, /* FastTrak TX2300 */
|
||||
board_2057x = 4, /* SATAII150 Tx2plus */
|
||||
board_40518 = 5, /* SATAII150 Tx4 */
|
||||
|
||||
PDC_HAS_PATA = (1 << 1), /* PDC20375 has PATA */
|
||||
PDC_HAS_PATA = (1 << 1), /* PDC20375/20575 has PATA */
|
||||
|
||||
PDC_RESET = (1 << 11), /* HDMA reset */
|
||||
|
||||
|
@ -82,6 +85,10 @@ struct pdc_port_priv {
|
|||
dma_addr_t pkt_dma;
|
||||
};
|
||||
|
||||
struct pdc_host_priv {
|
||||
int hotplug_offset;
|
||||
};
|
||||
|
||||
static u32 pdc_sata_scr_read (struct ata_port *ap, unsigned int sc_reg);
|
||||
static void pdc_sata_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val);
|
||||
static int pdc_ata_init_one (struct pci_dev *pdev, const struct pci_device_id *ent);
|
||||
|
@ -95,7 +102,8 @@ static void pdc_qc_prep(struct ata_queued_cmd *qc);
|
|||
static void pdc_tf_load_mmio(struct ata_port *ap, const struct ata_taskfile *tf);
|
||||
static void pdc_exec_command_mmio(struct ata_port *ap, const struct ata_taskfile *tf);
|
||||
static void pdc_irq_clear(struct ata_port *ap);
|
||||
static int pdc_qc_issue_prot(struct ata_queued_cmd *qc);
|
||||
static unsigned int pdc_qc_issue_prot(struct ata_queued_cmd *qc);
|
||||
static void pdc_host_stop(struct ata_host_set *host_set);
|
||||
|
||||
|
||||
static struct scsi_host_template pdc_ata_sht = {
|
||||
|
@ -103,11 +111,11 @@ static struct scsi_host_template pdc_ata_sht = {
|
|||
.name = DRV_NAME,
|
||||
.ioctl = ata_scsi_ioctl,
|
||||
.queuecommand = ata_scsi_queuecmd,
|
||||
.eh_timed_out = ata_scsi_timed_out,
|
||||
.eh_strategy_handler = ata_scsi_error,
|
||||
.can_queue = ATA_DEF_QUEUE,
|
||||
.this_id = ATA_SHT_THIS_ID,
|
||||
.sg_tablesize = LIBATA_MAX_PRD,
|
||||
.max_sectors = ATA_MAX_SECTORS,
|
||||
.cmd_per_lun = ATA_SHT_CMD_PER_LUN,
|
||||
.emulated = ATA_SHT_EMULATED,
|
||||
.use_clustering = ATA_SHT_USE_CLUSTERING,
|
||||
|
@ -137,7 +145,7 @@ static const struct ata_port_operations pdc_sata_ops = {
|
|||
.scr_write = pdc_sata_scr_write,
|
||||
.port_start = pdc_port_start,
|
||||
.port_stop = pdc_port_stop,
|
||||
.host_stop = ata_pci_host_stop,
|
||||
.host_stop = pdc_host_stop,
|
||||
};
|
||||
|
||||
static const struct ata_port_operations pdc_pata_ops = {
|
||||
|
@ -158,7 +166,7 @@ static const struct ata_port_operations pdc_pata_ops = {
|
|||
|
||||
.port_start = pdc_port_start,
|
||||
.port_stop = pdc_port_stop,
|
||||
.host_stop = ata_pci_host_stop,
|
||||
.host_stop = pdc_host_stop,
|
||||
};
|
||||
|
||||
static const struct ata_port_info pdc_port_info[] = {
|
||||
|
@ -201,6 +209,26 @@ static const struct ata_port_info pdc_port_info[] = {
|
|||
.udma_mask = 0x7f, /* udma0-6 ; FIXME */
|
||||
.port_ops = &pdc_sata_ops,
|
||||
},
|
||||
|
||||
/* board_2057x */
|
||||
{
|
||||
.sht = &pdc_ata_sht,
|
||||
.host_flags = PDC_COMMON_FLAGS | ATA_FLAG_SATA,
|
||||
.pio_mask = 0x1f, /* pio0-4 */
|
||||
.mwdma_mask = 0x07, /* mwdma0-2 */
|
||||
.udma_mask = 0x7f, /* udma0-6 ; FIXME */
|
||||
.port_ops = &pdc_sata_ops,
|
||||
},
|
||||
|
||||
/* board_40518 */
|
||||
{
|
||||
.sht = &pdc_ata_sht,
|
||||
.host_flags = PDC_COMMON_FLAGS | ATA_FLAG_SATA,
|
||||
.pio_mask = 0x1f, /* pio0-4 */
|
||||
.mwdma_mask = 0x07, /* mwdma0-2 */
|
||||
.udma_mask = 0x7f, /* udma0-6 ; FIXME */
|
||||
.port_ops = &pdc_sata_ops,
|
||||
},
|
||||
};
|
||||
|
||||
static const struct pci_device_id pdc_ata_pci_tbl[] = {
|
||||
|
@ -217,9 +245,9 @@ static const struct pci_device_id pdc_ata_pci_tbl[] = {
|
|||
{ PCI_VENDOR_ID_PROMISE, 0x3376, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
||||
board_2037x },
|
||||
{ PCI_VENDOR_ID_PROMISE, 0x3574, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
||||
board_2037x },
|
||||
board_2057x },
|
||||
{ PCI_VENDOR_ID_PROMISE, 0x3d75, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
||||
board_2037x },
|
||||
board_2057x },
|
||||
{ PCI_VENDOR_ID_PROMISE, 0x3d73, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
||||
board_2037x },
|
||||
|
||||
|
@ -227,12 +255,14 @@ static const struct pci_device_id pdc_ata_pci_tbl[] = {
|
|||
board_20319 },
|
||||
{ PCI_VENDOR_ID_PROMISE, 0x3319, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
||||
board_20319 },
|
||||
{ PCI_VENDOR_ID_PROMISE, 0x3515, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
||||
board_20319 },
|
||||
{ PCI_VENDOR_ID_PROMISE, 0x3519, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
||||
board_20319 },
|
||||
{ PCI_VENDOR_ID_PROMISE, 0x3d17, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
||||
board_20319 },
|
||||
{ PCI_VENDOR_ID_PROMISE, 0x3d18, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
||||
board_20319 },
|
||||
board_40518 },
|
||||
|
||||
{ PCI_VENDOR_ID_PROMISE, 0x6629, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
||||
board_20619 },
|
||||
|
@ -261,12 +291,11 @@ static int pdc_port_start(struct ata_port *ap)
|
|||
if (rc)
|
||||
return rc;
|
||||
|
||||
pp = kmalloc(sizeof(*pp), GFP_KERNEL);
|
||||
pp = kzalloc(sizeof(*pp), GFP_KERNEL);
|
||||
if (!pp) {
|
||||
rc = -ENOMEM;
|
||||
goto err_out;
|
||||
}
|
||||
memset(pp, 0, sizeof(*pp));
|
||||
|
||||
pp->pkt = dma_alloc_coherent(dev, 128, &pp->pkt_dma, GFP_KERNEL);
|
||||
if (!pp->pkt) {
|
||||
|
@ -298,6 +327,16 @@ static void pdc_port_stop(struct ata_port *ap)
|
|||
}
|
||||
|
||||
|
||||
static void pdc_host_stop(struct ata_host_set *host_set)
|
||||
{
|
||||
struct pdc_host_priv *hp = host_set->private_data;
|
||||
|
||||
ata_pci_host_stop(host_set);
|
||||
|
||||
kfree(hp);
|
||||
}
|
||||
|
||||
|
||||
static void pdc_reset_port(struct ata_port *ap)
|
||||
{
|
||||
void __iomem *mmio = (void __iomem *) ap->ioaddr.cmd_addr + PDC_CTLSTAT;
|
||||
|
@ -394,19 +433,6 @@ static void pdc_eng_timeout(struct ata_port *ap)
|
|||
spin_lock_irqsave(&host_set->lock, flags);
|
||||
|
||||
qc = ata_qc_from_tag(ap, ap->active_tag);
|
||||
if (!qc) {
|
||||
printk(KERN_ERR "ata%u: BUG: timeout without command\n",
|
||||
ap->id);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* hack alert! We cannot use the supplied completion
|
||||
* function from inside the ->eh_strategy_handler() thread.
|
||||
* libata is the only user of ->eh_strategy_handler() in
|
||||
* any kernel, so the default scsi_done() assumes it is
|
||||
* not being called from the SCSI EH.
|
||||
*/
|
||||
qc->scsidone = scsi_finish_command;
|
||||
|
||||
switch (qc->tf.protocol) {
|
||||
case ATA_PROT_DMA:
|
||||
|
@ -414,7 +440,6 @@ static void pdc_eng_timeout(struct ata_port *ap)
|
|||
printk(KERN_ERR "ata%u: command timeout\n", ap->id);
|
||||
drv_stat = ata_wait_idle(ap);
|
||||
qc->err_mask |= __ac_err_mask(drv_stat);
|
||||
ata_qc_complete(qc);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -424,12 +449,11 @@ static void pdc_eng_timeout(struct ata_port *ap)
|
|||
ap->id, qc->tf.command, drv_stat);
|
||||
|
||||
qc->err_mask |= ac_err_mask(drv_stat);
|
||||
ata_qc_complete(qc);
|
||||
break;
|
||||
}
|
||||
|
||||
out:
|
||||
spin_unlock_irqrestore(&host_set->lock, flags);
|
||||
ata_eh_qc_complete(qc);
|
||||
DPRINTK("EXIT\n");
|
||||
}
|
||||
|
||||
|
@ -495,14 +519,15 @@ static irqreturn_t pdc_interrupt (int irq, void *dev_instance, struct pt_regs *r
|
|||
VPRINTK("QUICK EXIT 2\n");
|
||||
return IRQ_NONE;
|
||||
}
|
||||
|
||||
spin_lock(&host_set->lock);
|
||||
|
||||
mask &= 0xffff; /* only 16 tags possible */
|
||||
if (!mask) {
|
||||
VPRINTK("QUICK EXIT 3\n");
|
||||
return IRQ_NONE;
|
||||
goto done_irq;
|
||||
}
|
||||
|
||||
spin_lock(&host_set->lock);
|
||||
|
||||
writel(mask, mmio_base + PDC_INT_SEQMASK);
|
||||
|
||||
for (i = 0; i < host_set->n_ports; i++) {
|
||||
|
@ -519,10 +544,10 @@ static irqreturn_t pdc_interrupt (int irq, void *dev_instance, struct pt_regs *r
|
|||
}
|
||||
}
|
||||
|
||||
spin_unlock(&host_set->lock);
|
||||
|
||||
VPRINTK("EXIT\n");
|
||||
|
||||
done_irq:
|
||||
spin_unlock(&host_set->lock);
|
||||
return IRQ_RETVAL(handled);
|
||||
}
|
||||
|
||||
|
@ -544,7 +569,7 @@ static inline void pdc_packet_start(struct ata_queued_cmd *qc)
|
|||
readl((void __iomem *) ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT); /* flush */
|
||||
}
|
||||
|
||||
static 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) {
|
||||
case ATA_PROT_DMA:
|
||||
|
@ -600,6 +625,8 @@ static void pdc_ata_setup_port(struct ata_ioports *port, unsigned long base)
|
|||
static void pdc_host_init(unsigned int chip_id, struct ata_probe_ent *pe)
|
||||
{
|
||||
void __iomem *mmio = pe->mmio_base;
|
||||
struct pdc_host_priv *hp = pe->private_data;
|
||||
int hotplug_offset = hp->hotplug_offset;
|
||||
u32 tmp;
|
||||
|
||||
/*
|
||||
|
@ -614,12 +641,12 @@ static void pdc_host_init(unsigned int chip_id, struct ata_probe_ent *pe)
|
|||
writel(tmp, mmio + PDC_FLASH_CTL);
|
||||
|
||||
/* clear plug/unplug flags for all ports */
|
||||
tmp = readl(mmio + PDC_SATA_PLUG_CSR);
|
||||
writel(tmp | 0xff, mmio + PDC_SATA_PLUG_CSR);
|
||||
tmp = readl(mmio + hotplug_offset);
|
||||
writel(tmp | 0xff, mmio + hotplug_offset);
|
||||
|
||||
/* mask plug/unplug ints */
|
||||
tmp = readl(mmio + PDC_SATA_PLUG_CSR);
|
||||
writel(tmp | 0xff0000, mmio + PDC_SATA_PLUG_CSR);
|
||||
tmp = readl(mmio + hotplug_offset);
|
||||
writel(tmp | 0xff0000, mmio + hotplug_offset);
|
||||
|
||||
/* reduce TBG clock to 133 Mhz. */
|
||||
tmp = readl(mmio + PDC_TBG_MODE);
|
||||
|
@ -641,6 +668,7 @@ static int pdc_ata_init_one (struct pci_dev *pdev, const struct pci_device_id *e
|
|||
{
|
||||
static int printed_version;
|
||||
struct ata_probe_ent *probe_ent = NULL;
|
||||
struct pdc_host_priv *hp;
|
||||
unsigned long base;
|
||||
void __iomem *mmio_base;
|
||||
unsigned int board_idx = (unsigned int) ent->driver_data;
|
||||
|
@ -671,13 +699,12 @@ static int pdc_ata_init_one (struct pci_dev *pdev, const struct pci_device_id *e
|
|||
if (rc)
|
||||
goto err_out_regions;
|
||||
|
||||
probe_ent = kmalloc(sizeof(*probe_ent), GFP_KERNEL);
|
||||
probe_ent = kzalloc(sizeof(*probe_ent), GFP_KERNEL);
|
||||
if (probe_ent == NULL) {
|
||||
rc = -ENOMEM;
|
||||
goto err_out_regions;
|
||||
}
|
||||
|
||||
memset(probe_ent, 0, sizeof(*probe_ent));
|
||||
probe_ent->dev = pci_dev_to_dev(pdev);
|
||||
INIT_LIST_HEAD(&probe_ent->node);
|
||||
|
||||
|
@ -688,6 +715,16 @@ static int pdc_ata_init_one (struct pci_dev *pdev, const struct pci_device_id *e
|
|||
}
|
||||
base = (unsigned long) mmio_base;
|
||||
|
||||
hp = kzalloc(sizeof(*hp), GFP_KERNEL);
|
||||
if (hp == NULL) {
|
||||
rc = -ENOMEM;
|
||||
goto err_out_free_ent;
|
||||
}
|
||||
|
||||
/* Set default hotplug offset */
|
||||
hp->hotplug_offset = PDC_SATA_PLUG_CSR;
|
||||
probe_ent->private_data = hp;
|
||||
|
||||
probe_ent->sht = pdc_port_info[board_idx].sht;
|
||||
probe_ent->host_flags = pdc_port_info[board_idx].host_flags;
|
||||
probe_ent->pio_mask = pdc_port_info[board_idx].pio_mask;
|
||||
|
@ -707,6 +744,10 @@ static int pdc_ata_init_one (struct pci_dev *pdev, const struct pci_device_id *e
|
|||
|
||||
/* notice 4-port boards */
|
||||
switch (board_idx) {
|
||||
case board_40518:
|
||||
/* Override hotplug offset for SATAII150 */
|
||||
hp->hotplug_offset = PDC2_SATA_PLUG_CSR;
|
||||
/* Fall through */
|
||||
case board_20319:
|
||||
probe_ent->n_ports = 4;
|
||||
|
||||
|
@ -716,6 +757,10 @@ static int pdc_ata_init_one (struct pci_dev *pdev, const struct pci_device_id *e
|
|||
probe_ent->port[2].scr_addr = base + 0x600;
|
||||
probe_ent->port[3].scr_addr = base + 0x700;
|
||||
break;
|
||||
case board_2057x:
|
||||
/* Override hotplug offset for SATAII150 */
|
||||
hp->hotplug_offset = PDC2_SATA_PLUG_CSR;
|
||||
/* Fall through */
|
||||
case board_2037x:
|
||||
probe_ent->n_ports = 2;
|
||||
break;
|
||||
|
@ -741,8 +786,10 @@ static int pdc_ata_init_one (struct pci_dev *pdev, const struct pci_device_id *e
|
|||
/* initialize adapter */
|
||||
pdc_host_init(board_idx, probe_ent);
|
||||
|
||||
/* FIXME: check ata_device_add return value */
|
||||
ata_device_add(probe_ent);
|
||||
/* FIXME: Need any other frees than hp? */
|
||||
if (!ata_device_add(probe_ent))
|
||||
kfree(hp);
|
||||
|
||||
kfree(probe_ent);
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -120,7 +120,7 @@ static void qs_host_stop(struct ata_host_set *host_set);
|
|||
static void qs_port_stop(struct ata_port *ap);
|
||||
static void qs_phy_reset(struct ata_port *ap);
|
||||
static void qs_qc_prep(struct ata_queued_cmd *qc);
|
||||
static int qs_qc_issue(struct ata_queued_cmd *qc);
|
||||
static unsigned int qs_qc_issue(struct ata_queued_cmd *qc);
|
||||
static int qs_check_atapi_dma(struct ata_queued_cmd *qc);
|
||||
static void qs_bmdma_stop(struct ata_queued_cmd *qc);
|
||||
static u8 qs_bmdma_status(struct ata_port *ap);
|
||||
|
@ -132,11 +132,11 @@ static struct scsi_host_template qs_ata_sht = {
|
|||
.name = DRV_NAME,
|
||||
.ioctl = ata_scsi_ioctl,
|
||||
.queuecommand = ata_scsi_queuecmd,
|
||||
.eh_timed_out = ata_scsi_timed_out,
|
||||
.eh_strategy_handler = ata_scsi_error,
|
||||
.can_queue = ATA_DEF_QUEUE,
|
||||
.this_id = ATA_SHT_THIS_ID,
|
||||
.sg_tablesize = QS_MAX_PRD,
|
||||
.max_sectors = ATA_MAX_SECTORS,
|
||||
.cmd_per_lun = ATA_SHT_CMD_PER_LUN,
|
||||
.emulated = ATA_SHT_EMULATED,
|
||||
//FIXME .use_clustering = ATA_SHT_USE_CLUSTERING,
|
||||
|
@ -276,8 +276,8 @@ static unsigned int qs_fill_sg(struct ata_queued_cmd *qc)
|
|||
unsigned int nelem;
|
||||
u8 *prd = pp->pkt + QS_CPB_BYTES;
|
||||
|
||||
assert(qc->__sg != NULL);
|
||||
assert(qc->n_elem > 0 || qc->pad_len > 0);
|
||||
WARN_ON(qc->__sg == NULL);
|
||||
WARN_ON(qc->n_elem == 0 && qc->pad_len == 0);
|
||||
|
||||
nelem = 0;
|
||||
ata_for_each_sg(sg, qc) {
|
||||
|
@ -352,7 +352,7 @@ static inline void qs_packet_start(struct ata_queued_cmd *qc)
|
|||
readl(chan + QS_CCT_CFF); /* flush */
|
||||
}
|
||||
|
||||
static int qs_qc_issue(struct ata_queued_cmd *qc)
|
||||
static unsigned int qs_qc_issue(struct ata_queued_cmd *qc)
|
||||
{
|
||||
struct qs_port_priv *pp = qc->ap->private_data;
|
||||
|
||||
|
|
|
@ -49,24 +49,30 @@
|
|||
#define DRV_VERSION "0.9"
|
||||
|
||||
enum {
|
||||
/*
|
||||
* host flags
|
||||
*/
|
||||
SIL_FLAG_RERR_ON_DMA_ACT = (1 << 29),
|
||||
SIL_FLAG_MOD15WRITE = (1 << 30),
|
||||
SIL_DFL_HOST_FLAGS = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
|
||||
ATA_FLAG_MMIO,
|
||||
|
||||
/*
|
||||
* Controller IDs
|
||||
*/
|
||||
sil_3112 = 0,
|
||||
sil_3112_m15w = 1,
|
||||
sil_3512 = 2,
|
||||
sil_3114 = 3,
|
||||
|
||||
SIL_FIFO_R0 = 0x40,
|
||||
SIL_FIFO_W0 = 0x41,
|
||||
SIL_FIFO_R1 = 0x44,
|
||||
SIL_FIFO_W1 = 0x45,
|
||||
SIL_FIFO_R2 = 0x240,
|
||||
SIL_FIFO_W2 = 0x241,
|
||||
SIL_FIFO_R3 = 0x244,
|
||||
SIL_FIFO_W3 = 0x245,
|
||||
sil_3512 = 1,
|
||||
sil_3114 = 2,
|
||||
|
||||
/*
|
||||
* Register offsets
|
||||
*/
|
||||
SIL_SYSCFG = 0x48,
|
||||
|
||||
/*
|
||||
* Register bits
|
||||
*/
|
||||
/* SYSCFG */
|
||||
SIL_MASK_IDE0_INT = (1 << 22),
|
||||
SIL_MASK_IDE1_INT = (1 << 23),
|
||||
SIL_MASK_IDE2_INT = (1 << 24),
|
||||
|
@ -75,9 +81,12 @@ enum {
|
|||
SIL_MASK_4PORT = SIL_MASK_2PORT |
|
||||
SIL_MASK_IDE2_INT | SIL_MASK_IDE3_INT,
|
||||
|
||||
SIL_IDE2_BMDMA = 0x200,
|
||||
|
||||
/* BMDMA/BMDMA2 */
|
||||
SIL_INTR_STEERING = (1 << 1),
|
||||
|
||||
/*
|
||||
* Others
|
||||
*/
|
||||
SIL_QUIRK_MOD15WRITE = (1 << 0),
|
||||
SIL_QUIRK_UDMA5MAX = (1 << 1),
|
||||
};
|
||||
|
@ -90,13 +99,13 @@ static void sil_post_set_mode (struct ata_port *ap);
|
|||
|
||||
|
||||
static const struct pci_device_id sil_pci_tbl[] = {
|
||||
{ 0x1095, 0x3112, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112_m15w },
|
||||
{ 0x1095, 0x0240, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112_m15w },
|
||||
{ 0x1095, 0x3112, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112 },
|
||||
{ 0x1095, 0x0240, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112 },
|
||||
{ 0x1095, 0x3512, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3512 },
|
||||
{ 0x1095, 0x3114, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3114 },
|
||||
{ 0x1002, 0x436e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112_m15w },
|
||||
{ 0x1002, 0x4379, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112_m15w },
|
||||
{ 0x1002, 0x437a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112_m15w },
|
||||
{ 0x1002, 0x436e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112 },
|
||||
{ 0x1002, 0x4379, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112 },
|
||||
{ 0x1002, 0x437a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112 },
|
||||
{ } /* terminate list */
|
||||
};
|
||||
|
||||
|
@ -137,11 +146,11 @@ static struct scsi_host_template sil_sht = {
|
|||
.name = DRV_NAME,
|
||||
.ioctl = ata_scsi_ioctl,
|
||||
.queuecommand = ata_scsi_queuecmd,
|
||||
.eh_timed_out = ata_scsi_timed_out,
|
||||
.eh_strategy_handler = ata_scsi_error,
|
||||
.can_queue = ATA_DEF_QUEUE,
|
||||
.this_id = ATA_SHT_THIS_ID,
|
||||
.sg_tablesize = LIBATA_MAX_PRD,
|
||||
.max_sectors = ATA_MAX_SECTORS,
|
||||
.cmd_per_lun = ATA_SHT_CMD_PER_LUN,
|
||||
.emulated = ATA_SHT_EMULATED,
|
||||
.use_clustering = ATA_SHT_USE_CLUSTERING,
|
||||
|
@ -159,7 +168,7 @@ static const struct ata_port_operations sil_ops = {
|
|||
.check_status = ata_check_status,
|
||||
.exec_command = ata_exec_command,
|
||||
.dev_select = ata_std_dev_select,
|
||||
.phy_reset = sata_phy_reset,
|
||||
.probe_reset = ata_std_probe_reset,
|
||||
.post_set_mode = sil_post_set_mode,
|
||||
.bmdma_setup = ata_bmdma_setup,
|
||||
.bmdma_start = ata_bmdma_start,
|
||||
|
@ -181,19 +190,7 @@ static const struct ata_port_info sil_port_info[] = {
|
|||
/* sil_3112 */
|
||||
{
|
||||
.sht = &sil_sht,
|
||||
.host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
|
||||
ATA_FLAG_SRST | ATA_FLAG_MMIO,
|
||||
.pio_mask = 0x1f, /* pio0-4 */
|
||||
.mwdma_mask = 0x07, /* mwdma0-2 */
|
||||
.udma_mask = 0x3f, /* udma0-5 */
|
||||
.port_ops = &sil_ops,
|
||||
},
|
||||
/* sil_3112_15w - keep it sync'd w/ sil_3112 */
|
||||
{
|
||||
.sht = &sil_sht,
|
||||
.host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
|
||||
ATA_FLAG_SRST | ATA_FLAG_MMIO |
|
||||
SIL_FLAG_MOD15WRITE,
|
||||
.host_flags = SIL_DFL_HOST_FLAGS | SIL_FLAG_MOD15WRITE,
|
||||
.pio_mask = 0x1f, /* pio0-4 */
|
||||
.mwdma_mask = 0x07, /* mwdma0-2 */
|
||||
.udma_mask = 0x3f, /* udma0-5 */
|
||||
|
@ -202,9 +199,7 @@ static const struct ata_port_info sil_port_info[] = {
|
|||
/* sil_3512 */
|
||||
{
|
||||
.sht = &sil_sht,
|
||||
.host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
|
||||
ATA_FLAG_SRST | ATA_FLAG_MMIO |
|
||||
SIL_FLAG_RERR_ON_DMA_ACT,
|
||||
.host_flags = SIL_DFL_HOST_FLAGS | SIL_FLAG_RERR_ON_DMA_ACT,
|
||||
.pio_mask = 0x1f, /* pio0-4 */
|
||||
.mwdma_mask = 0x07, /* mwdma0-2 */
|
||||
.udma_mask = 0x3f, /* udma0-5 */
|
||||
|
@ -213,9 +208,7 @@ static const struct ata_port_info sil_port_info[] = {
|
|||
/* sil_3114 */
|
||||
{
|
||||
.sht = &sil_sht,
|
||||
.host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
|
||||
ATA_FLAG_SRST | ATA_FLAG_MMIO |
|
||||
SIL_FLAG_RERR_ON_DMA_ACT,
|
||||
.host_flags = SIL_DFL_HOST_FLAGS | SIL_FLAG_RERR_ON_DMA_ACT,
|
||||
.pio_mask = 0x1f, /* pio0-4 */
|
||||
.mwdma_mask = 0x07, /* mwdma0-2 */
|
||||
.udma_mask = 0x3f, /* udma0-5 */
|
||||
|
@ -229,16 +222,17 @@ static const struct {
|
|||
unsigned long tf; /* ATA taskfile register block */
|
||||
unsigned long ctl; /* ATA control/altstatus register block */
|
||||
unsigned long bmdma; /* DMA register block */
|
||||
unsigned long fifo_cfg; /* FIFO Valid Byte Count and Control */
|
||||
unsigned long scr; /* SATA control register block */
|
||||
unsigned long sien; /* SATA Interrupt Enable register */
|
||||
unsigned long xfer_mode;/* data transfer mode register */
|
||||
unsigned long sfis_cfg; /* SATA FIS reception config register */
|
||||
} sil_port[] = {
|
||||
/* port 0 ... */
|
||||
{ 0x80, 0x8A, 0x00, 0x100, 0x148, 0xb4, 0x14c },
|
||||
{ 0xC0, 0xCA, 0x08, 0x180, 0x1c8, 0xf4, 0x1cc },
|
||||
{ 0x280, 0x28A, 0x200, 0x300, 0x348, 0x2b4, 0x34c },
|
||||
{ 0x2C0, 0x2CA, 0x208, 0x380, 0x3c8, 0x2f4, 0x3cc },
|
||||
{ 0x80, 0x8A, 0x00, 0x40, 0x100, 0x148, 0xb4, 0x14c },
|
||||
{ 0xC0, 0xCA, 0x08, 0x44, 0x180, 0x1c8, 0xf4, 0x1cc },
|
||||
{ 0x280, 0x28A, 0x200, 0x240, 0x300, 0x348, 0x2b4, 0x34c },
|
||||
{ 0x2C0, 0x2CA, 0x208, 0x244, 0x380, 0x3c8, 0x2f4, 0x3cc },
|
||||
/* ... port 3 */
|
||||
};
|
||||
|
||||
|
@ -354,22 +348,12 @@ static void sil_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val)
|
|||
static void sil_dev_config(struct ata_port *ap, struct ata_device *dev)
|
||||
{
|
||||
unsigned int n, quirks = 0;
|
||||
unsigned char model_num[40];
|
||||
const char *s;
|
||||
unsigned int len;
|
||||
unsigned char model_num[41];
|
||||
|
||||
ata_dev_id_string(dev->id, model_num, ATA_ID_PROD_OFS,
|
||||
sizeof(model_num));
|
||||
s = &model_num[0];
|
||||
len = strnlen(s, sizeof(model_num));
|
||||
|
||||
/* ATAPI specifies that empty space is blank-filled; remove blanks */
|
||||
while ((len > 0) && (s[len - 1] == ' '))
|
||||
len--;
|
||||
ata_id_c_string(dev->id, model_num, ATA_ID_PROD_OFS, sizeof(model_num));
|
||||
|
||||
for (n = 0; sil_blacklist[n].product; n++)
|
||||
if (!memcmp(sil_blacklist[n].product, s,
|
||||
strlen(sil_blacklist[n].product))) {
|
||||
if (!strcmp(sil_blacklist[n].product, model_num)) {
|
||||
quirks = sil_blacklist[n].quirk;
|
||||
break;
|
||||
}
|
||||
|
@ -380,16 +364,14 @@ static void sil_dev_config(struct ata_port *ap, struct ata_device *dev)
|
|||
(quirks & SIL_QUIRK_MOD15WRITE))) {
|
||||
printk(KERN_INFO "ata%u(%u): applying Seagate errata fix (mod15write workaround)\n",
|
||||
ap->id, dev->devno);
|
||||
ap->host->max_sectors = 15;
|
||||
ap->host->hostt->max_sectors = 15;
|
||||
dev->flags |= ATA_DFLAG_LOCK_SECTORS;
|
||||
dev->max_sectors = 15;
|
||||
return;
|
||||
}
|
||||
|
||||
/* limit to udma5 */
|
||||
if (quirks & SIL_QUIRK_UDMA5MAX) {
|
||||
printk(KERN_INFO "ata%u(%u): applying Maxtor errata fix %s\n",
|
||||
ap->id, dev->devno, s);
|
||||
ap->id, dev->devno, model_num);
|
||||
ap->udma_mask &= ATA_UDMA5;
|
||||
return;
|
||||
}
|
||||
|
@ -431,13 +413,12 @@ static int sil_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
|
|||
if (rc)
|
||||
goto err_out_regions;
|
||||
|
||||
probe_ent = kmalloc(sizeof(*probe_ent), GFP_KERNEL);
|
||||
probe_ent = kzalloc(sizeof(*probe_ent), GFP_KERNEL);
|
||||
if (probe_ent == NULL) {
|
||||
rc = -ENOMEM;
|
||||
goto err_out_regions;
|
||||
}
|
||||
|
||||
memset(probe_ent, 0, sizeof(*probe_ent));
|
||||
INIT_LIST_HEAD(&probe_ent->node);
|
||||
probe_ent->dev = pci_dev_to_dev(pdev);
|
||||
probe_ent->port_ops = sil_port_info[ent->driver_data].port_ops;
|
||||
|
@ -474,19 +455,12 @@ static int sil_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
|
|||
if (cls) {
|
||||
cls >>= 3;
|
||||
cls++; /* cls = (line_size/8)+1 */
|
||||
writeb(cls, mmio_base + SIL_FIFO_R0);
|
||||
writeb(cls, mmio_base + SIL_FIFO_W0);
|
||||
writeb(cls, mmio_base + SIL_FIFO_R1);
|
||||
writeb(cls, mmio_base + SIL_FIFO_W1);
|
||||
if (ent->driver_data == sil_3114) {
|
||||
writeb(cls, mmio_base + SIL_FIFO_R2);
|
||||
writeb(cls, mmio_base + SIL_FIFO_W2);
|
||||
writeb(cls, mmio_base + SIL_FIFO_R3);
|
||||
writeb(cls, mmio_base + SIL_FIFO_W3);
|
||||
}
|
||||
for (i = 0; i < probe_ent->n_ports; i++)
|
||||
writew(cls << 8 | cls,
|
||||
mmio_base + sil_port[i].fifo_cfg);
|
||||
} else
|
||||
dev_printk(KERN_WARNING, &pdev->dev,
|
||||
"cache line size not set. Driver may not function\n");
|
||||
"cache line size not set. Driver may not function\n");
|
||||
|
||||
/* Apply R_ERR on DMA activate FIS errata workaround */
|
||||
if (probe_ent->host_flags & SIL_FLAG_RERR_ON_DMA_ACT) {
|
||||
|
@ -509,10 +483,10 @@ static int sil_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
|
|||
irq_mask = SIL_MASK_4PORT;
|
||||
|
||||
/* flip the magic "make 4 ports work" bit */
|
||||
tmp = readl(mmio_base + SIL_IDE2_BMDMA);
|
||||
tmp = readl(mmio_base + sil_port[2].bmdma);
|
||||
if ((tmp & SIL_INTR_STEERING) == 0)
|
||||
writel(tmp | SIL_INTR_STEERING,
|
||||
mmio_base + SIL_IDE2_BMDMA);
|
||||
mmio_base + sil_port[2].bmdma);
|
||||
|
||||
} else {
|
||||
irq_mask = SIL_MASK_2PORT;
|
||||
|
|
|
@ -249,9 +249,9 @@ static u8 sil24_check_status(struct ata_port *ap);
|
|||
static u32 sil24_scr_read(struct ata_port *ap, unsigned sc_reg);
|
||||
static void sil24_scr_write(struct ata_port *ap, unsigned sc_reg, u32 val);
|
||||
static void sil24_tf_read(struct ata_port *ap, struct ata_taskfile *tf);
|
||||
static void sil24_phy_reset(struct ata_port *ap);
|
||||
static int sil24_probe_reset(struct ata_port *ap, unsigned int *classes);
|
||||
static void sil24_qc_prep(struct ata_queued_cmd *qc);
|
||||
static int sil24_qc_issue(struct ata_queued_cmd *qc);
|
||||
static unsigned int sil24_qc_issue(struct ata_queued_cmd *qc);
|
||||
static void sil24_irq_clear(struct ata_port *ap);
|
||||
static void sil24_eng_timeout(struct ata_port *ap);
|
||||
static irqreturn_t sil24_interrupt(int irq, void *dev_instance, struct pt_regs *regs);
|
||||
|
@ -262,6 +262,7 @@ static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
|
|||
|
||||
static const struct pci_device_id sil24_pci_tbl[] = {
|
||||
{ 0x1095, 0x3124, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BID_SIL3124 },
|
||||
{ 0x8086, 0x3124, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BID_SIL3124 },
|
||||
{ 0x1095, 0x3132, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BID_SIL3132 },
|
||||
{ 0x1095, 0x3131, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BID_SIL3131 },
|
||||
{ 0x1095, 0x3531, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BID_SIL3131 },
|
||||
|
@ -280,11 +281,11 @@ static struct scsi_host_template sil24_sht = {
|
|||
.name = DRV_NAME,
|
||||
.ioctl = ata_scsi_ioctl,
|
||||
.queuecommand = ata_scsi_queuecmd,
|
||||
.eh_timed_out = ata_scsi_timed_out,
|
||||
.eh_strategy_handler = ata_scsi_error,
|
||||
.can_queue = ATA_DEF_QUEUE,
|
||||
.this_id = ATA_SHT_THIS_ID,
|
||||
.sg_tablesize = LIBATA_MAX_PRD,
|
||||
.max_sectors = ATA_MAX_SECTORS,
|
||||
.cmd_per_lun = ATA_SHT_CMD_PER_LUN,
|
||||
.emulated = ATA_SHT_EMULATED,
|
||||
.use_clustering = ATA_SHT_USE_CLUSTERING,
|
||||
|
@ -305,7 +306,7 @@ static const struct ata_port_operations sil24_ops = {
|
|||
|
||||
.tf_read = sil24_tf_read,
|
||||
|
||||
.phy_reset = sil24_phy_reset,
|
||||
.probe_reset = sil24_probe_reset,
|
||||
|
||||
.qc_prep = sil24_qc_prep,
|
||||
.qc_issue = sil24_qc_issue,
|
||||
|
@ -335,8 +336,8 @@ static struct ata_port_info sil24_port_info[] = {
|
|||
{
|
||||
.sht = &sil24_sht,
|
||||
.host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
|
||||
ATA_FLAG_SRST | ATA_FLAG_MMIO |
|
||||
ATA_FLAG_PIO_DMA | SIL24_NPORTS2FLAG(4),
|
||||
ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA |
|
||||
SIL24_NPORTS2FLAG(4),
|
||||
.pio_mask = 0x1f, /* pio0-4 */
|
||||
.mwdma_mask = 0x07, /* mwdma0-2 */
|
||||
.udma_mask = 0x3f, /* udma0-5 */
|
||||
|
@ -346,8 +347,8 @@ static struct ata_port_info sil24_port_info[] = {
|
|||
{
|
||||
.sht = &sil24_sht,
|
||||
.host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
|
||||
ATA_FLAG_SRST | ATA_FLAG_MMIO |
|
||||
ATA_FLAG_PIO_DMA | SIL24_NPORTS2FLAG(2),
|
||||
ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA |
|
||||
SIL24_NPORTS2FLAG(2),
|
||||
.pio_mask = 0x1f, /* pio0-4 */
|
||||
.mwdma_mask = 0x07, /* mwdma0-2 */
|
||||
.udma_mask = 0x3f, /* udma0-5 */
|
||||
|
@ -357,8 +358,8 @@ static struct ata_port_info sil24_port_info[] = {
|
|||
{
|
||||
.sht = &sil24_sht,
|
||||
.host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
|
||||
ATA_FLAG_SRST | ATA_FLAG_MMIO |
|
||||
ATA_FLAG_PIO_DMA | SIL24_NPORTS2FLAG(1),
|
||||
ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA |
|
||||
SIL24_NPORTS2FLAG(1),
|
||||
.pio_mask = 0x1f, /* pio0-4 */
|
||||
.mwdma_mask = 0x07, /* mwdma0-2 */
|
||||
.udma_mask = 0x3f, /* udma0-5 */
|
||||
|
@ -370,7 +371,7 @@ static void sil24_dev_config(struct ata_port *ap, struct ata_device *dev)
|
|||
{
|
||||
void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr;
|
||||
|
||||
if (ap->cdb_len == 16)
|
||||
if (dev->cdb_len == 16)
|
||||
writel(PORT_CS_CDB16, port + PORT_CTRL_STAT);
|
||||
else
|
||||
writel(PORT_CS_CDB16, port + PORT_CTRL_CLR);
|
||||
|
@ -427,14 +428,23 @@ static void sil24_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
|
|||
*tf = pp->tf;
|
||||
}
|
||||
|
||||
static int sil24_issue_SRST(struct ata_port *ap)
|
||||
static int sil24_softreset(struct ata_port *ap, int verbose,
|
||||
unsigned int *class)
|
||||
{
|
||||
void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr;
|
||||
struct sil24_port_priv *pp = ap->private_data;
|
||||
struct sil24_prb *prb = &pp->cmd_block[0].ata.prb;
|
||||
dma_addr_t paddr = pp->cmd_block_dma;
|
||||
unsigned long timeout = jiffies + ATA_TMOUT_BOOT * HZ;
|
||||
u32 irq_enable, irq_stat;
|
||||
int cnt;
|
||||
|
||||
DPRINTK("ENTER\n");
|
||||
|
||||
if (!sata_dev_present(ap)) {
|
||||
DPRINTK("PHY reports no device\n");
|
||||
*class = ATA_DEV_NONE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* temporarily turn off IRQs during SRST */
|
||||
irq_enable = readl(port + PORT_IRQ_ENABLE_SET);
|
||||
|
@ -451,7 +461,7 @@ static int sil24_issue_SRST(struct ata_port *ap)
|
|||
|
||||
writel((u32)paddr, port + PORT_CMD_ACTIVATE);
|
||||
|
||||
for (cnt = 0; cnt < 100; cnt++) {
|
||||
do {
|
||||
irq_stat = readl(port + PORT_IRQ_STAT);
|
||||
writel(irq_stat, port + PORT_IRQ_STAT); /* clear irq */
|
||||
|
||||
|
@ -459,36 +469,42 @@ static int sil24_issue_SRST(struct ata_port *ap)
|
|||
if (irq_stat & (PORT_IRQ_COMPLETE | PORT_IRQ_ERROR))
|
||||
break;
|
||||
|
||||
msleep(1);
|
||||
}
|
||||
msleep(100);
|
||||
} while (time_before(jiffies, timeout));
|
||||
|
||||
/* restore IRQs */
|
||||
writel(irq_enable, port + PORT_IRQ_ENABLE_SET);
|
||||
|
||||
if (!(irq_stat & PORT_IRQ_COMPLETE))
|
||||
return -1;
|
||||
if (!(irq_stat & PORT_IRQ_COMPLETE)) {
|
||||
DPRINTK("EXIT, srst failed\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* update TF */
|
||||
sil24_update_tf(ap);
|
||||
*class = ata_dev_classify(&pp->tf);
|
||||
|
||||
if (*class == ATA_DEV_UNKNOWN)
|
||||
*class = ATA_DEV_NONE;
|
||||
|
||||
out:
|
||||
DPRINTK("EXIT, class=%u\n", *class);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void sil24_phy_reset(struct ata_port *ap)
|
||||
static int sil24_hardreset(struct ata_port *ap, int verbose,
|
||||
unsigned int *class)
|
||||
{
|
||||
struct sil24_port_priv *pp = ap->private_data;
|
||||
unsigned int dummy_class;
|
||||
|
||||
__sata_phy_reset(ap);
|
||||
if (ap->flags & ATA_FLAG_PORT_DISABLED)
|
||||
return;
|
||||
/* sil24 doesn't report device signature after hard reset */
|
||||
return sata_std_hardreset(ap, verbose, &dummy_class);
|
||||
}
|
||||
|
||||
if (sil24_issue_SRST(ap) < 0) {
|
||||
printk(KERN_ERR DRV_NAME
|
||||
" ata%u: SRST failed, disabling port\n", ap->id);
|
||||
ap->ops->port_disable(ap);
|
||||
return;
|
||||
}
|
||||
|
||||
ap->device->class = ata_dev_classify(&pp->tf);
|
||||
static int sil24_probe_reset(struct ata_port *ap, unsigned int *classes)
|
||||
{
|
||||
return ata_drive_probe_reset(ap, ata_std_probeinit,
|
||||
sil24_softreset, sil24_hardreset,
|
||||
ata_std_postreset, classes);
|
||||
}
|
||||
|
||||
static inline void sil24_fill_sg(struct ata_queued_cmd *qc,
|
||||
|
@ -533,7 +549,7 @@ static void sil24_qc_prep(struct ata_queued_cmd *qc)
|
|||
prb = &cb->atapi.prb;
|
||||
sge = cb->atapi.sge;
|
||||
memset(cb->atapi.cdb, 0, 32);
|
||||
memcpy(cb->atapi.cdb, qc->cdb, ap->cdb_len);
|
||||
memcpy(cb->atapi.cdb, qc->cdb, qc->dev->cdb_len);
|
||||
|
||||
if (qc->tf.protocol != ATA_PROT_ATAPI_NODATA) {
|
||||
if (qc->tf.flags & ATA_TFLAG_WRITE)
|
||||
|
@ -557,7 +573,7 @@ static void sil24_qc_prep(struct ata_queued_cmd *qc)
|
|||
sil24_fill_sg(qc, sge);
|
||||
}
|
||||
|
||||
static int sil24_qc_issue(struct ata_queued_cmd *qc)
|
||||
static unsigned int sil24_qc_issue(struct ata_queued_cmd *qc)
|
||||
{
|
||||
struct ata_port *ap = qc->ap;
|
||||
void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr;
|
||||
|
@ -638,23 +654,10 @@ static void sil24_eng_timeout(struct ata_port *ap)
|
|||
struct ata_queued_cmd *qc;
|
||||
|
||||
qc = ata_qc_from_tag(ap, ap->active_tag);
|
||||
if (!qc) {
|
||||
printk(KERN_ERR "ata%u: BUG: timeout without command\n",
|
||||
ap->id);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* hack alert! We cannot use the supplied completion
|
||||
* function from inside the ->eh_strategy_handler() thread.
|
||||
* libata is the only user of ->eh_strategy_handler() in
|
||||
* any kernel, so the default scsi_done() assumes it is
|
||||
* not being called from the SCSI EH.
|
||||
*/
|
||||
printk(KERN_ERR "ata%u: command timeout\n", ap->id);
|
||||
qc->scsidone = scsi_finish_command;
|
||||
qc->err_mask |= AC_ERR_OTHER;
|
||||
ata_qc_complete(qc);
|
||||
qc->err_mask |= AC_ERR_TIMEOUT;
|
||||
ata_eh_qc_complete(qc);
|
||||
|
||||
sil24_reset_controller(ap);
|
||||
}
|
||||
|
@ -895,6 +898,7 @@ static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
|
|||
probe_ent->sht = pinfo->sht;
|
||||
probe_ent->host_flags = pinfo->host_flags;
|
||||
probe_ent->pio_mask = pinfo->pio_mask;
|
||||
probe_ent->mwdma_mask = pinfo->mwdma_mask;
|
||||
probe_ent->udma_mask = pinfo->udma_mask;
|
||||
probe_ent->port_ops = pinfo->port_ops;
|
||||
probe_ent->n_ports = SIL24_FLAG2NPORTS(pinfo->host_flags);
|
||||
|
|
|
@ -87,11 +87,11 @@ static struct scsi_host_template sis_sht = {
|
|||
.name = DRV_NAME,
|
||||
.ioctl = ata_scsi_ioctl,
|
||||
.queuecommand = ata_scsi_queuecmd,
|
||||
.eh_timed_out = ata_scsi_timed_out,
|
||||
.eh_strategy_handler = ata_scsi_error,
|
||||
.can_queue = ATA_DEF_QUEUE,
|
||||
.this_id = ATA_SHT_THIS_ID,
|
||||
.sg_tablesize = ATA_MAX_PRD,
|
||||
.max_sectors = ATA_MAX_SECTORS,
|
||||
.cmd_per_lun = ATA_SHT_CMD_PER_LUN,
|
||||
.emulated = ATA_SHT_EMULATED,
|
||||
.use_clustering = ATA_SHT_USE_CLUSTERING,
|
||||
|
|
|
@ -288,11 +288,11 @@ static struct scsi_host_template k2_sata_sht = {
|
|||
.name = DRV_NAME,
|
||||
.ioctl = ata_scsi_ioctl,
|
||||
.queuecommand = ata_scsi_queuecmd,
|
||||
.eh_timed_out = ata_scsi_timed_out,
|
||||
.eh_strategy_handler = ata_scsi_error,
|
||||
.can_queue = ATA_DEF_QUEUE,
|
||||
.this_id = ATA_SHT_THIS_ID,
|
||||
.sg_tablesize = LIBATA_MAX_PRD,
|
||||
.max_sectors = ATA_MAX_SECTORS,
|
||||
.cmd_per_lun = ATA_SHT_CMD_PER_LUN,
|
||||
.emulated = ATA_SHT_EMULATED,
|
||||
.use_clustering = ATA_SHT_USE_CLUSTERING,
|
||||
|
|
|
@ -174,7 +174,7 @@ static void pdc20621_get_from_dimm(struct ata_probe_ent *pe,
|
|||
static void pdc20621_put_to_dimm(struct ata_probe_ent *pe,
|
||||
void *psource, u32 offset, u32 size);
|
||||
static void pdc20621_irq_clear(struct ata_port *ap);
|
||||
static int pdc20621_qc_issue_prot(struct ata_queued_cmd *qc);
|
||||
static unsigned int pdc20621_qc_issue_prot(struct ata_queued_cmd *qc);
|
||||
|
||||
|
||||
static struct scsi_host_template pdc_sata_sht = {
|
||||
|
@ -182,11 +182,11 @@ static struct scsi_host_template pdc_sata_sht = {
|
|||
.name = DRV_NAME,
|
||||
.ioctl = ata_scsi_ioctl,
|
||||
.queuecommand = ata_scsi_queuecmd,
|
||||
.eh_timed_out = ata_scsi_timed_out,
|
||||
.eh_strategy_handler = ata_scsi_error,
|
||||
.can_queue = ATA_DEF_QUEUE,
|
||||
.this_id = ATA_SHT_THIS_ID,
|
||||
.sg_tablesize = LIBATA_MAX_PRD,
|
||||
.max_sectors = ATA_MAX_SECTORS,
|
||||
.cmd_per_lun = ATA_SHT_CMD_PER_LUN,
|
||||
.emulated = ATA_SHT_EMULATED,
|
||||
.use_clustering = ATA_SHT_USE_CLUSTERING,
|
||||
|
@ -460,7 +460,7 @@ static void pdc20621_dma_prep(struct ata_queued_cmd *qc)
|
|||
unsigned int i, idx, total_len = 0, sgt_len;
|
||||
u32 *buf = (u32 *) &pp->dimm_buf[PDC_DIMM_HEADER_SZ];
|
||||
|
||||
assert(qc->flags & ATA_QCFLAG_DMAMAP);
|
||||
WARN_ON(!(qc->flags & ATA_QCFLAG_DMAMAP));
|
||||
|
||||
VPRINTK("ata%u: ENTER\n", ap->id);
|
||||
|
||||
|
@ -678,7 +678,7 @@ static void pdc20621_packet_start(struct ata_queued_cmd *qc)
|
|||
}
|
||||
}
|
||||
|
||||
static int pdc20621_qc_issue_prot(struct ata_queued_cmd *qc)
|
||||
static unsigned int pdc20621_qc_issue_prot(struct ata_queued_cmd *qc)
|
||||
{
|
||||
switch (qc->tf.protocol) {
|
||||
case ATA_PROT_DMA:
|
||||
|
@ -866,26 +866,12 @@ static void pdc_eng_timeout(struct ata_port *ap)
|
|||
spin_lock_irqsave(&host_set->lock, flags);
|
||||
|
||||
qc = ata_qc_from_tag(ap, ap->active_tag);
|
||||
if (!qc) {
|
||||
printk(KERN_ERR "ata%u: BUG: timeout without command\n",
|
||||
ap->id);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* hack alert! We cannot use the supplied completion
|
||||
* function from inside the ->eh_strategy_handler() thread.
|
||||
* libata is the only user of ->eh_strategy_handler() in
|
||||
* any kernel, so the default scsi_done() assumes it is
|
||||
* not being called from the SCSI EH.
|
||||
*/
|
||||
qc->scsidone = scsi_finish_command;
|
||||
|
||||
switch (qc->tf.protocol) {
|
||||
case ATA_PROT_DMA:
|
||||
case ATA_PROT_NODATA:
|
||||
printk(KERN_ERR "ata%u: command timeout\n", ap->id);
|
||||
qc->err_mask |= __ac_err_mask(ata_wait_idle(ap));
|
||||
ata_qc_complete(qc);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -895,12 +881,11 @@ static void pdc_eng_timeout(struct ata_port *ap)
|
|||
ap->id, qc->tf.command, drv_stat);
|
||||
|
||||
qc->err_mask |= ac_err_mask(drv_stat);
|
||||
ata_qc_complete(qc);
|
||||
break;
|
||||
}
|
||||
|
||||
out:
|
||||
spin_unlock_irqrestore(&host_set->lock, flags);
|
||||
ata_eh_qc_complete(qc);
|
||||
DPRINTK("EXIT\n");
|
||||
}
|
||||
|
||||
|
|
|
@ -75,11 +75,11 @@ static struct scsi_host_template uli_sht = {
|
|||
.name = DRV_NAME,
|
||||
.ioctl = ata_scsi_ioctl,
|
||||
.queuecommand = ata_scsi_queuecmd,
|
||||
.eh_timed_out = ata_scsi_timed_out,
|
||||
.eh_strategy_handler = ata_scsi_error,
|
||||
.can_queue = ATA_DEF_QUEUE,
|
||||
.this_id = ATA_SHT_THIS_ID,
|
||||
.sg_tablesize = LIBATA_MAX_PRD,
|
||||
.max_sectors = ATA_MAX_SECTORS,
|
||||
.cmd_per_lun = ATA_SHT_CMD_PER_LUN,
|
||||
.emulated = ATA_SHT_EMULATED,
|
||||
.use_clustering = ATA_SHT_USE_CLUSTERING,
|
||||
|
|
|
@ -94,11 +94,11 @@ static struct scsi_host_template svia_sht = {
|
|||
.name = DRV_NAME,
|
||||
.ioctl = ata_scsi_ioctl,
|
||||
.queuecommand = ata_scsi_queuecmd,
|
||||
.eh_timed_out = ata_scsi_timed_out,
|
||||
.eh_strategy_handler = ata_scsi_error,
|
||||
.can_queue = ATA_DEF_QUEUE,
|
||||
.this_id = ATA_SHT_THIS_ID,
|
||||
.sg_tablesize = LIBATA_MAX_PRD,
|
||||
.max_sectors = ATA_MAX_SECTORS,
|
||||
.cmd_per_lun = ATA_SHT_CMD_PER_LUN,
|
||||
.emulated = ATA_SHT_EMULATED,
|
||||
.use_clustering = ATA_SHT_USE_CLUSTERING,
|
||||
|
|
|
@ -251,11 +251,11 @@ static struct scsi_host_template vsc_sata_sht = {
|
|||
.name = DRV_NAME,
|
||||
.ioctl = ata_scsi_ioctl,
|
||||
.queuecommand = ata_scsi_queuecmd,
|
||||
.eh_timed_out = ata_scsi_timed_out,
|
||||
.eh_strategy_handler = ata_scsi_error,
|
||||
.can_queue = ATA_DEF_QUEUE,
|
||||
.this_id = ATA_SHT_THIS_ID,
|
||||
.sg_tablesize = LIBATA_MAX_PRD,
|
||||
.max_sectors = ATA_MAX_SECTORS,
|
||||
.cmd_per_lun = ATA_SHT_CMD_PER_LUN,
|
||||
.emulated = ATA_SHT_EMULATED,
|
||||
.use_clustering = ATA_SHT_USE_CLUSTERING,
|
||||
|
|
|
@ -584,8 +584,7 @@ static int scsi_request_sense(struct scsi_cmnd *scmd)
|
|||
* keep a list of pending commands for final completion, and once we
|
||||
* are ready to leave error handling we handle completion for real.
|
||||
**/
|
||||
static void scsi_eh_finish_cmd(struct scsi_cmnd *scmd,
|
||||
struct list_head *done_q)
|
||||
void scsi_eh_finish_cmd(struct scsi_cmnd *scmd, struct list_head *done_q)
|
||||
{
|
||||
scmd->device->host->host_failed--;
|
||||
scmd->eh_eflags = 0;
|
||||
|
@ -597,6 +596,7 @@ static void scsi_eh_finish_cmd(struct scsi_cmnd *scmd,
|
|||
scsi_setup_cmd_retry(scmd);
|
||||
list_move_tail(&scmd->eh_entry, done_q);
|
||||
}
|
||||
EXPORT_SYMBOL(scsi_eh_finish_cmd);
|
||||
|
||||
/**
|
||||
* scsi_eh_get_sense - Get device sense data.
|
||||
|
@ -1425,7 +1425,7 @@ static void scsi_eh_ready_devs(struct Scsi_Host *shost,
|
|||
* @done_q: list_head of processed commands.
|
||||
*
|
||||
**/
|
||||
static void scsi_eh_flush_done_q(struct list_head *done_q)
|
||||
void scsi_eh_flush_done_q(struct list_head *done_q)
|
||||
{
|
||||
struct scsi_cmnd *scmd, *next;
|
||||
|
||||
|
@ -1454,6 +1454,7 @@ static void scsi_eh_flush_done_q(struct list_head *done_q)
|
|||
}
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(scsi_eh_flush_done_q);
|
||||
|
||||
/**
|
||||
* scsi_unjam_host - Attempt to fix a host which has a cmd that failed.
|
||||
|
|
|
@ -267,6 +267,16 @@ struct ata_taskfile {
|
|||
((u64) (id)[(n) + 1] << 16) | \
|
||||
((u64) (id)[(n) + 0]) )
|
||||
|
||||
static inline unsigned int ata_id_major_version(const u16 *id)
|
||||
{
|
||||
unsigned int mver;
|
||||
|
||||
for (mver = 14; mver >= 1; mver--)
|
||||
if (id[ATA_ID_MAJOR_VER] & (1 << mver))
|
||||
break;
|
||||
return mver;
|
||||
}
|
||||
|
||||
static inline int ata_id_current_chs_valid(const u16 *id)
|
||||
{
|
||||
/* For ATA-1 devices, if the INITIALIZE DEVICE PARAMETERS command
|
||||
|
@ -302,4 +312,16 @@ static inline int ata_ok(u8 status)
|
|||
== ATA_DRDY);
|
||||
}
|
||||
|
||||
static inline int lba_28_ok(u64 block, u32 n_block)
|
||||
{
|
||||
/* check the ending block number */
|
||||
return ((block + n_block - 1) < ((u64)1 << 28)) && (n_block <= 256);
|
||||
}
|
||||
|
||||
static inline int lba_48_ok(u64 block, u32 n_block)
|
||||
{
|
||||
/* check the ending block number */
|
||||
return ((block + n_block - 1) < ((u64)1 << 48)) && (n_block <= 65536);
|
||||
}
|
||||
|
||||
#endif /* __LINUX_ATA_H__ */
|
||||
|
|
|
@ -35,7 +35,8 @@
|
|||
#include <linux/workqueue.h>
|
||||
|
||||
/*
|
||||
* compile-time options
|
||||
* compile-time options: to be removed as soon as all the drivers are
|
||||
* converted to the new debugging mechanism
|
||||
*/
|
||||
#undef ATA_DEBUG /* debugging output */
|
||||
#undef ATA_VERBOSE_DEBUG /* yet more debugging output */
|
||||
|
@ -61,15 +62,37 @@
|
|||
|
||||
#define BPRINTK(fmt, args...) if (ap->flags & ATA_FLAG_DEBUGMSG) printk(KERN_ERR "%s: " fmt, __FUNCTION__, ## args)
|
||||
|
||||
#ifdef ATA_NDEBUG
|
||||
#define assert(expr)
|
||||
#else
|
||||
#define assert(expr) \
|
||||
if(unlikely(!(expr))) { \
|
||||
printk(KERN_ERR "Assertion failed! %s,%s,%s,line=%d\n", \
|
||||
#expr,__FILE__,__FUNCTION__,__LINE__); \
|
||||
}
|
||||
#endif
|
||||
/* NEW: debug levels */
|
||||
#define HAVE_LIBATA_MSG 1
|
||||
|
||||
enum {
|
||||
ATA_MSG_DRV = 0x0001,
|
||||
ATA_MSG_INFO = 0x0002,
|
||||
ATA_MSG_PROBE = 0x0004,
|
||||
ATA_MSG_WARN = 0x0008,
|
||||
ATA_MSG_MALLOC = 0x0010,
|
||||
ATA_MSG_CTL = 0x0020,
|
||||
ATA_MSG_INTR = 0x0040,
|
||||
ATA_MSG_ERR = 0x0080,
|
||||
};
|
||||
|
||||
#define ata_msg_drv(p) ((p)->msg_enable & ATA_MSG_DRV)
|
||||
#define ata_msg_info(p) ((p)->msg_enable & ATA_MSG_INFO)
|
||||
#define ata_msg_probe(p) ((p)->msg_enable & ATA_MSG_PROBE)
|
||||
#define ata_msg_warn(p) ((p)->msg_enable & ATA_MSG_WARN)
|
||||
#define ata_msg_malloc(p) ((p)->msg_enable & ATA_MSG_MALLOC)
|
||||
#define ata_msg_ctl(p) ((p)->msg_enable & ATA_MSG_CTL)
|
||||
#define ata_msg_intr(p) ((p)->msg_enable & ATA_MSG_INTR)
|
||||
#define ata_msg_err(p) ((p)->msg_enable & ATA_MSG_ERR)
|
||||
|
||||
static inline u32 ata_msg_init(int dval, int default_msg_enable_bits)
|
||||
{
|
||||
if (dval < 0 || dval >= (sizeof(u32) * 8))
|
||||
return default_msg_enable_bits; /* should be 0x1 - only driver info msgs */
|
||||
if (!dval)
|
||||
return 0;
|
||||
return (1 << dval) - 1;
|
||||
}
|
||||
|
||||
/* defines only for the constants which don't work well as enums */
|
||||
#define ATA_TAG_POISON 0xfafbfcfdU
|
||||
|
@ -99,8 +122,7 @@ enum {
|
|||
/* struct ata_device stuff */
|
||||
ATA_DFLAG_LBA48 = (1 << 0), /* device supports LBA48 */
|
||||
ATA_DFLAG_PIO = (1 << 1), /* device currently in PIO mode */
|
||||
ATA_DFLAG_LOCK_SECTORS = (1 << 2), /* don't adjust max_sectors */
|
||||
ATA_DFLAG_LBA = (1 << 3), /* device supports LBA */
|
||||
ATA_DFLAG_LBA = (1 << 2), /* device supports LBA */
|
||||
|
||||
ATA_DEV_UNKNOWN = 0, /* unknown device */
|
||||
ATA_DEV_ATA = 1, /* ATA device */
|
||||
|
@ -115,9 +137,9 @@ enum {
|
|||
ATA_FLAG_PORT_DISABLED = (1 << 2), /* port is disabled, ignore it */
|
||||
ATA_FLAG_SATA = (1 << 3),
|
||||
ATA_FLAG_NO_LEGACY = (1 << 4), /* no legacy mode check */
|
||||
ATA_FLAG_SRST = (1 << 5), /* use ATA SRST, not E.D.D. */
|
||||
ATA_FLAG_SRST = (1 << 5), /* (obsolete) use ATA SRST, not E.D.D. */
|
||||
ATA_FLAG_MMIO = (1 << 6), /* use MMIO, not PIO */
|
||||
ATA_FLAG_SATA_RESET = (1 << 7), /* use COMRESET */
|
||||
ATA_FLAG_SATA_RESET = (1 << 7), /* (obsolete) use COMRESET */
|
||||
ATA_FLAG_PIO_DMA = (1 << 8), /* PIO cmds via DMA */
|
||||
ATA_FLAG_NOINTR = (1 << 9), /* FIXME: Remove this once
|
||||
* proper HSM is in place. */
|
||||
|
@ -129,10 +151,14 @@ enum {
|
|||
ATA_FLAG_PIO_LBA48 = (1 << 13), /* Host DMA engine is LBA28 only */
|
||||
ATA_FLAG_IRQ_MASK = (1 << 14), /* Mask IRQ in PIO xfers */
|
||||
|
||||
ATA_FLAG_FLUSH_PORT_TASK = (1 << 15), /* Flush port task */
|
||||
ATA_FLAG_IN_EH = (1 << 16), /* EH in progress */
|
||||
|
||||
ATA_QCFLAG_ACTIVE = (1 << 1), /* cmd not yet ack'd to scsi lyer */
|
||||
ATA_QCFLAG_SG = (1 << 3), /* have s/g table? */
|
||||
ATA_QCFLAG_SINGLE = (1 << 4), /* no s/g, just a single buffer */
|
||||
ATA_QCFLAG_DMAMAP = ATA_QCFLAG_SG | ATA_QCFLAG_SINGLE,
|
||||
ATA_QCFLAG_EH_SCHEDULED = (1 << 5), /* EH scheduled */
|
||||
|
||||
/* various lengths of time */
|
||||
ATA_TMOUT_EDD = 5 * HZ, /* heuristic */
|
||||
|
@ -162,11 +188,19 @@ enum {
|
|||
PORT_DISABLED = 2,
|
||||
|
||||
/* encoding various smaller bitmaps into a single
|
||||
* unsigned long bitmap
|
||||
* unsigned int bitmap
|
||||
*/
|
||||
ATA_SHIFT_UDMA = 0,
|
||||
ATA_SHIFT_MWDMA = 8,
|
||||
ATA_SHIFT_PIO = 11,
|
||||
ATA_BITS_PIO = 5,
|
||||
ATA_BITS_MWDMA = 3,
|
||||
ATA_BITS_UDMA = 8,
|
||||
|
||||
ATA_SHIFT_PIO = 0,
|
||||
ATA_SHIFT_MWDMA = ATA_SHIFT_PIO + ATA_BITS_PIO,
|
||||
ATA_SHIFT_UDMA = ATA_SHIFT_MWDMA + ATA_BITS_MWDMA,
|
||||
|
||||
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 */
|
||||
ATA_DMA_PAD_SZ = 4,
|
||||
|
@ -189,10 +223,15 @@ enum hsm_task_states {
|
|||
};
|
||||
|
||||
enum ata_completion_errors {
|
||||
AC_ERR_OTHER = (1 << 0),
|
||||
AC_ERR_DEV = (1 << 1),
|
||||
AC_ERR_ATA_BUS = (1 << 2),
|
||||
AC_ERR_HOST_BUS = (1 << 3),
|
||||
AC_ERR_DEV = (1 << 0), /* device reported error */
|
||||
AC_ERR_HSM = (1 << 1), /* host state machine violation */
|
||||
AC_ERR_TIMEOUT = (1 << 2), /* timeout */
|
||||
AC_ERR_MEDIA = (1 << 3), /* media error */
|
||||
AC_ERR_ATA_BUS = (1 << 4), /* ATA bus error */
|
||||
AC_ERR_HOST_BUS = (1 << 5), /* host bus error */
|
||||
AC_ERR_SYSTEM = (1 << 6), /* system error */
|
||||
AC_ERR_INVALID = (1 << 7), /* invalid argument */
|
||||
AC_ERR_OTHER = (1 << 8), /* unknown */
|
||||
};
|
||||
|
||||
/* forward declarations */
|
||||
|
@ -202,7 +241,10 @@ struct ata_port;
|
|||
struct ata_queued_cmd;
|
||||
|
||||
/* typedefs */
|
||||
typedef int (*ata_qc_cb_t) (struct ata_queued_cmd *qc);
|
||||
typedef void (*ata_qc_cb_t) (struct ata_queued_cmd *qc);
|
||||
typedef void (*ata_probeinit_fn_t)(struct ata_port *);
|
||||
typedef int (*ata_reset_fn_t)(struct ata_port *, int, unsigned int *);
|
||||
typedef void (*ata_postreset_fn_t)(struct ata_port *ap, unsigned int *);
|
||||
|
||||
struct ata_ioports {
|
||||
unsigned long cmd_addr;
|
||||
|
@ -305,7 +347,7 @@ struct ata_device {
|
|||
unsigned long flags; /* ATA_DFLAG_xxx */
|
||||
unsigned int class; /* ATA_DEV_xxx */
|
||||
unsigned int devno; /* 0 or 1 */
|
||||
u16 id[ATA_ID_WORDS]; /* IDENTIFY xxx DEVICE data */
|
||||
u16 *id; /* IDENTIFY xxx DEVICE data */
|
||||
u8 pio_mode;
|
||||
u8 dma_mode;
|
||||
u8 xfer_mode;
|
||||
|
@ -313,6 +355,8 @@ struct ata_device {
|
|||
|
||||
unsigned int multi_count; /* sectors count for
|
||||
READ/WRITE MULTIPLE */
|
||||
unsigned int max_sectors; /* per-device max sectors */
|
||||
unsigned int cdb_len;
|
||||
|
||||
/* for CHS addressing */
|
||||
u16 cylinders; /* Number of cylinders */
|
||||
|
@ -342,7 +386,6 @@ struct ata_port {
|
|||
unsigned int mwdma_mask;
|
||||
unsigned int udma_mask;
|
||||
unsigned int cbl; /* cable type; ATA_CBL_xxx */
|
||||
unsigned int cdb_len;
|
||||
|
||||
struct ata_device device[ATA_MAX_DEVICES];
|
||||
|
||||
|
@ -353,12 +396,14 @@ struct ata_port {
|
|||
struct ata_host_stats stats;
|
||||
struct ata_host_set *host_set;
|
||||
|
||||
struct work_struct packet_task;
|
||||
struct work_struct port_task;
|
||||
|
||||
struct work_struct pio_task;
|
||||
unsigned int hsm_task_state;
|
||||
unsigned long pio_task_timeout;
|
||||
|
||||
u32 msg_enable;
|
||||
struct list_head eh_done_q;
|
||||
|
||||
void *private_data;
|
||||
};
|
||||
|
||||
|
@ -378,7 +423,9 @@ struct ata_port_operations {
|
|||
u8 (*check_altstatus)(struct ata_port *ap);
|
||||
void (*dev_select)(struct ata_port *ap, unsigned int device);
|
||||
|
||||
void (*phy_reset) (struct ata_port *ap);
|
||||
void (*phy_reset) (struct ata_port *ap); /* obsolete */
|
||||
int (*probe_reset) (struct ata_port *ap, unsigned int *classes);
|
||||
|
||||
void (*post_set_mode) (struct ata_port *ap);
|
||||
|
||||
int (*check_atapi_dma) (struct ata_queued_cmd *qc);
|
||||
|
@ -387,7 +434,7 @@ struct ata_port_operations {
|
|||
void (*bmdma_start) (struct ata_queued_cmd *qc);
|
||||
|
||||
void (*qc_prep) (struct ata_queued_cmd *qc);
|
||||
int (*qc_issue) (struct ata_queued_cmd *qc);
|
||||
unsigned int (*qc_issue) (struct ata_queued_cmd *qc);
|
||||
|
||||
void (*eng_timeout) (struct ata_port *ap);
|
||||
|
||||
|
@ -435,6 +482,18 @@ extern void ata_port_probe(struct ata_port *);
|
|||
extern void __sata_phy_reset(struct ata_port *ap);
|
||||
extern void sata_phy_reset(struct ata_port *ap);
|
||||
extern void ata_bus_reset(struct ata_port *ap);
|
||||
extern int ata_drive_probe_reset(struct ata_port *ap,
|
||||
ata_probeinit_fn_t probeinit,
|
||||
ata_reset_fn_t softreset, ata_reset_fn_t hardreset,
|
||||
ata_postreset_fn_t postreset, unsigned int *classes);
|
||||
extern void ata_std_probeinit(struct ata_port *ap);
|
||||
extern int ata_std_softreset(struct ata_port *ap, int verbose,
|
||||
unsigned int *classes);
|
||||
extern int sata_std_hardreset(struct ata_port *ap, int verbose,
|
||||
unsigned int *class);
|
||||
extern void ata_std_postreset(struct ata_port *ap, unsigned int *classes);
|
||||
extern int ata_dev_revalidate(struct ata_port *ap, struct ata_device *dev,
|
||||
int post_reset);
|
||||
extern void ata_port_disable(struct ata_port *);
|
||||
extern void ata_std_ports(struct ata_ioports *ioaddr);
|
||||
#ifdef CONFIG_PCI
|
||||
|
@ -449,7 +508,10 @@ extern void ata_host_set_remove(struct ata_host_set *host_set);
|
|||
extern int ata_scsi_detect(struct scsi_host_template *sht);
|
||||
extern int ata_scsi_ioctl(struct scsi_device *dev, int cmd, void __user *arg);
|
||||
extern int ata_scsi_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *));
|
||||
extern enum scsi_eh_timer_return ata_scsi_timed_out(struct scsi_cmnd *cmd);
|
||||
extern int ata_scsi_error(struct Scsi_Host *host);
|
||||
extern void ata_eh_qc_complete(struct ata_queued_cmd *qc);
|
||||
extern void ata_eh_qc_retry(struct ata_queued_cmd *qc);
|
||||
extern int ata_scsi_release(struct Scsi_Host *host);
|
||||
extern unsigned int ata_host_intr(struct ata_port *ap, struct ata_queued_cmd *qc);
|
||||
extern int ata_scsi_device_resume(struct scsi_device *);
|
||||
|
@ -457,6 +519,11 @@ extern int ata_scsi_device_suspend(struct scsi_device *);
|
|||
extern int ata_device_resume(struct ata_port *, struct ata_device *);
|
||||
extern int ata_device_suspend(struct ata_port *, struct ata_device *);
|
||||
extern int ata_ratelimit(void);
|
||||
extern unsigned int ata_busy_sleep(struct ata_port *ap,
|
||||
unsigned long timeout_pat,
|
||||
unsigned long timeout);
|
||||
extern void ata_port_queue_task(struct ata_port *ap, void (*fn)(void *),
|
||||
void *data, unsigned long delay);
|
||||
|
||||
/*
|
||||
* Default driver ops implementations
|
||||
|
@ -470,26 +537,28 @@ extern void ata_std_dev_select (struct ata_port *ap, unsigned int device);
|
|||
extern u8 ata_check_status(struct ata_port *ap);
|
||||
extern u8 ata_altstatus(struct ata_port *ap);
|
||||
extern void ata_exec_command(struct ata_port *ap, const struct ata_taskfile *tf);
|
||||
extern int ata_std_probe_reset(struct ata_port *ap, unsigned int *classes);
|
||||
extern int ata_port_start (struct ata_port *ap);
|
||||
extern void ata_port_stop (struct ata_port *ap);
|
||||
extern void ata_host_stop (struct ata_host_set *host_set);
|
||||
extern irqreturn_t ata_interrupt (int irq, void *dev_instance, struct pt_regs *regs);
|
||||
extern void ata_qc_prep(struct ata_queued_cmd *qc);
|
||||
extern 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,
|
||||
unsigned int n_elem);
|
||||
extern unsigned int ata_dev_classify(const struct ata_taskfile *tf);
|
||||
extern void ata_dev_id_string(const u16 *id, unsigned char *s,
|
||||
unsigned int ofs, unsigned int len);
|
||||
extern void ata_dev_config(struct ata_port *ap, unsigned int i);
|
||||
extern void ata_id_string(const u16 *id, unsigned char *s,
|
||||
unsigned int ofs, unsigned int len);
|
||||
extern void ata_id_c_string(const u16 *id, unsigned char *s,
|
||||
unsigned int ofs, unsigned int len);
|
||||
extern void ata_bmdma_setup (struct ata_queued_cmd *qc);
|
||||
extern void ata_bmdma_start (struct ata_queued_cmd *qc);
|
||||
extern void ata_bmdma_stop(struct ata_queued_cmd *qc);
|
||||
extern u8 ata_bmdma_status(struct ata_port *ap);
|
||||
extern void ata_bmdma_irq_clear(struct ata_port *ap);
|
||||
extern void ata_qc_complete(struct ata_queued_cmd *qc);
|
||||
extern void __ata_qc_complete(struct ata_queued_cmd *qc);
|
||||
extern void ata_eng_timeout(struct ata_port *ap);
|
||||
extern void ata_scsi_simulate(struct ata_port *ap, struct ata_device *dev,
|
||||
struct scsi_cmnd *cmd,
|
||||
|
@ -586,10 +655,14 @@ static inline unsigned int ata_tag_valid(unsigned int tag)
|
|||
return (tag < ATA_MAX_QUEUE) ? 1 : 0;
|
||||
}
|
||||
|
||||
static inline unsigned int ata_class_present(unsigned int class)
|
||||
{
|
||||
return class == ATA_DEV_ATA || class == ATA_DEV_ATAPI;
|
||||
}
|
||||
|
||||
static inline unsigned int ata_dev_present(const struct ata_device *dev)
|
||||
{
|
||||
return ((dev->class == ATA_DEV_ATA) ||
|
||||
(dev->class == ATA_DEV_ATAPI));
|
||||
return ata_class_present(dev->class);
|
||||
}
|
||||
|
||||
static inline u8 ata_chk_status(struct ata_port *ap)
|
||||
|
@ -657,9 +730,9 @@ static inline u8 ata_wait_idle(struct ata_port *ap)
|
|||
|
||||
if (status & (ATA_BUSY | ATA_DRQ)) {
|
||||
unsigned long l = ap->ioaddr.status_addr;
|
||||
printk(KERN_WARNING
|
||||
"ATA: abnormal status 0x%X on port 0x%lX\n",
|
||||
status, l);
|
||||
if (ata_msg_warn(ap))
|
||||
printk(KERN_WARNING "ATA: abnormal status 0x%X on port 0x%lX\n",
|
||||
status, l);
|
||||
}
|
||||
|
||||
return status;
|
||||
|
@ -701,6 +774,24 @@ static inline void ata_qc_reinit(struct ata_queued_cmd *qc)
|
|||
ata_tf_init(qc->ap, &qc->tf, qc->dev->devno);
|
||||
}
|
||||
|
||||
/**
|
||||
* ata_qc_complete - Complete an active ATA command
|
||||
* @qc: Command to complete
|
||||
* @err_mask: ATA Status register contents
|
||||
*
|
||||
* Indicate to the mid and upper layers that an ATA
|
||||
* command has completed, with either an ok or not-ok status.
|
||||
*
|
||||
* LOCKING:
|
||||
* spin_lock_irqsave(host_set lock)
|
||||
*/
|
||||
static inline void ata_qc_complete(struct ata_queued_cmd *qc)
|
||||
{
|
||||
if (unlikely(qc->flags & ATA_QCFLAG_EH_SCHEDULED))
|
||||
return;
|
||||
|
||||
__ata_qc_complete(qc);
|
||||
}
|
||||
|
||||
/**
|
||||
* ata_irq_on - Enable interrupts on a port.
|
||||
|
@ -751,7 +842,8 @@ static inline u8 ata_irq_ack(struct ata_port *ap, unsigned int chk_drq)
|
|||
|
||||
status = ata_busy_wait(ap, bits, 1000);
|
||||
if (status & bits)
|
||||
DPRINTK("abnormal status 0x%X\n", status);
|
||||
if (ata_msg_err(ap))
|
||||
printk(KERN_ERR "abnormal status 0x%X\n", status);
|
||||
|
||||
/* get controller status; clear intr, err bits */
|
||||
if (ap->flags & ATA_FLAG_MMIO) {
|
||||
|
@ -769,8 +861,10 @@ static inline u8 ata_irq_ack(struct ata_port *ap, unsigned int chk_drq)
|
|||
post_stat = inb(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS);
|
||||
}
|
||||
|
||||
VPRINTK("irq ack: host_stat 0x%X, new host_stat 0x%X, drv_stat 0x%X\n",
|
||||
host_stat, post_stat, status);
|
||||
if (ata_msg_intr(ap))
|
||||
printk(KERN_INFO "%s: irq ack: host_stat 0x%X, new host_stat 0x%X, drv_stat 0x%X\n",
|
||||
__FUNCTION__,
|
||||
host_stat, post_stat, status);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
@ -807,7 +901,7 @@ static inline int ata_try_flush_cache(const struct ata_device *dev)
|
|||
static inline unsigned int ac_err_mask(u8 status)
|
||||
{
|
||||
if (status & ATA_BUSY)
|
||||
return AC_ERR_ATA_BUS;
|
||||
return AC_ERR_HSM;
|
||||
if (status & (ATA_ERR | ATA_DF))
|
||||
return AC_ERR_DEV;
|
||||
return 0;
|
||||
|
|
|
@ -35,6 +35,9 @@ static inline int scsi_sense_valid(struct scsi_sense_hdr *sshdr)
|
|||
}
|
||||
|
||||
|
||||
extern void scsi_eh_finish_cmd(struct scsi_cmnd *scmd,
|
||||
struct list_head *done_q);
|
||||
extern void scsi_eh_flush_done_q(struct list_head *done_q);
|
||||
extern void scsi_report_bus_reset(struct Scsi_Host *, int);
|
||||
extern void scsi_report_device_reset(struct Scsi_Host *, int, int);
|
||||
extern int scsi_block_when_processing_errors(struct scsi_device *);
|
||||
|
|
Loading…
Reference in a new issue