dect
/
linux-2.6
Archived
13
0
Fork 0

Merge branch 'upstream' of master.kernel.org:/pub/scm/linux/kernel/git/jgarzik/libata-dev

This commit is contained in:
Linus Torvalds 2005-10-28 09:06:50 -07:00
commit 5fadd053d9
23 changed files with 4982 additions and 828 deletions

File diff suppressed because it is too large Load Diff

View File

@ -489,11 +489,11 @@ config SCSI_SATA_NV
If unsure, say N.
config SCSI_SATA_PROMISE
tristate "Promise SATA TX2/TX4 support"
config SCSI_PDC_ADMA
tristate "Pacific Digital ADMA support"
depends on SCSI_SATA && PCI
help
This option enables support for Promise Serial ATA TX2/TX4.
This option enables support for Pacific Digital ADMA controllers
If unsure, say N.
@ -505,6 +505,14 @@ config SCSI_SATA_QSTOR
If unsure, say N.
config SCSI_SATA_PROMISE
tristate "Promise SATA TX2/TX4 support"
depends on SCSI_SATA && PCI
help
This option enables support for Promise Serial ATA TX2/TX4.
If unsure, say N.
config SCSI_SATA_SX4
tristate "Promise SATA SX4 support"
depends on SCSI_SATA && PCI && EXPERIMENTAL
@ -521,6 +529,14 @@ config SCSI_SATA_SIL
If unsure, say N.
config SCSI_SATA_SIL24
tristate "Silicon Image 3124/3132 SATA support"
depends on SCSI_SATA && PCI && EXPERIMENTAL
help
This option enables support for Silicon Image 3124/3132 Serial ATA.
If unsure, say N.
config SCSI_SATA_SIS
tristate "SiS 964/180 SATA support"
depends on SCSI_SATA && PCI && EXPERIMENTAL

View File

@ -130,6 +130,7 @@ obj-$(CONFIG_SCSI_ATA_PIIX) += libata.o ata_piix.o
obj-$(CONFIG_SCSI_SATA_PROMISE) += libata.o sata_promise.o
obj-$(CONFIG_SCSI_SATA_QSTOR) += libata.o sata_qstor.o
obj-$(CONFIG_SCSI_SATA_SIL) += libata.o sata_sil.o
obj-$(CONFIG_SCSI_SATA_SIL24) += libata.o sata_sil24.o
obj-$(CONFIG_SCSI_SATA_VIA) += libata.o sata_via.o
obj-$(CONFIG_SCSI_SATA_VITESSE) += libata.o sata_vsc.o
obj-$(CONFIG_SCSI_SATA_SIS) += libata.o sata_sis.o
@ -137,6 +138,7 @@ obj-$(CONFIG_SCSI_SATA_SX4) += libata.o sata_sx4.o
obj-$(CONFIG_SCSI_SATA_NV) += libata.o sata_nv.o
obj-$(CONFIG_SCSI_SATA_ULI) += libata.o sata_uli.o
obj-$(CONFIG_SCSI_SATA_MV) += libata.o sata_mv.o
obj-$(CONFIG_SCSI_PDC_ADMA) += libata.o pdc_adma.o
obj-$(CONFIG_ARM) += arm/

View File

