Merge branch 'upstream' of master.kernel.org:/pub/scm/linux/kernel/git/jgarzik/libata-dev
This commit is contained in:
Коммит
5fadd053d9
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -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
|
||||
|
|
|
@ -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/
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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,
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -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__ */
|
||||
|
|
|
@ -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);
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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++)
|
||||
|
|
|
@ -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) ||
|
||||
|
|
|
@ -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) ||
|
||||
|
|
Загрузка…
Ссылка в новой задаче