@ -216,7 +216,7 @@ static Scsi_Host_Template ahci_sht = {
.ordered_flush = 1,
};
static struct ata_port_operations ahci_ops = {
static const struct ata_port_operations ahci_ops = {
.port_disable = ata_port_disable,
.check_status = ahci_check_status,
@ -407,7 +407,7 @@ static u32 ahci_scr_read (struct ata_port *ap, unsigned int sc_reg_in)
return 0xffffffffU;
}
return readl((void *) ap->ioaddr.scr_addr + (sc_reg * 4));
return readl((void __iomem *) ap->ioaddr.scr_addr + (sc_reg * 4));
}
@ -425,7 +425,7 @@ static void ahci_scr_write (struct ata_port *ap, unsigned int sc_reg_in,
return;
}
writel(val, (void *) ap->ioaddr.scr_addr + (sc_reg * 4));
writel(val, (void __iomem *) ap->ioaddr.scr_addr + (sc_reg * 4));
}
static void ahci_phy_reset(struct ata_port *ap)
@ -453,14 +453,14 @@ static void ahci_phy_reset(struct ata_port *ap)
static u8 ahci_check_status(struct ata_port *ap)
{
void *mmio = (void *) ap->ioaddr.cmd_addr;
void __iomem *mmio = (void __iomem *) ap->ioaddr.cmd_addr;
return readl(mmio + PORT_TFDATA) & 0xFF;
}
static u8 ahci_check_err(struct ata_port *ap)
{
void *mmio = (void *) ap->ioaddr.cmd_addr;
void __iomem *mmio = (void __iomem *) ap->ioaddr.cmd_addr;
return (readl(mmio + PORT_TFDATA) >> 8) & 0xFF;
}
@ -672,17 +672,36 @@ static irqreturn_t ahci_interrupt (int irq, void *dev_instance, struct pt_regs *
for (i = 0; i < host_set->n_ports; i++) {
struct ata_port *ap;
u32 tmp;
VPRINTK("port %u\n", i);
if (!(irq_stat & (1 << i)))
continue;
ap = host_set->ports[i];
tmp = irq_stat & (1 << i);
if (tmp && ap) {
if (ap) {
struct ata_queued_cmd *qc;
qc = ata_qc_from_tag(ap, ap->active_tag);
if (ahci_host_intr(ap, qc))
irq_ack |= (1 << i);
if (!ahci_host_intr(ap, qc))
if (ata_ratelimit()) {
struct pci_dev *pdev =
to_pci_dev(ap->host_set->dev);
printk(KERN_WARNING
"ahci(%s): unhandled interrupt on port %u\n",
pci_name(pdev), i);
}
VPRINTK("port %u\n", i);
} else {
VPRINTK("port %u (no irq)\n", i);
if (ata_ratelimit()) {
struct pci_dev *pdev =
to_pci_dev(ap->host_set->dev);
printk(KERN_WARNING
"ahci(%s): interrupt on disabled port %u\n",
pci_name(pdev), i);
}
}
irq_ack |= (1 << i);
}
if (irq_ack) {

View File

@ -147,7 +147,7 @@ static Scsi_Host_Template piix_sht = {
.ordered_flush = 1,
};
static struct ata_port_operations piix_pata_ops = {
static const struct ata_port_operations piix_pata_ops = {
.port_disable = ata_port_disable,
.set_piomode = piix_set_piomode,
.set_dmamode = piix_set_dmamode,
@ -177,7 +177,7 @@ static struct ata_port_operations piix_pata_ops = {
.host_stop = ata_host_stop,
};
static struct ata_port_operations piix_sata_ops = {
static const struct ata_port_operations piix_sata_ops = {
.port_disable = ata_port_disable,
.tf_load = ata_tf_load,

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -39,18 +39,23 @@ struct ata_scsi_args {
/* libata-core.c */
extern int atapi_enabled;
extern int ata_qc_complete_noop(struct ata_queued_cmd *qc, u8 drv_stat);
extern struct ata_queued_cmd *ata_qc_new_init(struct ata_port *ap,
struct ata_device *dev);
extern void ata_rwcmd_protocol(struct ata_queued_cmd *qc);
extern void ata_qc_free(struct ata_queued_cmd *qc);
extern 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);
extern void ata_tf_to_host_nolock(struct ata_port *ap, struct ata_taskfile *tf);
extern void ata_tf_to_host_nolock(struct ata_port *ap, const struct ata_taskfile *tf);
extern void swap_buf_le16(u16 *buf, unsigned int buf_words);
/* libata-scsi.c */
extern void atapi_request_sense(struct ata_port *ap, struct ata_device *dev,
struct scsi_cmnd *cmd);
extern void ata_scsi_scan_host(struct ata_port *ap);
extern void ata_to_sense_error(struct ata_queued_cmd *qc, u8 drv_stat);
extern int ata_scsi_error(struct Scsi_Host *host);
extern unsigned int ata_scsiop_inq_std(struct ata_scsi_args *args, u8 *rbuf,
@ -76,18 +81,10 @@ extern unsigned int ata_scsiop_report_luns(struct ata_scsi_args *args, u8 *rbuf,
extern void ata_scsi_badcmd(struct scsi_cmnd *cmd,
void (*done)(struct scsi_cmnd *),
u8 asc, u8 ascq);
extern void ata_scsi_set_sense(struct scsi_cmnd *cmd,
u8 sk, u8 asc, u8 ascq);
extern void ata_scsi_rbuf_fill(struct ata_scsi_args *args,
unsigned int (*actor) (struct ata_scsi_args *args,
u8 *rbuf, unsigned int buflen));
static inline void ata_bad_scsiop(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
{
ata_scsi_badcmd(cmd, done, 0x20, 0x00);
}
static inline void ata_bad_cdb(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
{
ata_scsi_badcmd(cmd, done, 0x24, 0x00);
}
#endif /* __LIBATA_H__ */

739
drivers/scsi/pdc_adma.c Normal file
View File

@ -0,0 +1,739 @@
/*
* pdc_adma.c - Pacific Digital Corporation ADMA
*
* Maintained by: Mark Lord <mlord@pobox.com>
*
* Copyright 2005 Mark Lord
*
* 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.*
*
*
* Supports ATA disks in single-packet ADMA mode.
* Uses PIO for everything else.
*
* TODO: Use ADMA transfers for ATAPI devices, when possible.
* This requires careful attention to a number of quirks of the chip.
*
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/init.h>
#include <linux/blkdev.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/sched.h>
#include "scsi.h"
#include <scsi/scsi_host.h>
#include <asm/io.h>
#include <linux/libata.h>
#define DRV_NAME "pdc_adma"
#define DRV_VERSION "0.01"
/* macro to calculate base address for ATA regs */
#define ADMA_ATA_REGS(base,port_no) ((base) + ((port_no) * 0x40))
/* macro to calculate base address for ADMA regs */
#define ADMA_REGS(base,port_no) ((base) + 0x80 + ((port_no) * 0x20))
enum {
ADMA_PORTS = 2,
ADMA_CPB_BYTES = 40,
ADMA_PRD_BYTES = LIBATA_MAX_PRD * 16,
ADMA_PKT_BYTES = ADMA_CPB_BYTES + ADMA_PRD_BYTES,
ADMA_DMA_BOUNDARY = 0xffffffff,
/* global register offsets */
ADMA_MODE_LOCK = 0x00c7,
/* per-channel register offsets */
ADMA_CONTROL = 0x0000, /* ADMA control */
ADMA_STATUS = 0x0002, /* ADMA status */
ADMA_CPB_COUNT = 0x0004, /* CPB count */
ADMA_CPB_CURRENT = 0x000c, /* current CPB address */
ADMA_CPB_NEXT = 0x000c, /* next CPB address */
ADMA_CPB_LOOKUP = 0x0010, /* CPB lookup table */
ADMA_FIFO_IN = 0x0014, /* input FIFO threshold */
ADMA_FIFO_OUT = 0x0016, /* output FIFO threshold */
/* ADMA_CONTROL register bits */
aNIEN = (1 << 8), /* irq mask: 1==masked */
aGO = (1 << 7), /* packet trigger ("Go!") */
aRSTADM = (1 << 5), /* ADMA logic reset */
aRSTA = (1 << 2), /* ATA hard reset */
aPIOMD4 = 0x0003, /* PIO mode 4 */
/* ADMA_STATUS register bits */
aPSD = (1 << 6),
aUIRQ = (1 << 4),
aPERR = (1 << 0),
/* CPB bits */
cDONE = (1 << 0),
cVLD = (1 << 0),
cDAT = (1 << 2),
cIEN = (1 << 3),
/* PRD bits */
pORD = (1 << 4),
pDIRO = (1 << 5),
pEND = (1 << 7),
/* ATA register flags */
rIGN = (1 << 5),
rEND = (1 << 7),
/* ATA register addresses */
ADMA_REGS_CONTROL = 0x0e,
ADMA_REGS_SECTOR_COUNT = 0x12,
ADMA_REGS_LBA_LOW = 0x13,
ADMA_REGS_LBA_MID = 0x14,
ADMA_REGS_LBA_HIGH = 0x15,
ADMA_REGS_DEVICE = 0x16,
ADMA_REGS_COMMAND = 0x17,
/* PCI device IDs */
board_1841_idx = 0, /* ADMA 2-port controller */
};
typedef enum { adma_state_idle, adma_state_pkt, adma_state_mmio } adma_state_t;
struct adma_port_priv {
u8 *pkt;
dma_addr_t pkt_dma;
adma_state_t state;
};
static int adma_ata_init_one (struct pci_dev *pdev,
const struct pci_device_id *ent);
static irqreturn_t adma_intr (int irq, void *dev_instance,
struct pt_regs *regs);
static int adma_port_start(struct ata_port *ap);
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 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);
static void adma_irq_clear(struct ata_port *ap);
static void adma_eng_timeout(struct ata_port *ap);
static Scsi_Host_Template adma_ata_sht = {
.module = THIS_MODULE,
.name = DRV_NAME,
.ioctl = ata_scsi_ioctl,
.queuecommand = ata_scsi_queuecmd,
.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,
.proc_name = DRV_NAME,
.dma_boundary = ADMA_DMA_BOUNDARY,
.slave_configure = ata_scsi_slave_config,
.bios_param = ata_std_bios_param,
};
static const struct ata_port_operations adma_ata_ops = {
.port_disable = ata_port_disable,
.tf_load = ata_tf_load,
.tf_read = ata_tf_read,
.check_status = ata_check_status,
.check_atapi_dma = adma_check_atapi_dma,
.exec_command = ata_exec_command,
.dev_select = ata_std_dev_select,
.phy_reset = adma_phy_reset,
.qc_prep = adma_qc_prep,
.qc_issue = adma_qc_issue,
.eng_timeout = adma_eng_timeout,
.irq_handler = adma_intr,
.irq_clear = adma_irq_clear,
.port_start = adma_port_start,
.port_stop = adma_port_stop,
.host_stop = adma_host_stop,
.bmdma_stop = adma_bmdma_stop,
.bmdma_status = adma_bmdma_status,
};
static struct ata_port_info adma_port_info[] = {
/* board_1841_idx */
{
.sht = &adma_ata_sht,
.host_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST |
ATA_FLAG_NO_LEGACY | ATA_FLAG_MMIO,
.pio_mask = 0x10, /* pio4 */
.udma_mask = 0x1f, /* udma0-4 */
.port_ops = &adma_ata_ops,
},
};
static struct pci_device_id adma_ata_pci_tbl[] = {
{ PCI_VENDOR_ID_PDC, 0x1841, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
board_1841_idx },
{ } /* terminate list */
};
static struct pci_driver adma_ata_pci_driver = {
.name = DRV_NAME,
.id_table = adma_ata_pci_tbl,
.probe = adma_ata_init_one,
.remove = ata_pci_remove_one,
};
static int adma_check_atapi_dma(struct ata_queued_cmd *qc)
{
return 1; /* ATAPI DMA not yet supported */
}
static void adma_bmdma_stop(struct ata_queued_cmd *qc)
{
/* nothing */
}
static u8 adma_bmdma_status(struct ata_port *ap)
{
return 0;
}
static void adma_irq_clear(struct ata_port *ap)
{
/* nothing */
}
static void adma_reset_engine(void __iomem *chan)
{
/* reset ADMA to idle state */
writew(aPIOMD4 | aNIEN | aRSTADM, chan + ADMA_CONTROL);
udelay(2);
writew(aPIOMD4, chan + ADMA_CONTROL);
udelay(2);
}
static void adma_reinit_engine(struct ata_port *ap)
{
struct adma_port_priv *pp = ap->private_data;
void __iomem *mmio_base = ap->host_set->mmio_base;
void __iomem *chan = ADMA_REGS(mmio_base, ap->port_no);
/* mask/clear ATA interrupts */
writeb(ATA_NIEN, (void __iomem *)ap->ioaddr.ctl_addr);
ata_check_status(ap);
/* reset the ADMA engine */
adma_reset_engine(chan);
/* set in-FIFO threshold to 0x100 */
writew(0x100, chan + ADMA_FIFO_IN);
/* set CPB pointer */
writel((u32)pp->pkt_dma, chan + ADMA_CPB_NEXT);
/* set out-FIFO threshold to 0x100 */
writew(0x100, chan + ADMA_FIFO_OUT);
/* set CPB count */
writew(1, chan + ADMA_CPB_COUNT);
/* read/discard ADMA status */
readb(chan + ADMA_STATUS);
}
static inline void adma_enter_reg_mode(struct ata_port *ap)
{
void __iomem *chan = ADMA_REGS(ap->host_set->mmio_base, ap->port_no);
writew(aPIOMD4, chan + ADMA_CONTROL);
readb(chan + ADMA_STATUS); /* flush */
}
static void adma_phy_reset(struct ata_port *ap)
{
struct adma_port_priv *pp = ap->private_data;
pp->state = adma_state_idle;
adma_reinit_engine(ap);
ata_port_probe(ap);
ata_bus_reset(ap);
}
static void adma_eng_timeout(struct ata_port *ap)
{
struct adma_port_priv *pp = ap->private_data;
if (pp->state != adma_state_idle) /* healthy paranoia */
pp->state = adma_state_mmio;
adma_reinit_engine(ap);
ata_eng_timeout(ap);
}
static int adma_fill_sg(struct ata_queued_cmd *qc)
{
struct scatterlist *sg = qc->sg;
struct ata_port *ap = qc->ap;
struct adma_port_priv *pp = ap->private_data;
u8 *buf = pp->pkt;
int nelem, i = (2 + buf[3]) * 8;
u8 pFLAGS = pORD | ((qc->tf.flags & ATA_TFLAG_WRITE) ? pDIRO : 0);
for (nelem = 0; nelem < qc->n_elem; nelem++,sg++) {
u32 addr;
u32 len;
addr = (u32)sg_dma_address(sg);
*(__le32 *)(buf + i) = cpu_to_le32(addr);
i += 4;
len = sg_dma_len(sg) >> 3;
*(__le32 *)(buf + i) = cpu_to_le32(len);
i += 4;
if ((nelem + 1) == qc->n_elem)
pFLAGS |= pEND;
buf[i++] = pFLAGS;
buf[i++] = qc->dev->dma_mode & 0xf;
buf[i++] = 0; /* pPKLW */
buf[i++] = 0; /* reserved */
*(__le32 *)(buf + i)
= (pFLAGS & pEND) ? 0 : cpu_to_le32(pp->pkt_dma + i + 4);
i += 4;
VPRINTK("PRD[%u] = (0x%lX, 0x%X)\n", nelem,
(unsigned long)addr, len);
}
return i;
}
static void adma_qc_prep(struct ata_queued_cmd *qc)
{
struct adma_port_priv *pp = qc->ap->private_data;
u8 *buf = pp->pkt;
u32 pkt_dma = (u32)pp->pkt_dma;
int i = 0;
VPRINTK("ENTER\n");
adma_enter_reg_mode(qc->ap);
if (qc->tf.protocol != ATA_PROT_DMA) {
ata_qc_prep(qc);
return;
}
buf[i++] = 0; /* Response flags */
buf[i++] = 0; /* reserved */
buf[i++] = cVLD | cDAT | cIEN;
i++; /* cLEN, gets filled in below */
*(__le32 *)(buf+i) = cpu_to_le32(pkt_dma); /* cNCPB */
i += 4; /* cNCPB */
i += 4; /* cPRD, gets filled in below */
buf[i++] = 0; /* reserved */
buf[i++] = 0; /* reserved */
buf[i++] = 0; /* reserved */
buf[i++] = 0; /* reserved */
/* ATA registers; must be a multiple of 4 */
buf[i++] = qc->tf.device;
buf[i++] = ADMA_REGS_DEVICE;
if ((qc->tf.flags & ATA_TFLAG_LBA48)) {
buf[i++] = qc->tf.hob_nsect;
buf[i++] = ADMA_REGS_SECTOR_COUNT;
buf[i++] = qc->tf.hob_lbal;
buf[i++] = ADMA_REGS_LBA_LOW;
buf[i++] = qc->tf.hob_lbam;
buf[i++] = ADMA_REGS_LBA_MID;
buf[i++] = qc->tf.hob_lbah;
buf[i++] = ADMA_REGS_LBA_HIGH;
}
buf[i++] = qc->tf.nsect;
buf[i++] = ADMA_REGS_SECTOR_COUNT;
buf[i++] = qc->tf.lbal;
buf[i++] = ADMA_REGS_LBA_LOW;
buf[i++] = qc->tf.lbam;
buf[i++] = ADMA_REGS_LBA_MID;
buf[i++] = qc->tf.lbah;
buf[i++] = ADMA_REGS_LBA_HIGH;
buf[i++] = 0;
buf[i++] = ADMA_REGS_CONTROL;
buf[i++] = rIGN;
buf[i++] = 0;
buf[i++] = qc->tf.command;
buf[i++] = ADMA_REGS_COMMAND | rEND;
buf[3] = (i >> 3) - 2; /* cLEN */
*(__le32 *)(buf+8) = cpu_to_le32(pkt_dma + i); /* cPRD */
i = adma_fill_sg(qc);
wmb(); /* flush PRDs and pkt to memory */
#if 0
/* dump out CPB + PRDs for debug */
{
int j, len = 0;
static char obuf[2048];
for (j = 0; j < i; ++j) {
len += sprintf(obuf+len, "%02x ", buf[j]);
if ((j & 7) == 7) {
printk("%s\n", obuf);
len = 0;
}
}
if (len)
printk("%s\n", obuf);
}
#endif
}
static inline void adma_packet_start(struct ata_queued_cmd *qc)
{
struct ata_port *ap = qc->ap;
void __iomem *chan = ADMA_REGS(ap->host_set->mmio_base, ap->port_no);
VPRINTK("ENTER, ap %p\n", ap);
/* fire up the ADMA engine */
writew(aPIOMD4 | aGO, chan + ADMA_CONTROL);
}
static int adma_qc_issue(struct ata_queued_cmd *qc)
{
struct adma_port_priv *pp = qc->ap->private_data;
switch (qc->tf.protocol) {
case ATA_PROT_DMA:
pp->state = adma_state_pkt;
adma_packet_start(qc);
return 0;
case ATA_PROT_ATAPI_DMA:
BUG();
break;
default:
break;
}
pp->state = adma_state_mmio;
return ata_qc_issue_prot(qc);
}
static inline unsigned int adma_intr_pkt(struct ata_host_set *host_set)
{
unsigned int handled = 0, port_no;
u8 __iomem *mmio_base = host_set->mmio_base;
for (port_no = 0; port_no < host_set->n_ports; ++port_no) {
struct ata_port *ap = host_set->ports[port_no];
struct adma_port_priv *pp;
struct ata_queued_cmd *qc;
void __iomem *chan = ADMA_REGS(mmio_base, port_no);
u8 drv_stat, status = readb(chan + ADMA_STATUS);
if (status == 0)
continue;
handled = 1;
adma_enter_reg_mode(ap);
if ((ap->flags & ATA_FLAG_PORT_DISABLED))
continue;
pp = ap->private_data;
if (!pp || pp->state != adma_state_pkt)
continue;
qc = ata_qc_from_tag(ap, ap->active_tag);
drv_stat = 0;
if ((status & (aPERR | aPSD | aUIRQ)))
drv_stat = ATA_ERR;
else if (pp->pkt[0] != cDONE)
drv_stat = ATA_ERR;
ata_qc_complete(qc, drv_stat);
}
return handled;
}
static inline unsigned int adma_intr_mmio(struct ata_host_set *host_set)
{
unsigned int handled = 0, port_no;
for (port_no = 0; port_no < host_set->n_ports; ++port_no) {
struct ata_port *ap;
ap = host_set->ports[port_no];
if (ap && (!(ap->flags & (ATA_FLAG_PORT_DISABLED | ATA_FLAG_NOINTR)))) {
struct ata_queued_cmd *qc;
struct adma_port_priv *pp = ap->private_data;
if (!pp || pp->state != adma_state_mmio)
continue;
qc = ata_qc_from_tag(ap, ap->active_tag);
if (qc && (!(qc->tf.ctl & ATA_NIEN))) {
/* check main status, clearing INTRQ */
u8 status = ata_chk_status(ap);
if ((status & ATA_BUSY))
continue;
DPRINTK("ata%u: protocol %d (dev_stat 0x%X)\n",
ap->id, qc->tf.protocol, status);
/* complete taskfile transaction */
pp->state = adma_state_idle;
ata_qc_complete(qc, status);
handled = 1;
}
}
}
return handled;
}
static irqreturn_t adma_intr(int irq, void *dev_instance, struct pt_regs *regs)
{
struct ata_host_set *host_set = dev_instance;
unsigned int handled = 0;
VPRINTK("ENTER\n");
spin_lock(&host_set->lock);
handled = adma_intr_pkt(host_set) | adma_intr_mmio(host_set);
spin_unlock(&host_set->lock);
VPRINTK("EXIT\n");
return IRQ_RETVAL(handled);
}
static void adma_ata_setup_port(struct ata_ioports *port, unsigned long base)
{
port->cmd_addr =
port->data_addr = base + 0x000;
port->error_addr =
port->feature_addr = base + 0x004;
port->nsect_addr = base + 0x008;
port->lbal_addr = base + 0x00c;
port->lbam_addr = base + 0x010;
port->lbah_addr = base + 0x014;
port->device_addr = base + 0x018;
port->status_addr =
port->command_addr = base + 0x01c;
port->altstatus_addr =
port->ctl_addr = base + 0x038;
}
static int adma_port_start(struct ata_port *ap)
{
struct device *dev = ap->host_set->dev;
struct adma_port_priv *pp;
int rc;
rc = ata_port_start(ap);
if (rc)
return rc;
adma_enter_reg_mode(ap);
rc = -ENOMEM;
pp = kcalloc(1, sizeof(*pp), GFP_KERNEL);
if (!pp)
goto err_out;
pp->pkt = dma_alloc_coherent(dev, ADMA_PKT_BYTES, &pp->pkt_dma,
GFP_KERNEL);
if (!pp->pkt)
goto err_out_kfree;
/* paranoia? */
if ((pp->pkt_dma & 7) != 0) {
printk("bad alignment for pp->pkt_dma: %08x\n",
(u32)pp->pkt_dma);
goto err_out_kfree2;
}
memset(pp->pkt, 0, ADMA_PKT_BYTES);
ap->private_data = pp;
adma_reinit_engine(ap);
return 0;
err_out_kfree2:
kfree(pp);
err_out_kfree:
kfree(pp);
err_out:
ata_port_stop(ap);
return rc;
}
static void adma_port_stop(struct ata_port *ap)
{
struct device *dev = ap->host_set->dev;
struct adma_port_priv *pp = ap->private_data;
adma_reset_engine(ADMA_REGS(ap->host_set->mmio_base, ap->port_no));
if (pp != NULL) {
ap->private_data = NULL;
if (pp->pkt != NULL)
dma_free_coherent(dev, ADMA_PKT_BYTES,
pp->pkt, pp->pkt_dma);
kfree(pp);
}
ata_port_stop(ap);
}
static void adma_host_stop(struct ata_host_set *host_set)
{
unsigned int port_no;
for (port_no = 0; port_no < ADMA_PORTS; ++port_no)
adma_reset_engine(ADMA_REGS(host_set->mmio_base, port_no));
ata_pci_host_stop(host_set);
}
static void adma_host_init(unsigned int chip_id,
struct ata_probe_ent *probe_ent)
{
unsigned int port_no;
void __iomem *mmio_base = probe_ent->mmio_base;
/* enable/lock aGO operation */
writeb(7, mmio_base + ADMA_MODE_LOCK);
/* reset the ADMA logic */
for (port_no = 0; port_no < ADMA_PORTS; ++port_no)
adma_reset_engine(ADMA_REGS(mmio_base, port_no));
}
static int adma_set_dma_masks(struct pci_dev *pdev, void __iomem *mmio_base)
{
int rc;
rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
if (rc) {
printk(KERN_ERR DRV_NAME
"(%s): 32-bit DMA enable failed\n",
pci_name(pdev));
return rc;
}
rc = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
if (rc) {
printk(KERN_ERR DRV_NAME
"(%s): 32-bit consistent DMA enable failed\n",
pci_name(pdev));
return rc;
}
return 0;
}
static int adma_ata_init_one(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
static int printed_version;
struct ata_probe_ent *probe_ent = NULL;
void __iomem *mmio_base;
unsigned int board_idx = (unsigned int) ent->driver_data;
int rc, port_no;
if (!printed_version++)
printk(KERN_DEBUG DRV_NAME " version " DRV_VERSION "\n");
rc = pci_enable_device(pdev);
if (rc)
return rc;
rc = pci_request_regions(pdev, DRV_NAME);
if (rc)
goto err_out;
if ((pci_resource_flags(pdev, 4) & IORESOURCE_MEM) == 0) {
rc = -ENODEV;
goto err_out_regions;
}
mmio_base = pci_iomap(pdev, 4, 0);
if (mmio_base == NULL) {
rc = -ENOMEM;
goto err_out_regions;
}
rc = adma_set_dma_masks(pdev, mmio_base);
if (rc)
goto err_out_iounmap;
probe_ent = kcalloc(1, sizeof(*probe_ent), GFP_KERNEL);
if (probe_ent == NULL) {
rc = -ENOMEM;
goto err_out_iounmap;
}
probe_ent->dev = pci_dev_to_dev(pdev);
INIT_LIST_HEAD(&probe_ent->node);
probe_ent->sht = adma_port_info[board_idx].sht;
probe_ent->host_flags = adma_port_info[board_idx].host_flags;
probe_ent->pio_mask = adma_port_info[board_idx].pio_mask;
probe_ent->mwdma_mask = adma_port_info[board_idx].mwdma_mask;
probe_ent->udma_mask = adma_port_info[board_idx].udma_mask;
probe_ent->port_ops = adma_port_info[board_idx].port_ops;
probe_ent->irq = pdev->irq;
probe_ent->irq_flags = SA_SHIRQ;
probe_ent->mmio_base = mmio_base;
probe_ent->n_ports = ADMA_PORTS;
for (port_no = 0; port_no < probe_ent->n_ports; ++port_no) {
adma_ata_setup_port(&probe_ent->port[port_no],
ADMA_ATA_REGS((unsigned long)mmio_base, port_no));
}
pci_set_master(pdev);
/* initialize adapter */
adma_host_init(board_idx, probe_ent);
rc = ata_device_add(probe_ent);
kfree(probe_ent);
if (rc != ADMA_PORTS)
goto err_out_iounmap;
return 0;
err_out_iounmap:
pci_iounmap(pdev, mmio_base);
err_out_regions:
pci_release_regions(pdev);
err_out:
pci_disable_device(pdev);
return rc;
}
static int __init adma_ata_init(void)
{
return pci_module_init(&adma_ata_pci_driver);
}
static void __exit adma_ata_exit(void)
{
pci_unregister_driver(&adma_ata_pci_driver);
}
MODULE_AUTHOR("Mark Lord");
MODULE_DESCRIPTION("Pacific Digital Corporation ADMA low-level driver");
MODULE_LICENSE("GPL");
MODULE_DEVICE_TABLE(pci, adma_ata_pci_tbl);
MODULE_VERSION(DRV_VERSION);
module_init(adma_ata_init);
module_exit(adma_ata_exit);

File diff suppressed because it is too large Load Diff

View File

@ -238,7 +238,7 @@ static Scsi_Host_Template nv_sht = {
.ordered_flush = 1,
};
static struct ata_port_operations nv_ops = {
static const struct ata_port_operations nv_ops = {
.port_disable = ata_port_disable,
.tf_load = ata_tf_load,
.tf_read = ata_tf_read,
@ -331,7 +331,7 @@ static u32 nv_scr_read (struct ata_port *ap, unsigned int sc_reg)
return 0xffffffffU;
if (host->host_flags & NV_HOST_FLAGS_SCR_MMIO)
return readl((void*)ap->ioaddr.scr_addr + (sc_reg * 4));
return readl((void __iomem *)ap->ioaddr.scr_addr + (sc_reg * 4));
else
return inl(ap->ioaddr.scr_addr + (sc_reg * 4));
}
@ -345,7 +345,7 @@ static void nv_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val)
return;
if (host->host_flags & NV_HOST_FLAGS_SCR_MMIO)
writel(val, (void*)ap->ioaddr.scr_addr + (sc_reg * 4));
writel(val, (void __iomem *)ap->ioaddr.scr_addr + (sc_reg * 4));
else
outl(val, ap->ioaddr.scr_addr + (sc_reg * 4));
}
@ -405,7 +405,7 @@ static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
rc = -ENOMEM;
ppi = &nv_port_info;
probe_ent = ata_pci_init_native_mode(pdev, &ppi);
probe_ent = ata_pci_init_native_mode(pdev, &ppi, ATA_PORT_PRIMARY | ATA_PORT_SECONDARY);
if (!probe_ent)
goto err_out_regions;

View File

@ -87,8 +87,8 @@ static void pdc_port_stop(struct ata_port *ap);
static void pdc_pata_phy_reset(struct ata_port *ap);
static void pdc_sata_phy_reset(struct ata_port *ap);
static void pdc_qc_prep(struct ata_queued_cmd *qc);
static void pdc_tf_load_mmio(struct ata_port *ap, struct ata_taskfile *tf);
static void pdc_exec_command_mmio(struct ata_port *ap, struct ata_taskfile *tf);
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);
@ -113,7 +113,7 @@ static Scsi_Host_Template pdc_ata_sht = {
.ordered_flush = 1,
};
static struct ata_port_operations pdc_sata_ops = {
static const struct ata_port_operations pdc_sata_ops = {
.port_disable = ata_port_disable,
.tf_load = pdc_tf_load_mmio,
.tf_read = ata_tf_read,
@ -136,7 +136,7 @@ static struct ata_port_operations pdc_sata_ops = {
.host_stop = ata_pci_host_stop,
};
static struct ata_port_operations pdc_pata_ops = {
static const struct ata_port_operations pdc_pata_ops = {
.port_disable = ata_port_disable,
.tf_load = pdc_tf_load_mmio,
.tf_read = ata_tf_read,
@ -324,7 +324,7 @@ static u32 pdc_sata_scr_read (struct ata_port *ap, unsigned int sc_reg)
{
if (sc_reg > SCR_CONTROL)
return 0xffffffffU;
return readl((void *) ap->ioaddr.scr_addr + (sc_reg * 4));
return readl((void __iomem *) ap->ioaddr.scr_addr + (sc_reg * 4));
}
@ -333,7 +333,7 @@ static void pdc_sata_scr_write (struct ata_port *ap, unsigned int sc_reg,
{
if (sc_reg > SCR_CONTROL)
return;
writel(val, (void *) ap->ioaddr.scr_addr + (sc_reg * 4));
writel(val, (void __iomem *) ap->ioaddr.scr_addr + (sc_reg * 4));
}
static void pdc_qc_prep(struct ata_queued_cmd *qc)
@ -438,11 +438,11 @@ static inline unsigned int pdc_host_intr( struct ata_port *ap,
break;
default:
ap->stats.idle_irq++;
break;
ap->stats.idle_irq++;
break;
}
return handled;
return handled;
}
static void pdc_irq_clear(struct ata_port *ap)
@ -523,8 +523,8 @@ static inline void pdc_packet_start(struct ata_queued_cmd *qc)
pp->pkt[2] = seq;
wmb(); /* flush PRD, pkt writes */
writel(pp->pkt_dma, (void *) ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT);
readl((void *) ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT); /* flush */
writel(pp->pkt_dma, (void __iomem *) ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT);
readl((void __iomem *) ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT); /* flush */
}
static int pdc_qc_issue_prot(struct ata_queued_cmd *qc)
@ -546,7 +546,7 @@ static int pdc_qc_issue_prot(struct ata_queued_cmd *qc)
return ata_qc_issue_prot(qc);
}
static void pdc_tf_load_mmio(struct ata_port *ap, struct ata_taskfile *tf)
static void pdc_tf_load_mmio(struct ata_port *ap, const struct ata_taskfile *tf)
{
WARN_ON (tf->protocol == ATA_PROT_DMA ||
tf->protocol == ATA_PROT_NODATA);
@ -554,7 +554,7 @@ static void pdc_tf_load_mmio(struct ata_port *ap, struct ata_taskfile *tf)
}
static void pdc_exec_command_mmio(struct ata_port *ap, struct ata_taskfile *tf)
static void pdc_exec_command_mmio(struct ata_port *ap, const struct ata_taskfile *tf)
{
WARN_ON (tf->protocol == ATA_PROT_DMA ||
tf->protocol == ATA_PROT_NODATA);

View File

@ -51,8 +51,6 @@ enum {
QS_PRD_BYTES = QS_MAX_PRD * 16,
QS_PKT_BYTES = QS_CPB_BYTES + QS_PRD_BYTES,
QS_DMA_BOUNDARY = ~0UL,
/* global register offsets */
QS_HCF_CNFG3 = 0x0003, /* host configuration offset */
QS_HID_HPHY = 0x0004, /* host physical interface info */
@ -101,6 +99,10 @@ enum {
board_2068_idx = 0, /* QStor 4-port SATA/RAID */
};
enum {
QS_DMA_BOUNDARY = ~0UL
};
typedef enum { qs_state_idle, qs_state_pkt, qs_state_mmio } qs_state_t;
struct qs_port_priv {
@ -145,7 +147,7 @@ static Scsi_Host_Template qs_ata_sht = {
.bios_param = ata_std_bios_param,
};
static struct ata_port_operations qs_ata_ops = {
static const struct ata_port_operations qs_ata_ops = {
.port_disable = ata_port_disable,
.tf_load = ata_tf_load,
.tf_read = ata_tf_read,

View File

@ -150,7 +150,7 @@ static Scsi_Host_Template sil_sht = {
.ordered_flush = 1,
};
static struct ata_port_operations sil_ops = {
static const struct ata_port_operations sil_ops = {
.port_disable = ata_port_disable,
.dev_config = sil_dev_config,
.tf_load = ata_tf_load,
@ -289,7 +289,7 @@ static inline unsigned long sil_scr_addr(struct ata_port *ap, unsigned int sc_re
static u32 sil_scr_read (struct ata_port *ap, unsigned int sc_reg)
{
void *mmio = (void *) sil_scr_addr(ap, sc_reg);
void __iomem *mmio = (void __iomem *) sil_scr_addr(ap, sc_reg);
if (mmio)
return readl(mmio);
return 0xffffffffU;
@ -297,7 +297,7 @@ static u32 sil_scr_read (struct ata_port *ap, unsigned int sc_reg)
static void sil_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val)
{
void *mmio = (void *) sil_scr_addr(ap, sc_reg);
void *mmio = (void __iomem *) sil_scr_addr(ap, sc_reg);
if (mmio)
writel(val, mmio);
}

875
drivers/scsi/sata_sil24.c Normal file
View File

@ -0,0 +1,875 @@
/*
* sata_sil24.c - Driver for Silicon Image 3124/3132 SATA-2 controllers
*
* Copyright 2005 Tejun Heo
*
* Based on preview driver from Silicon Image.
*
* NOTE: No NCQ/ATAPI support yet. The preview driver didn't support
* NCQ nor ATAPI, and, unfortunately, I couldn't find out how to make
* those work. Enabling those shouldn't be difficult. Basic
* structure is all there (in libata-dev tree). If you have any
* information about this hardware, please contact me or linux-ide.
* Info is needed on...
*
* - How to issue tagged commands and turn on sactive on issue accordingly.
* - Where to put an ATAPI command and how to tell the device to send it.
* - How to enable/use 64bit.
*
* 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.
*
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/blkdev.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/dma-mapping.h>
#include <scsi/scsi_host.h>
#include "scsi.h"
#include <linux/libata.h>
#include <asm/io.h>
#define DRV_NAME "sata_sil24"
#define DRV_VERSION "0.22" /* Silicon Image's preview driver was 0.10 */
/*
* Port request block (PRB) 32 bytes
*/
struct sil24_prb {
u16 ctrl;
u16 prot;
u32 rx_cnt;
u8 fis[6 * 4];
};
/*
* Scatter gather entry (SGE) 16 bytes
*/
struct sil24_sge {
u64 addr;
u32 cnt;
u32 flags;
};
/*
* Port multiplier
*/
struct sil24_port_multiplier {
u32 diag;
u32 sactive;
};
enum {
/*
* Global controller registers (128 bytes @ BAR0)
*/
/* 32 bit regs */
HOST_SLOT_STAT = 0x00, /* 32 bit slot stat * 4 */
HOST_CTRL = 0x40,
HOST_IRQ_STAT = 0x44,
HOST_PHY_CFG = 0x48,
HOST_BIST_CTRL = 0x50,
HOST_BIST_PTRN = 0x54,
HOST_BIST_STAT = 0x58,
HOST_MEM_BIST_STAT = 0x5c,
HOST_FLASH_CMD = 0x70,
/* 8 bit regs */
HOST_FLASH_DATA = 0x74,
HOST_TRANSITION_DETECT = 0x75,
HOST_GPIO_CTRL = 0x76,
HOST_I2C_ADDR = 0x78, /* 32 bit */
HOST_I2C_DATA = 0x7c,
HOST_I2C_XFER_CNT = 0x7e,
HOST_I2C_CTRL = 0x7f,
/* HOST_SLOT_STAT bits */
HOST_SSTAT_ATTN = (1 << 31),
/*
* Port registers
* (8192 bytes @ +0x0000, +0x2000, +0x4000 and +0x6000 @ BAR2)
*/
PORT_REGS_SIZE = 0x2000,
PORT_PRB = 0x0000, /* (32 bytes PRB + 16 bytes SGEs * 6) * 31 (3968 bytes) */
PORT_PM = 0x0f80, /* 8 bytes PM * 16 (128 bytes) */
/* 32 bit regs */
PORT_CTRL_STAT = 0x1000, /* write: ctrl-set, read: stat */
PORT_CTRL_CLR = 0x1004, /* write: ctrl-clear */
PORT_IRQ_STAT = 0x1008, /* high: status, low: interrupt */
PORT_IRQ_ENABLE_SET = 0x1010, /* write: enable-set */
PORT_IRQ_ENABLE_CLR = 0x1014, /* write: enable-clear */
PORT_ACTIVATE_UPPER_ADDR= 0x101c,
PORT_EXEC_FIFO = 0x1020, /* command execution fifo */
PORT_CMD_ERR = 0x1024, /* command error number */
PORT_FIS_CFG = 0x1028,
PORT_FIFO_THRES = 0x102c,
/* 16 bit regs */
PORT_DECODE_ERR_CNT = 0x1040,
PORT_DECODE_ERR_THRESH = 0x1042,
PORT_CRC_ERR_CNT = 0x1044,
PORT_CRC_ERR_THRESH = 0x1046,
PORT_HSHK_ERR_CNT = 0x1048,
PORT_HSHK_ERR_THRESH = 0x104a,
/* 32 bit regs */
PORT_PHY_CFG = 0x1050,
PORT_SLOT_STAT = 0x1800,
PORT_CMD_ACTIVATE = 0x1c00, /* 64 bit cmd activate * 31 (248 bytes) */
PORT_EXEC_DIAG = 0x1e00, /* 32bit exec diag * 16 (64 bytes, 0-10 used on 3124) */
PORT_PSD_DIAG = 0x1e40, /* 32bit psd diag * 16 (64 bytes, 0-8 used on 3124) */
PORT_SCONTROL = 0x1f00,
PORT_SSTATUS = 0x1f04,
PORT_SERROR = 0x1f08,
PORT_SACTIVE = 0x1f0c,
/* PORT_CTRL_STAT bits */
PORT_CS_PORT_RST = (1 << 0), /* port reset */
PORT_CS_DEV_RST = (1 << 1), /* device reset */
PORT_CS_INIT = (1 << 2), /* port initialize */
PORT_CS_IRQ_WOC = (1 << 3), /* interrupt write one to clear */
PORT_CS_RESUME = (1 << 6), /* port resume */
PORT_CS_32BIT_ACTV = (1 << 10), /* 32-bit activation */
PORT_CS_PM_EN = (1 << 13), /* port multiplier enable */
PORT_CS_RDY = (1 << 31), /* port ready to accept commands */
/* PORT_IRQ_STAT/ENABLE_SET/CLR */
/* bits[11:0] are masked */
PORT_IRQ_COMPLETE = (1 << 0), /* command(s) completed */
PORT_IRQ_ERROR = (1 << 1), /* command execution error */
PORT_IRQ_PORTRDY_CHG = (1 << 2), /* port ready change */
PORT_IRQ_PWR_CHG = (1 << 3), /* power management change */
PORT_IRQ_PHYRDY_CHG = (1 << 4), /* PHY ready change */
PORT_IRQ_COMWAKE = (1 << 5), /* COMWAKE received */
PORT_IRQ_UNK_FIS = (1 << 6), /* Unknown FIS received */
PORT_IRQ_SDB_FIS = (1 << 11), /* SDB FIS received */
/* bits[27:16] are unmasked (raw) */
PORT_IRQ_RAW_SHIFT = 16,
PORT_IRQ_MASKED_MASK = 0x7ff,
PORT_IRQ_RAW_MASK = (0x7ff << PORT_IRQ_RAW_SHIFT),
/* ENABLE_SET/CLR specific, intr steering - 2 bit field */
PORT_IRQ_STEER_SHIFT = 30,
PORT_IRQ_STEER_MASK = (3 << PORT_IRQ_STEER_SHIFT),
/* PORT_CMD_ERR constants */
PORT_CERR_DEV = 1, /* Error bit in D2H Register FIS */
PORT_CERR_SDB = 2, /* Error bit in SDB FIS */
PORT_CERR_DATA = 3, /* Error in data FIS not detected by dev */
PORT_CERR_SEND = 4, /* Initial cmd FIS transmission failure */
PORT_CERR_INCONSISTENT = 5, /* Protocol mismatch */
PORT_CERR_DIRECTION = 6, /* Data direction mismatch */
PORT_CERR_UNDERRUN = 7, /* Ran out of SGEs while writing */
PORT_CERR_OVERRUN = 8, /* Ran out of SGEs while reading */
PORT_CERR_PKT_PROT = 11, /* DIR invalid in 1st PIO setup of ATAPI */
PORT_CERR_SGT_BOUNDARY = 16, /* PLD ecode 00 - SGT not on qword boundary */
PORT_CERR_SGT_TGTABRT = 17, /* PLD ecode 01 - target abort */
PORT_CERR_SGT_MSTABRT = 18, /* PLD ecode 10 - master abort */
PORT_CERR_SGT_PCIPERR = 19, /* PLD ecode 11 - PCI parity err while fetching SGT */
PORT_CERR_CMD_BOUNDARY = 24, /* ctrl[15:13] 001 - PRB not on qword boundary */
PORT_CERR_CMD_TGTABRT = 25, /* ctrl[15:13] 010 - target abort */
PORT_CERR_CMD_MSTABRT = 26, /* ctrl[15:13] 100 - master abort */
PORT_CERR_CMD_PCIPERR = 27, /* ctrl[15:13] 110 - PCI parity err while fetching PRB */
PORT_CERR_XFR_UNDEF = 32, /* PSD ecode 00 - undefined */
PORT_CERR_XFR_TGTABRT = 33, /* PSD ecode 01 - target abort */
PORT_CERR_XFR_MSGABRT = 34, /* PSD ecode 10 - master abort */
PORT_CERR_XFR_PCIPERR = 35, /* PSD ecode 11 - PCI prity err during transfer */
PORT_CERR_SENDSERVICE = 36, /* FIS received while sending service */
/*
* Other constants
*/
SGE_TRM = (1 << 31), /* Last SGE in chain */
PRB_SOFT_RST = (1 << 7), /* Soft reset request (ign BSY?) */
/* board id */
BID_SIL3124 = 0,
BID_SIL3132 = 1,
BID_SIL3131 = 2,
IRQ_STAT_4PORTS = 0xf,
};
struct sil24_cmd_block {
struct sil24_prb prb;
struct sil24_sge sge[LIBATA_MAX_PRD];
};
/*
* ap->private_data
*
* The preview driver always returned 0 for status. We emulate it
* here from the previous interrupt.
*/
struct sil24_port_priv {
struct sil24_cmd_block *cmd_block; /* 32 cmd blocks */
dma_addr_t cmd_block_dma; /* DMA base addr for them */
struct ata_taskfile tf; /* Cached taskfile registers */
};
/* ap->host_set->private_data */
struct sil24_host_priv {
void *host_base; /* global controller control (128 bytes @BAR0) */
void *port_base; /* port registers (4 * 8192 bytes @BAR2) */
};
static u8 sil24_check_status(struct ata_port *ap);
static u8 sil24_check_err(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 void sil24_qc_prep(struct ata_queued_cmd *qc);
static 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);
static int sil24_port_start(struct ata_port *ap);
static void sil24_port_stop(struct ata_port *ap);
static void sil24_host_stop(struct ata_host_set *host_set);
static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);
static struct pci_device_id sil24_pci_tbl[] = {
{ 0x1095, 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 },
{ } /* terminate list */
};
static struct pci_driver sil24_pci_driver = {
.name = DRV_NAME,
.id_table = sil24_pci_tbl,
.probe = sil24_init_one,
.remove = ata_pci_remove_one, /* safe? */
};
static Scsi_Host_Template sil24_sht = {
.module = THIS_MODULE,
.name = DRV_NAME,
.ioctl = ata_scsi_ioctl,
.queuecommand = ata_scsi_queuecmd,
.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,
.proc_name = DRV_NAME,
.dma_boundary = ATA_DMA_BOUNDARY,
.slave_configure = ata_scsi_slave_config,
.bios_param = ata_std_bios_param,
.ordered_flush = 1, /* NCQ not supported yet */
};
static const struct ata_port_operations sil24_ops = {
.port_disable = ata_port_disable,
.check_status = sil24_check_status,
.check_altstatus = sil24_check_status,
.check_err = sil24_check_err,
.dev_select = ata_noop_dev_select,
.tf_read = sil24_tf_read,
.phy_reset = sil24_phy_reset,
.qc_prep = sil24_qc_prep,
.qc_issue = sil24_qc_issue,
.eng_timeout = sil24_eng_timeout,
.irq_handler = sil24_interrupt,
.irq_clear = sil24_irq_clear,
.scr_read = sil24_scr_read,
.scr_write = sil24_scr_write,
.port_start = sil24_port_start,
.port_stop = sil24_port_stop,
.host_stop = sil24_host_stop,
};
/*
* Use bits 30-31 of host_flags to encode available port numbers.
* Current maxium is 4.
*/
#define SIL24_NPORTS2FLAG(nports) ((((unsigned)(nports) - 1) & 0x3) << 30)
#define SIL24_FLAG2NPORTS(flag) ((((flag) >> 30) & 0x3) + 1)
static struct ata_port_info sil24_port_info[] = {
/* sil_3124 */
{
.sht = &sil24_sht,
.host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
ATA_FLAG_SATA_RESET | 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 */
.port_ops = &sil24_ops,
},
/* sil_3132 */
{
.sht = &sil24_sht,
.host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
ATA_FLAG_SATA_RESET | 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 */
.port_ops = &sil24_ops,
},
/* sil_3131/sil_3531 */
{
.sht = &sil24_sht,
.host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
ATA_FLAG_SATA_RESET | 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 */
.port_ops = &sil24_ops,
},
};
static inline void sil24_update_tf(struct ata_port *ap)
{
struct sil24_port_priv *pp = ap->private_data;
void *port = (void *)ap->ioaddr.cmd_addr;
struct sil24_prb *prb = port;
ata_tf_from_fis(prb->fis, &pp->tf);
}
static u8 sil24_check_status(struct ata_port *ap)
{
struct sil24_port_priv *pp = ap->private_data;
return pp->tf.command;
}
static u8 sil24_check_err(struct ata_port *ap)
{
struct sil24_port_priv *pp = ap->private_data;
return pp->tf.feature;
}
static int sil24_scr_map[] = {
[SCR_CONTROL] = 0,
[SCR_STATUS] = 1,
[SCR_ERROR] = 2,
[SCR_ACTIVE] = 3,
};
static u32 sil24_scr_read(struct ata_port *ap, unsigned sc_reg)
{
void *scr_addr = (void *)ap->ioaddr.scr_addr;
if (sc_reg < ARRAY_SIZE(sil24_scr_map)) {
void *addr;
addr = scr_addr + sil24_scr_map[sc_reg] * 4;
return readl(scr_addr + sil24_scr_map[sc_reg] * 4);
}
return 0xffffffffU;
}
static void sil24_scr_write(struct ata_port *ap, unsigned sc_reg, u32 val)
{
void *scr_addr = (void *)ap->ioaddr.scr_addr;
if (sc_reg < ARRAY_SIZE(sil24_scr_map)) {
void *addr;
addr = scr_addr + sil24_scr_map[sc_reg] * 4;
writel(val, scr_addr + sil24_scr_map[sc_reg] * 4);
}
}
static void sil24_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
{
struct sil24_port_priv *pp = ap->private_data;
*tf = pp->tf;
}
static void sil24_phy_reset(struct ata_port *ap)
{
__sata_phy_reset(ap);
/*
* No ATAPI yet. Just unconditionally indicate ATA device.
* If ATAPI device is attached, it will fail ATA_CMD_ID_ATA
* and libata core will ignore the device.
*/
if (!(ap->flags & ATA_FLAG_PORT_DISABLED))
ap->device[0].class = ATA_DEV_ATA;
}
static inline void sil24_fill_sg(struct ata_queued_cmd *qc,
struct sil24_cmd_block *cb)
{
struct scatterlist *sg = qc->sg;
struct sil24_sge *sge = cb->sge;
unsigned i;
for (i = 0; i < qc->n_elem; i++, sg++, sge++) {
sge->addr = cpu_to_le64(sg_dma_address(sg));
sge->cnt = cpu_to_le32(sg_dma_len(sg));
sge->flags = 0;
sge->flags = i < qc->n_elem - 1 ? 0 : cpu_to_le32(SGE_TRM);
}
}
static void sil24_qc_prep(struct ata_queued_cmd *qc)
{
struct ata_port *ap = qc->ap;
struct sil24_port_priv *pp = ap->private_data;
struct sil24_cmd_block *cb = pp->cmd_block + qc->tag;
struct sil24_prb *prb = &cb->prb;
switch (qc->tf.protocol) {
case ATA_PROT_PIO:
case ATA_PROT_DMA:
case ATA_PROT_NODATA:
break;
default:
/* ATAPI isn't supported yet */
BUG();
}
ata_tf_to_fis(&qc->tf, prb->fis, 0);
if (qc->flags & ATA_QCFLAG_DMAMAP)
sil24_fill_sg(qc, cb);
}
static int sil24_qc_issue(struct ata_queued_cmd *qc)
{
struct ata_port *ap = qc->ap;
void *port = (void *)ap->ioaddr.cmd_addr;
struct sil24_port_priv *pp = ap->private_data;
dma_addr_t paddr = pp->cmd_block_dma + qc->tag * sizeof(*pp->cmd_block);
writel((u32)paddr, port + PORT_CMD_ACTIVATE);
return 0;
}
static void sil24_irq_clear(struct ata_port *ap)
{
/* unused */
}
static int __sil24_reset_controller(void *port)
{
int cnt;
u32 tmp;
/* Reset controller state. Is this correct? */
writel(PORT_CS_DEV_RST, port + PORT_CTRL_STAT);
readl(port + PORT_CTRL_STAT); /* sync */
/* Max ~100ms */
for (cnt = 0; cnt < 1000; cnt++) {
udelay(100);
tmp = readl(port + PORT_CTRL_STAT);
if (!(tmp & PORT_CS_DEV_RST))
break;
}
if (tmp & PORT_CS_DEV_RST)
return -1;
return 0;
}
static void sil24_reset_controller(struct ata_port *ap)
{
printk(KERN_NOTICE DRV_NAME
" ata%u: resetting controller...\n", ap->id);
if (__sil24_reset_controller((void *)ap->ioaddr.cmd_addr))
printk(KERN_ERR DRV_NAME
" ata%u: failed to reset controller\n", ap->id);
}
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: tiemout 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;
ata_qc_complete(qc, ATA_ERR);
sil24_reset_controller(ap);
}
static void sil24_error_intr(struct ata_port *ap, u32 slot_stat)
{
struct ata_queued_cmd *qc = ata_qc_from_tag(ap, ap->active_tag);
struct sil24_port_priv *pp = ap->private_data;
void *port = (void *)ap->ioaddr.cmd_addr;
u32 irq_stat, cmd_err, sstatus, serror;
irq_stat = readl(port + PORT_IRQ_STAT);
writel(irq_stat, port + PORT_IRQ_STAT); /* clear irq */
if (!(irq_stat & PORT_IRQ_ERROR)) {
/* ignore non-completion, non-error irqs for now */
printk(KERN_WARNING DRV_NAME
"ata%u: non-error exception irq (irq_stat %x)\n",
ap->id, irq_stat);
return;
}
cmd_err = readl(port + PORT_CMD_ERR);
sstatus = readl(port + PORT_SSTATUS);
serror = readl(port + PORT_SERROR);
if (serror)
writel(serror, port + PORT_SERROR);
printk(KERN_ERR DRV_NAME " ata%u: error interrupt on port%d\n"
" stat=0x%x irq=0x%x cmd_err=%d sstatus=0x%x serror=0x%x\n",
ap->id, ap->port_no, slot_stat, irq_stat, cmd_err, sstatus, serror);
if (cmd_err == PORT_CERR_DEV || cmd_err == PORT_CERR_SDB) {
/*
* Device is reporting error, tf registers are valid.
*/
sil24_update_tf(ap);
} else {
/*
* Other errors. libata currently doesn't have any
* mechanism to report these errors. Just turn on
* ATA_ERR.
*/
pp->tf.command = ATA_ERR;
}
if (qc)
ata_qc_complete(qc, pp->tf.command);
sil24_reset_controller(ap);
}
static inline void sil24_host_intr(struct ata_port *ap)
{
struct ata_queued_cmd *qc = ata_qc_from_tag(ap, ap->active_tag);
void *port = (void *)ap->ioaddr.cmd_addr;
u32 slot_stat;
slot_stat = readl(port + PORT_SLOT_STAT);
if (!(slot_stat & HOST_SSTAT_ATTN)) {
struct sil24_port_priv *pp = ap->private_data;
/*
* !HOST_SSAT_ATTN guarantees successful completion,
* so reading back tf registers is unnecessary for
* most commands. TODO: read tf registers for
* commands which require these values on successful
* completion (EXECUTE DEVICE DIAGNOSTIC, CHECK POWER,
* DEVICE RESET and READ PORT MULTIPLIER (any more?).
*/
sil24_update_tf(ap);
if (qc)
ata_qc_complete(qc, pp->tf.command);
} else
sil24_error_intr(ap, slot_stat);
}
static irqreturn_t sil24_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
{
struct ata_host_set *host_set = dev_instance;
struct sil24_host_priv *hpriv = host_set->private_data;
unsigned handled = 0;
u32 status;
int i;
status = readl(hpriv->host_base + HOST_IRQ_STAT);
if (status == 0xffffffff) {
printk(KERN_ERR DRV_NAME ": IRQ status == 0xffffffff, "
"PCI fault or device removal?\n");
goto out;
}
if (!(status & IRQ_STAT_4PORTS))
goto out;
spin_lock(&host_set->lock);
for (i = 0; i < host_set->n_ports; i++)
if (status & (1 << i)) {
struct ata_port *ap = host_set->ports[i];
if (ap && !(ap->flags & ATA_FLAG_PORT_DISABLED)) {
sil24_host_intr(host_set->ports[i]);
handled++;
} else
printk(KERN_ERR DRV_NAME
": interrupt from disabled port %d\n", i);
}
spin_unlock(&host_set->lock);
out:
return IRQ_RETVAL(handled);
}
static int sil24_port_start(struct ata_port *ap)
{
struct device *dev = ap->host_set->dev;
struct sil24_port_priv *pp;
struct sil24_cmd_block *cb;
size_t cb_size = sizeof(*cb);
dma_addr_t cb_dma;
pp = kmalloc(sizeof(*pp), GFP_KERNEL);
if (!pp)
return -ENOMEM;
memset(pp, 0, sizeof(*pp));
pp->tf.command = ATA_DRDY;
cb = dma_alloc_coherent(dev, cb_size, &cb_dma, GFP_KERNEL);
if (!cb) {
kfree(pp);
return -ENOMEM;
}
memset(cb, 0, cb_size);
pp->cmd_block = cb;
pp->cmd_block_dma = cb_dma;
ap->private_data = pp;
return 0;
}
static void sil24_port_stop(struct ata_port *ap)
{
struct device *dev = ap->host_set->dev;
struct sil24_port_priv *pp = ap->private_data;
size_t cb_size = sizeof(*pp->cmd_block);
dma_free_coherent(dev, cb_size, pp->cmd_block, pp->cmd_block_dma);
kfree(pp);
}
static void sil24_host_stop(struct ata_host_set *host_set)
{
struct sil24_host_priv *hpriv = host_set->private_data;
iounmap(hpriv->host_base);
iounmap(hpriv->port_base);
kfree(hpriv);
}
static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
{
static int printed_version = 0;
unsigned int board_id = (unsigned int)ent->driver_data;
struct ata_port_info *pinfo = &sil24_port_info[board_id];
struct ata_probe_ent *probe_ent = NULL;
struct sil24_host_priv *hpriv = NULL;
void *host_base = NULL, *port_base = NULL;
int i, rc;
if (!printed_version++)
printk(KERN_DEBUG DRV_NAME " version " DRV_VERSION "\n");
rc = pci_enable_device(pdev);
if (rc)
return rc;
rc = pci_request_regions(pdev, DRV_NAME);
if (rc)
goto out_disable;
rc = -ENOMEM;
/* ioremap mmio registers */
host_base = ioremap(pci_resource_start(pdev, 0),
pci_resource_len(pdev, 0));
if (!host_base)
goto out_free;
port_base = ioremap(pci_resource_start(pdev, 2),
pci_resource_len(pdev, 2));
if (!port_base)
goto out_free;
/* allocate & init probe_ent and hpriv */
probe_ent = kmalloc(sizeof(*probe_ent), GFP_KERNEL);
if (!probe_ent)
goto out_free;
hpriv = kmalloc(sizeof(*hpriv), GFP_KERNEL);
if (!hpriv)
goto out_free;
memset(probe_ent, 0, sizeof(*probe_ent));
probe_ent->dev = pci_dev_to_dev(pdev);
INIT_LIST_HEAD(&probe_ent->node);
probe_ent->sht = pinfo->sht;
probe_ent->host_flags = pinfo->host_flags;
probe_ent->pio_mask = pinfo->pio_mask;
probe_ent->udma_mask = pinfo->udma_mask;
probe_ent->port_ops = pinfo->port_ops;
probe_ent->n_ports = SIL24_FLAG2NPORTS(pinfo->host_flags);
probe_ent->irq = pdev->irq;
probe_ent->irq_flags = SA_SHIRQ;
probe_ent->mmio_base = port_base;
probe_ent->private_data = hpriv;
memset(hpriv, 0, sizeof(*hpriv));
hpriv->host_base = host_base;
hpriv->port_base = port_base;
/*
* Configure the device
*/
/*
* FIXME: This device is certainly 64-bit capable. We just
* don't know how to use it. After fixing 32bit activation in
* this function, enable 64bit masks here.
*/
rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
if (rc) {
printk(KERN_ERR DRV_NAME "(%s): 32-bit DMA enable failed\n",
pci_name(pdev));
goto out_free;
}
rc = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
if (rc) {
printk(KERN_ERR DRV_NAME "(%s): 32-bit consistent DMA enable failed\n",
pci_name(pdev));
goto out_free;
}
/* GPIO off */
writel(0, host_base + HOST_FLASH_CMD);
/* Mask interrupts during initialization */
writel(0, host_base + HOST_CTRL);
for (i = 0; i < probe_ent->n_ports; i++) {
void *port = port_base + i * PORT_REGS_SIZE;
unsigned long portu = (unsigned long)port;
u32 tmp;
int cnt;
probe_ent->port[i].cmd_addr = portu + PORT_PRB;
probe_ent->port[i].scr_addr = portu + PORT_SCONTROL;
ata_std_ports(&probe_ent->port[i]);
/* Initial PHY setting */
writel(0x20c, port + PORT_PHY_CFG);
/* Clear port RST */
tmp = readl(port + PORT_CTRL_STAT);
if (tmp & PORT_CS_PORT_RST) {
writel(PORT_CS_PORT_RST, port + PORT_CTRL_CLR);
readl(port + PORT_CTRL_STAT); /* sync */
for (cnt = 0; cnt < 10; cnt++) {
msleep(10);
tmp = readl(port + PORT_CTRL_STAT);
if (!(tmp & PORT_CS_PORT_RST))
break;
}
if (tmp & PORT_CS_PORT_RST)
printk(KERN_ERR DRV_NAME
"(%s): failed to clear port RST\n",
pci_name(pdev));
}
/* Zero error counters. */
writel(0x8000, port + PORT_DECODE_ERR_THRESH);
writel(0x8000, port + PORT_CRC_ERR_THRESH);
writel(0x8000, port + PORT_HSHK_ERR_THRESH);
writel(0x0000, port + PORT_DECODE_ERR_CNT);
writel(0x0000, port + PORT_CRC_ERR_CNT);
writel(0x0000, port + PORT_HSHK_ERR_CNT);
/* FIXME: 32bit activation? */
writel(0, port + PORT_ACTIVATE_UPPER_ADDR);
writel(PORT_CS_32BIT_ACTV, port + PORT_CTRL_STAT);
/* Configure interrupts */
writel(0xffff, port + PORT_IRQ_ENABLE_CLR);
writel(PORT_IRQ_COMPLETE | PORT_IRQ_ERROR | PORT_IRQ_SDB_FIS,
port + PORT_IRQ_ENABLE_SET);
/* Clear interrupts */
writel(0x0fff0fff, port + PORT_IRQ_STAT);
writel(PORT_CS_IRQ_WOC, port + PORT_CTRL_CLR);
/* Clear port multiplier enable and resume bits */
writel(PORT_CS_PM_EN | PORT_CS_RESUME, port + PORT_CTRL_CLR);
/* Reset itself */
if (__sil24_reset_controller(port))
printk(KERN_ERR DRV_NAME
"(%s): failed to reset controller\n",
pci_name(pdev));
}
/* Turn on interrupts */
writel(IRQ_STAT_4PORTS, host_base + HOST_CTRL);
pci_set_master(pdev);
/* FIXME: check ata_device_add return value */
ata_device_add(probe_ent);
kfree(probe_ent);
return 0;
out_free:
if (host_base)
iounmap(host_base);
if (port_base)
iounmap(port_base);
kfree(probe_ent);
kfree(hpriv);
pci_release_regions(pdev);
out_disable:
pci_disable_device(pdev);
return rc;
}
static int __init sil24_init(void)
{
return pci_module_init(&sil24_pci_driver);
}
static void __exit sil24_exit(void)
{
pci_unregister_driver(&sil24_pci_driver);
}
MODULE_AUTHOR("Tejun Heo");
MODULE_DESCRIPTION("Silicon Image 3124/3132 SATA low-level driver");
MODULE_LICENSE("GPL");
MODULE_DEVICE_TABLE(pci, sil24_pci_tbl);
module_init(sil24_init);
module_exit(sil24_exit);

View File

@ -102,7 +102,7 @@ static Scsi_Host_Template sis_sht = {
.ordered_flush = 1,
};
static struct ata_port_operations sis_ops = {
static const struct ata_port_operations sis_ops = {
.port_disable = ata_port_disable,
.tf_load = ata_tf_load,
.tf_read = ata_tf_read,
@ -263,7 +263,7 @@ static int sis_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
goto err_out_regions;
ppi = &sis_port_info;
probe_ent = ata_pci_init_native_mode(pdev, &ppi);
probe_ent = ata_pci_init_native_mode(pdev, &ppi, ATA_PORT_PRIMARY | ATA_PORT_SECONDARY);
if (!probe_ent) {
rc = -ENOMEM;
goto err_out_regions;

View File

@ -102,7 +102,7 @@ static void k2_sata_scr_write (struct ata_port *ap, unsigned int sc_reg,
}
static void k2_sata_tf_load(struct ata_port *ap, struct ata_taskfile *tf)
static void k2_sata_tf_load(struct ata_port *ap, const struct ata_taskfile *tf)
{
struct ata_ioports *ioaddr = &ap->ioaddr;
unsigned int is_addr = tf->flags & ATA_TFLAG_ISADDR;
@ -297,7 +297,7 @@ static Scsi_Host_Template k2_sata_sht = {
};
static struct ata_port_operations k2_sata_ops = {
static const struct ata_port_operations k2_sata_ops = {
.port_disable = ata_port_disable,
.tf_load = k2_sata_tf_load,
.tf_read = k2_sata_tf_read,

View File

@ -137,7 +137,7 @@ struct pdc_port_priv {
};
struct pdc_host_priv {
void *dimm_mmio;
void __iomem *dimm_mmio;
unsigned int doing_hdma;
unsigned int hdma_prod;
@ -157,8 +157,8 @@ static void pdc_20621_phy_reset (struct ata_port *ap);
static int pdc_port_start(struct ata_port *ap);
static void pdc_port_stop(struct ata_port *ap);
static void pdc20621_qc_prep(struct ata_queued_cmd *qc);
static void pdc_tf_load_mmio(struct ata_port *ap, struct ata_taskfile *tf);
static void pdc_exec_command_mmio(struct ata_port *ap, struct ata_taskfile *tf);
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 pdc20621_host_stop(struct ata_host_set *host_set);
static unsigned int pdc20621_dimm_init(struct ata_probe_ent *pe);
static int pdc20621_detect_dimm(struct ata_probe_ent *pe);
@ -196,7 +196,7 @@ static Scsi_Host_Template pdc_sata_sht = {
.ordered_flush = 1,
};
static struct ata_port_operations pdc_20621_ops = {
static const struct ata_port_operations pdc_20621_ops = {
.port_disable = ata_port_disable,
.tf_load = pdc_tf_load_mmio,
.tf_read = ata_tf_read,
@ -247,7 +247,7 @@ static void pdc20621_host_stop(struct ata_host_set *host_set)
{
struct pci_dev *pdev = to_pci_dev(host_set->dev);
struct pdc_host_priv *hpriv = host_set->private_data;
void *dimm_mmio = hpriv->dimm_mmio;
void __iomem *dimm_mmio = hpriv->dimm_mmio;
pci_iounmap(pdev, dimm_mmio);
kfree(hpriv);
@ -669,8 +669,8 @@ static void pdc20621_packet_start(struct ata_queued_cmd *qc)
readl(mmio + PDC_20621_SEQCTL + (seq * 4)); /* flush */
writel(port_ofs + PDC_DIMM_ATA_PKT,
(void *) ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT);
readl((void *) ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT);
(void __iomem *) ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT);
readl((void __iomem *) ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT);
VPRINTK("submitted ofs 0x%x (%u), seq %u\n",
port_ofs + PDC_DIMM_ATA_PKT,
port_ofs + PDC_DIMM_ATA_PKT,
@ -747,8 +747,8 @@ static inline unsigned int pdc20621_host_intr( struct ata_port *ap,
writel(0x00000001, mmio + PDC_20621_SEQCTL + (seq * 4));
readl(mmio + PDC_20621_SEQCTL + (seq * 4));
writel(port_ofs + PDC_DIMM_ATA_PKT,
(void *) ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT);
readl((void *) ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT);
(void __iomem *) ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT);
readl((void __iomem *) ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT);
}
/* step two - execute ATA command */
@ -899,7 +899,7 @@ out:
DPRINTK("EXIT\n");
}
static void pdc_tf_load_mmio(struct ata_port *ap, struct ata_taskfile *tf)
static void pdc_tf_load_mmio(struct ata_port *ap, const struct ata_taskfile *tf)
{
WARN_ON (tf->protocol == ATA_PROT_DMA ||
tf->protocol == ATA_PROT_NODATA);
@ -907,7 +907,7 @@ static void pdc_tf_load_mmio(struct ata_port *ap, struct ata_taskfile *tf)
}
static void pdc_exec_command_mmio(struct ata_port *ap, struct ata_taskfile *tf)
static void pdc_exec_command_mmio(struct ata_port *ap, const struct ata_taskfile *tf)
{
WARN_ON (tf->protocol == ATA_PROT_DMA ||
tf->protocol == ATA_PROT_NODATA);
@ -1014,7 +1014,7 @@ static void pdc20621_put_to_dimm(struct ata_probe_ent *pe, void *psource,
idx++;
dist = ((long)(s32)(window_size - (offset + size))) >= 0 ? size :
(long) (window_size - offset);
memcpy_toio((char *) (dimm_mmio + offset / 4), (char *) psource, dist);
memcpy_toio(dimm_mmio + offset / 4, psource, dist);
writel(0x01, mmio + PDC_GENERAL_CTLR);
readl(mmio + PDC_GENERAL_CTLR);
@ -1023,8 +1023,7 @@ static void pdc20621_put_to_dimm(struct ata_probe_ent *pe, void *psource,
for (; (long) size >= (long) window_size ;) {
writel(((idx) << page_mask), mmio + PDC_DIMM_WINDOW_CTLR);
readl(mmio + PDC_DIMM_WINDOW_CTLR);
memcpy_toio((char *) (dimm_mmio), (char *) psource,
window_size / 4);
memcpy_toio(dimm_mmio, psource, window_size / 4);
writel(0x01, mmio + PDC_GENERAL_CTLR);
readl(mmio + PDC_GENERAL_CTLR);
psource += window_size;
@ -1035,7 +1034,7 @@ static void pdc20621_put_to_dimm(struct ata_probe_ent *pe, void *psource,
if (size) {
writel(((idx) << page_mask), mmio + PDC_DIMM_WINDOW_CTLR);
readl(mmio + PDC_DIMM_WINDOW_CTLR);
memcpy_toio((char *) (dimm_mmio), (char *) psource, size / 4);
memcpy_toio(dimm_mmio, psource, size / 4);
writel(0x01, mmio + PDC_GENERAL_CTLR);
readl(mmio + PDC_GENERAL_CTLR);
}

View File

@ -90,7 +90,7 @@ static Scsi_Host_Template uli_sht = {
.ordered_flush = 1,
};
static struct ata_port_operations uli_ops = {
static const struct ata_port_operations uli_ops = {
.port_disable = ata_port_disable,
.tf_load = ata_tf_load,
@ -202,7 +202,7 @@ static int uli_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
goto err_out_regions;
ppi = &uli_port_info;
probe_ent = ata_pci_init_native_mode(pdev, &ppi);
probe_ent = ata_pci_init_native_mode(pdev, &ppi, ATA_PORT_PRIMARY | ATA_PORT_SECONDARY);
if (!probe_ent) {
rc = -ENOMEM;
goto err_out_regions;

View File

@ -109,7 +109,7 @@ static Scsi_Host_Template svia_sht = {
.ordered_flush = 1,
};
static struct ata_port_operations svia_sata_ops = {
static const struct ata_port_operations svia_sata_ops = {
.port_disable = ata_port_disable,
.tf_load = ata_tf_load,
@ -212,7 +212,7 @@ static struct ata_probe_ent *vt6420_init_probe_ent(struct pci_dev *pdev)
struct ata_probe_ent *probe_ent;
struct ata_port_info *ppi = &svia_port_info;
probe_ent = ata_pci_init_native_mode(pdev, &ppi);
probe_ent = ata_pci_init_native_mode(pdev, &ppi, ATA_PORT_PRIMARY | ATA_PORT_SECONDARY);
if (!probe_ent)
return NULL;

View File

@ -86,7 +86,7 @@ static u32 vsc_sata_scr_read (struct ata_port *ap, unsigned int sc_reg)
{
if (sc_reg > SCR_CONTROL)
return 0xffffffffU;
return readl((void *) ap->ioaddr.scr_addr + (sc_reg * 4));
return readl((void __iomem *) ap->ioaddr.scr_addr + (sc_reg * 4));
}
@ -95,16 +95,16 @@ static void vsc_sata_scr_write (struct ata_port *ap, unsigned int sc_reg,
{
if (sc_reg > SCR_CONTROL)
return;
writel(val, (void *) ap->ioaddr.scr_addr + (sc_reg * 4));
writel(val, (void __iomem *) ap->ioaddr.scr_addr + (sc_reg * 4));
}
static void vsc_intr_mask_update(struct ata_port *ap, u8 ctl)
{
unsigned long mask_addr;
void __iomem *mask_addr;
u8 mask;
mask_addr = (unsigned long) ap->host_set->mmio_base +
mask_addr = ap->host_set->mmio_base +
VSC_SATA_INT_MASK_OFFSET + ap->port_no;
mask = readb(mask_addr);
if (ctl & ATA_NIEN)
@ -115,7 +115,7 @@ static void vsc_intr_mask_update(struct ata_port *ap, u8 ctl)
}
static void vsc_sata_tf_load(struct ata_port *ap, struct ata_taskfile *tf)
static void vsc_sata_tf_load(struct ata_port *ap, const struct ata_taskfile *tf)
{
struct ata_ioports *ioaddr = &ap->ioaddr;
unsigned int is_addr = tf->flags & ATA_TFLAG_ISADDR;
@ -231,7 +231,7 @@ static Scsi_Host_Template vsc_sata_sht = {
};
static struct ata_port_operations vsc_sata_ops = {
static const struct ata_port_operations vsc_sata_ops = {
.port_disable = ata_port_disable,
.tf_load = vsc_sata_tf_load,
.tf_read = vsc_sata_tf_read,
@ -283,7 +283,7 @@ static int __devinit vsc_sata_init_one (struct pci_dev *pdev, const struct pci_d
struct ata_probe_ent *probe_ent = NULL;
unsigned long base;
int pci_dev_busy = 0;
void *mmio_base;
void __iomem *mmio_base;
int rc;
if (!printed_version++)

View File

@ -42,13 +42,18 @@ enum {
ATA_SECT_SIZE = 512,
ATA_ID_WORDS = 256,
ATA_ID_PROD_OFS = 27,
ATA_ID_FW_REV_OFS = 23,
ATA_ID_SERNO_OFS = 10,
ATA_ID_MAJOR_VER = 80,
ATA_ID_PIO_MODES = 64,
ATA_ID_FW_REV_OFS = 23,
ATA_ID_PROD_OFS = 27,
ATA_ID_OLD_PIO_MODES = 51,
ATA_ID_FIELD_VALID = 53,
ATA_ID_MWDMA_MODES = 63,
ATA_ID_PIO_MODES = 64,
ATA_ID_EIDE_DMA_MIN = 65,
ATA_ID_EIDE_PIO = 67,
ATA_ID_EIDE_PIO_IORDY = 68,
ATA_ID_UDMA_MODES = 88,
ATA_ID_MAJOR_VER = 80,
ATA_ID_PIO4 = (1 << 1),
ATA_PCI_CTL_OFS = 2,
@ -128,10 +133,15 @@ enum {
ATA_CMD_PIO_READ_EXT = 0x24,
ATA_CMD_PIO_WRITE = 0x30,
ATA_CMD_PIO_WRITE_EXT = 0x34,
ATA_CMD_READ_MULTI = 0xC4,
ATA_CMD_READ_MULTI_EXT = 0x29,
ATA_CMD_WRITE_MULTI = 0xC5,
ATA_CMD_WRITE_MULTI_EXT = 0x39,
ATA_CMD_SET_FEATURES = 0xEF,
ATA_CMD_PACKET = 0xA0,
ATA_CMD_VERIFY = 0x40,
ATA_CMD_VERIFY_EXT = 0x42,
ATA_CMD_INIT_DEV_PARAMS = 0x91,
/* SETFEATURES stuff */
SETFEATURES_XFER = 0x03,
@ -146,14 +156,14 @@ enum {
XFER_MW_DMA_2 = 0x22,
XFER_MW_DMA_1 = 0x21,
XFER_MW_DMA_0 = 0x20,
XFER_SW_DMA_2 = 0x12,
XFER_SW_DMA_1 = 0x11,
XFER_SW_DMA_0 = 0x10,
XFER_PIO_4 = 0x0C,
XFER_PIO_3 = 0x0B,
XFER_PIO_2 = 0x0A,
XFER_PIO_1 = 0x09,
XFER_PIO_0 = 0x08,
XFER_SW_DMA_2 = 0x12,
XFER_SW_DMA_1 = 0x11,
XFER_SW_DMA_0 = 0x10,
XFER_PIO_SLOW = 0x00,
/* ATAPI stuff */
@ -181,6 +191,7 @@ enum {
ATA_TFLAG_ISADDR = (1 << 1), /* enable r/w to nsect/lba regs */
ATA_TFLAG_DEVICE = (1 << 2), /* enable r/w to device reg */
ATA_TFLAG_WRITE = (1 << 3), /* data dir: host->dev==1 (write) */
ATA_TFLAG_LBA = (1 << 4), /* enable LBA */
};
enum ata_tf_protocols {
@ -250,7 +261,19 @@ struct ata_taskfile {
((u64) (id)[(n) + 1] << 16) | \
((u64) (id)[(n) + 0]) )
static inline int atapi_cdb_len(u16 *dev_id)
static inline int ata_id_current_chs_valid(const u16 *id)
{
/* For ATA-1 devices, if the INITIALIZE DEVICE PARAMETERS command
has not been issued to the device then the values of
id[54] to id[56] are vendor specific. */
return (id[53] & 0x01) && /* Current translation valid */
id[54] && /* cylinders in current translation */
id[55] && /* heads in current translation */
id[55] <= 16 &&
id[56]; /* sectors in current translation */
}
static inline int atapi_cdb_len(const u16 *dev_id)
{
u16 tmp = dev_id[0] & 0x3;
switch (tmp) {
@ -260,7 +283,7 @@ static inline int atapi_cdb_len(u16 *dev_id)
}
}
static inline int is_atapi_taskfile(struct ata_taskfile *tf)
static inline int is_atapi_taskfile(const struct ata_taskfile *tf)
{
return (tf->protocol == ATA_PROT_ATAPI) ||
(tf->protocol == ATA_PROT_ATAPI_NODATA) ||

View File

@ -91,12 +91,13 @@ enum {
ATA_SHT_EMULATED = 1,
ATA_SHT_CMD_PER_LUN = 1,
ATA_SHT_THIS_ID = -1,
ATA_SHT_USE_CLUSTERING = 0,
ATA_SHT_USE_CLUSTERING = 1,
/* 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_DEV_UNKNOWN = 0, /* unknown device */
ATA_DEV_ATA = 1, /* ATA device */
@ -154,17 +155,21 @@ enum {
ATA_SHIFT_UDMA = 0,
ATA_SHIFT_MWDMA = 8,
ATA_SHIFT_PIO = 11,
/* Masks for port functions */
ATA_PORT_PRIMARY = (1 << 0),
ATA_PORT_SECONDARY = (1 << 1),
};
enum pio_task_states {
PIO_ST_UNKNOWN,
PIO_ST_IDLE,
PIO_ST_POLL,
PIO_ST_TMOUT,
PIO_ST,
PIO_ST_LAST,
PIO_ST_LAST_POLL,
PIO_ST_ERR,
enum hsm_task_states {
HSM_ST_UNKNOWN,
HSM_ST_IDLE,
HSM_ST_POLL,
HSM_ST_TMOUT,
HSM_ST,
HSM_ST_LAST,
HSM_ST_LAST_POLL,
HSM_ST_ERR,
};
/* forward declarations */
@ -197,7 +202,7 @@ struct ata_ioports {
struct ata_probe_ent {
struct list_head node;
struct device *dev;
struct ata_port_operations *port_ops;
const struct ata_port_operations *port_ops;
Scsi_Host_Template *sht;
struct ata_ioports port[ATA_MAX_PORTS];
unsigned int n_ports;
@ -220,7 +225,7 @@ struct ata_host_set {
void __iomem *mmio_base;
unsigned int n_ports;
void *private_data;
struct ata_port_operations *ops;
const struct ata_port_operations *ops;
struct ata_port * ports[0];
};
@ -278,15 +283,18 @@ struct ata_device {
u8 xfer_mode;
unsigned int xfer_shift; /* ATA_SHIFT_xxx */
/* cache info about current transfer mode */
u8 xfer_protocol; /* taskfile xfer protocol */
u8 read_cmd; /* opcode to use on read */
u8 write_cmd; /* opcode to use on write */
unsigned int multi_count; /* sectors count for
READ/WRITE MULTIPLE */
/* for CHS addressing */
u16 cylinders; /* Number of cylinders */
u16 heads; /* Number of heads */
u16 sectors; /* Number of sectors per track */
};
struct ata_port {
struct Scsi_Host *host; /* our co-allocated scsi host */
struct ata_port_operations *ops;
const struct ata_port_operations *ops;
unsigned long flags; /* ATA_FLAG_xxx */
unsigned int id; /* unique id req'd by scsi midlyr */
unsigned int port_no; /* unique port #; from zero */
@ -319,7 +327,7 @@ struct ata_port {
struct work_struct packet_task;
struct work_struct pio_task;
unsigned int pio_task_state;
unsigned int hsm_task_state;
unsigned long pio_task_timeout;
void *private_data;
@ -333,10 +341,10 @@ struct ata_port_operations {
void (*set_piomode) (struct ata_port *, struct ata_device *);
void (*set_dmamode) (struct ata_port *, struct ata_device *);
void (*tf_load) (struct ata_port *ap, struct ata_taskfile *tf);
void (*tf_load) (struct ata_port *ap, const struct ata_taskfile *tf);
void (*tf_read) (struct ata_port *ap, struct ata_taskfile *tf);
void (*exec_command)(struct ata_port *ap, struct ata_taskfile *tf);
void (*exec_command)(struct ata_port *ap, const struct ata_taskfile *tf);
u8 (*check_status)(struct ata_port *ap);
u8 (*check_altstatus)(struct ata_port *ap);
u8 (*check_err)(struct ata_port *ap);
@ -377,9 +385,22 @@ struct ata_port_info {
unsigned long pio_mask;
unsigned long mwdma_mask;
unsigned long udma_mask;
struct ata_port_operations *port_ops;
const struct ata_port_operations *port_ops;
};
struct ata_timing {
unsigned short mode; /* ATA mode */
unsigned short setup; /* t1 */
unsigned short act8b; /* t2 for 8-bit I/O */
unsigned short rec8b; /* t2i for 8-bit I/O */
unsigned short cyc8b; /* t0 for 8-bit I/O */
unsigned short active; /* t2 or tD */
unsigned short recover; /* t2i or tK */
unsigned short cycle; /* t0 */
unsigned short udma; /* t2CYCTYP/2 */
};
#define FIT(v,vmin,vmax) max_t(short,min_t(short,v,vmax),vmin)
extern void ata_port_probe(struct ata_port *);
extern void __sata_phy_reset(struct ata_port *ap);
@ -392,7 +413,7 @@ extern int ata_pci_init_one (struct pci_dev *pdev, struct ata_port_info **port_i
unsigned int n_ports);
extern void ata_pci_remove_one (struct pci_dev *pdev);
#endif /* CONFIG_PCI */
extern int ata_device_add(struct ata_probe_ent *ent);
extern int ata_device_add(const struct ata_probe_ent *ent);
extern void ata_host_set_remove(struct ata_host_set *host_set);
extern int ata_scsi_detect(Scsi_Host_Template *sht);
extern int ata_scsi_ioctl(struct scsi_device *dev, int cmd, void __user *arg);
@ -400,19 +421,21 @@ extern int ata_scsi_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmn
extern int ata_scsi_error(struct Scsi_Host *host);
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_ratelimit(void);
/*
* Default driver ops implementations
*/
extern void ata_tf_load(struct ata_port *ap, struct ata_taskfile *tf);
extern void ata_tf_load(struct ata_port *ap, const struct ata_taskfile *tf);
extern void ata_tf_read(struct ata_port *ap, struct ata_taskfile *tf);
extern void ata_tf_to_fis(struct ata_taskfile *tf, u8 *fis, u8 pmp);
extern void ata_tf_from_fis(u8 *fis, struct ata_taskfile *tf);
extern void ata_tf_to_fis(const struct ata_taskfile *tf, u8 *fis, u8 pmp);
extern void ata_tf_from_fis(const u8 *fis, struct ata_taskfile *tf);
extern void ata_noop_dev_select (struct ata_port *ap, unsigned int device);
extern void ata_std_dev_select (struct ata_port *ap, unsigned int device);
extern u8 ata_check_status(struct ata_port *ap);
extern u8 ata_altstatus(struct ata_port *ap);
extern u8 ata_chk_err(struct ata_port *ap);
extern void ata_exec_command(struct ata_port *ap, struct ata_taskfile *tf);
extern void ata_exec_command(struct ata_port *ap, const struct ata_taskfile *tf);
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);
@ -423,8 +446,8 @@ 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(struct ata_taskfile *tf);
extern void ata_dev_id_string(u16 *id, unsigned char *s,
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_bmdma_setup (struct ata_queued_cmd *qc);
@ -441,6 +464,32 @@ extern int ata_std_bios_param(struct scsi_device *sdev,
sector_t capacity, int geom[]);
extern int ata_scsi_slave_config(struct scsi_device *sdev);
/*
* Timing helpers
*/
extern int ata_timing_compute(struct ata_device *, unsigned short,
struct ata_timing *, int, int);
extern void ata_timing_merge(const struct ata_timing *,
const struct ata_timing *, struct ata_timing *,
unsigned int);
enum {
ATA_TIMING_SETUP = (1 << 0),
ATA_TIMING_ACT8B = (1 << 1),
ATA_TIMING_REC8B = (1 << 2),
ATA_TIMING_CYC8B = (1 << 3),
ATA_TIMING_8BIT = ATA_TIMING_ACT8B | ATA_TIMING_REC8B |
ATA_TIMING_CYC8B,
ATA_TIMING_ACTIVE = (1 << 4),
ATA_TIMING_RECOVER = (1 << 5),
ATA_TIMING_CYCLE = (1 << 6),
ATA_TIMING_UDMA = (1 << 7),
ATA_TIMING_ALL = ATA_TIMING_SETUP | ATA_TIMING_ACT8B |
ATA_TIMING_REC8B | ATA_TIMING_CYC8B |
ATA_TIMING_ACTIVE | ATA_TIMING_RECOVER |
ATA_TIMING_CYCLE | ATA_TIMING_UDMA,
};
#ifdef CONFIG_PCI
struct pci_bits {
@ -452,8 +501,8 @@ struct pci_bits {
extern void ata_pci_host_stop (struct ata_host_set *host_set);
extern struct ata_probe_ent *
ata_pci_init_native_mode(struct pci_dev *pdev, struct ata_port_info **port);
extern int pci_test_config_bits(struct pci_dev *pdev, struct pci_bits *bits);
ata_pci_init_native_mode(struct pci_dev *pdev, struct ata_port_info **port, int portmask);
extern int pci_test_config_bits(struct pci_dev *pdev, const struct pci_bits *bits);
#endif /* CONFIG_PCI */
@ -463,7 +512,7 @@ static inline unsigned int ata_tag_valid(unsigned int tag)
return (tag < ATA_MAX_QUEUE) ? 1 : 0;
}
static inline unsigned int ata_dev_present(struct ata_device *dev)
static inline unsigned int ata_dev_present(const struct ata_device *dev)
{
return ((dev->class == ATA_DEV_ATA) ||
(dev->class == ATA_DEV_ATAPI));
@ -662,7 +711,7 @@ static inline unsigned int sata_dev_present(struct ata_port *ap)
return ((scr_read(ap, SCR_STATUS) & 0xf) == 0x3) ? 1 : 0;
}
static inline int ata_try_flush_cache(struct ata_device *dev)
static inline int ata_try_flush_cache(const struct ata_device *dev)
{
return ata_id_wcache_enabled(dev->id) ||
ata_id_has_flush(dev->id) ||